4 * This file contains C command functions for a bunch of additional Tcl
5 * commands that are used for testing out Tcl's C interfaces. These
6 * commands are not normally included in Tcl applications; they're only
9 * Copyright (c) 1993-1994 The Regents of the University of California.
10 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11 * Copyright (c) 1998-1999 by Scriptics Corporation.
13 * See the file "license.terms" for information on usage and redistribution of
14 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
19 # define USE_TCL_STUBS
31 #if defined(MAC_OSX_TK)
32 #include "tkMacOSXInt.h"
33 #include "tkScrollbar.h"
34 #define LOG_DISPLAY(drawable) TkTestLogDisplay(drawable)
36 #define LOG_DISPLAY(drawable) 1
40 #include "tkUnixInt.h"
44 * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the
45 * Tcltest_Init declaration is in the source file itself, which is only
46 * accessed when we are building a library.
49 #undef TCL_STORAGE_CLASS
50 #define TCL_STORAGE_CLASS DLLEXPORT
51 EXTERN int Tktest_Init(Tcl_Interp *interp);
53 * The following data structure represents the model for a test image:
56 typedef struct TImageModel {
57 Tk_ImageModel model; /* Tk's token for image model. */
58 Tcl_Interp *interp; /* Interpreter for application. */
59 int width, height; /* Dimensions of image. */
60 char *imageName; /* Name of image (malloc-ed). */
61 char *varName; /* Name of variable in which to log events for
62 * image (malloc-ed). */
66 * The following data structure represents a particular use of a particular
70 typedef struct TImageInstance {
71 TImageModel *modelPtr; /* Pointer to model for image. */
72 XColor *fg; /* Foreground color for drawing in image. */
73 GC gc; /* Graphics context for drawing in image. */
74 Bool displayFailed; /* macOS display attempted out of drawRect. */
75 char buffer[200 + TCL_INTEGER_SPACE * 6]; /* message to log on display. */
79 * The type record for test images:
82 static int ImageCreate(Tcl_Interp *interp,
83 const char *name, int argc, Tcl_Obj *const objv[],
84 const Tk_ImageType *typePtr, Tk_ImageModel model,
85 ClientData *clientDataPtr);
86 static ClientData ImageGet(Tk_Window tkwin, ClientData clientData);
87 static void ImageDisplay(ClientData clientData,
88 Display *display, Drawable drawable,
89 int imageX, int imageY, int width,
90 int height, int drawableX,
92 static void ImageFree(ClientData clientData, Display *display);
93 static void ImageDelete(ClientData clientData);
95 static Tk_ImageType imageType = {
97 ImageCreate, /* createProc */
98 ImageGet, /* getProc */
99 ImageDisplay, /* displayProc */
100 ImageFree, /* freeProc */
101 ImageDelete, /* deleteProc */
102 NULL, /* postscriptPtr */
108 * One of the following structures describes each of the interpreters created
109 * by the "testnewapp" command. This information is used by the
110 * "testdeleteinterps" command to destroy all of those interpreters.
113 typedef struct NewApp {
114 Tcl_Interp *interp; /* Token for interpreter. */
115 struct NewApp *nextPtr; /* Next in list of new interpreters. */
118 static NewApp *newAppPtr = NULL;/* First in list of all new interpreters. */
121 * Header for trivial configuration command items.
124 #define ODD TK_CONFIG_USER_BIT
125 #define EVEN (TK_CONFIG_USER_BIT << 1)
133 typedef struct TrivialCommandHeader {
134 Tcl_Interp *interp; /* The interp that this command lives in. */
135 Tk_OptionTable optionTable; /* The option table that go with this
137 Tk_Window tkwin; /* For widgets, the window associated with
139 Tcl_Command widgetCmd; /* For widgets, the command associated with
141 } TrivialCommandHeader;
144 * Forward declarations for functions defined later in this file:
147 static int ImageObjCmd(ClientData dummy,
148 Tcl_Interp *interp, int objc,
149 Tcl_Obj * const objv[]);
150 static int TestbitmapObjCmd(ClientData dummy,
151 Tcl_Interp *interp, int objc,
152 Tcl_Obj * const objv[]);
153 static int TestborderObjCmd(ClientData dummy,
154 Tcl_Interp *interp, int objc,
155 Tcl_Obj * const objv[]);
156 static int TestcolorObjCmd(ClientData dummy,
157 Tcl_Interp *interp, int objc,
158 Tcl_Obj * const objv[]);
159 static int TestcursorObjCmd(ClientData dummy,
160 Tcl_Interp *interp, int objc,
161 Tcl_Obj * const objv[]);
162 static int TestdeleteappsObjCmd(ClientData dummy,
163 Tcl_Interp *interp, int objc,
164 Tcl_Obj * const objv[]);
165 static int TestfontObjCmd(ClientData dummy,
166 Tcl_Interp *interp, int objc,
167 Tcl_Obj *const objv[]);
168 static int TestmakeexistObjCmd(ClientData dummy,
169 Tcl_Interp *interp, int objc,
170 Tcl_Obj *const objv[]);
171 #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
172 static int TestmenubarObjCmd(ClientData dummy,
173 Tcl_Interp *interp, int objc,
174 Tcl_Obj *const objv[]);
177 static int TestmetricsObjCmd(ClientData dummy,
178 Tcl_Interp *interp, int objc,
179 Tcl_Obj * const objv[]);
181 static int TestobjconfigObjCmd(ClientData dummy,
182 Tcl_Interp *interp, int objc,
183 Tcl_Obj * const objv[]);
184 static int CustomOptionSet(ClientData clientData,
185 Tcl_Interp *interp, Tk_Window tkwin,
186 Tcl_Obj **value, char *recordPtr,
187 int internalOffset, char *saveInternalPtr,
189 static Tcl_Obj * CustomOptionGet(ClientData clientData,
190 Tk_Window tkwin, char *recordPtr,
192 static void CustomOptionRestore(ClientData clientData,
193 Tk_Window tkwin, char *internalPtr,
194 char *saveInternalPtr);
195 static void CustomOptionFree(ClientData clientData,
196 Tk_Window tkwin, char *internalPtr);
197 static int TestpropObjCmd(ClientData dummy,
198 Tcl_Interp *interp, int objc,
199 Tcl_Obj * const objv[]);
200 #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
201 static int TestwrapperObjCmd(ClientData dummy,
202 Tcl_Interp *interp, int objc,
203 Tcl_Obj * const objv[]);
205 static void TrivialCmdDeletedProc(ClientData clientData);
206 static int TrivialConfigObjCmd(ClientData dummy,
207 Tcl_Interp *interp, int objc,
208 Tcl_Obj * const objv[]);
209 static void TrivialEventProc(ClientData clientData,
213 *----------------------------------------------------------------------
217 * This function performs initialization for the Tk test suite extensions.
220 * Returns a standard Tcl completion code, and leaves an error message in
221 * the interp's result if an error occurs.
224 * Creates several test commands.
226 *----------------------------------------------------------------------
231 Tcl_Interp *interp) /* Interpreter for application. */
233 static int initialized = 0;
235 if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
238 if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {
243 * Create additional commands for testing Tk.
246 if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) {
250 Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL);
251 Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
252 (ClientData) Tk_MainWindow(interp), NULL);
253 Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
254 (ClientData) Tk_MainWindow(interp), NULL);
255 Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
256 (ClientData) Tk_MainWindow(interp), NULL);
257 Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd,
258 (ClientData) Tk_MainWindow(interp), NULL);
259 Tcl_CreateObjCommand(interp, "testdeleteapps", TestdeleteappsObjCmd,
260 (ClientData) Tk_MainWindow(interp), NULL);
261 Tcl_CreateObjCommand(interp, "testembed", TkpTestembedCmd,
262 (ClientData) Tk_MainWindow(interp), NULL);
263 Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd,
264 (ClientData) Tk_MainWindow(interp), NULL);
265 Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd,
266 (ClientData) Tk_MainWindow(interp), NULL);
267 Tcl_CreateObjCommand(interp, "testmakeexist", TestmakeexistObjCmd,
268 (ClientData) Tk_MainWindow(interp), NULL);
269 Tcl_CreateObjCommand(interp, "testprop", TestpropObjCmd,
270 (ClientData) Tk_MainWindow(interp), NULL);
271 Tcl_CreateObjCommand(interp, "testtext", TkpTesttextCmd,
272 (ClientData) Tk_MainWindow(interp), NULL);
275 Tcl_CreateObjCommand(interp, "testmetrics", TestmetricsObjCmd,
276 (ClientData) Tk_MainWindow(interp), NULL);
277 #elif !defined(__CYGWIN__) && !defined(MAC_OSX_TK)
278 Tcl_CreateObjCommand(interp, "testmenubar", TestmenubarObjCmd,
279 (ClientData) Tk_MainWindow(interp), NULL);
280 Tcl_CreateObjCommand(interp, "testsend", TkpTestsendCmd,
281 (ClientData) Tk_MainWindow(interp), NULL);
282 Tcl_CreateObjCommand(interp, "testwrapper", TestwrapperObjCmd,
283 (ClientData) Tk_MainWindow(interp), NULL);
287 * Create test image type.
292 Tk_CreateImageType(&imageType);
296 * Enable testing of legacy interfaces.
299 if (TkOldTestInit(interp) != TCL_OK) {
304 * And finally add any platform specific test commands.
307 return TkplatformtestInit(interp);
311 *----------------------------------------------------------------------
313 * TestbitmapObjCmd --
315 * This function implements the "testbitmap" command, which is used to
316 * test color resource handling in tkBitmap tmp.c.
319 * A standard Tcl result.
324 *----------------------------------------------------------------------
329 TCL_UNUSED(void *), /* Main window for application. */
330 Tcl_Interp *interp, /* Current interpreter. */
331 int objc, /* Number of arguments. */
332 Tcl_Obj *const objv[]) /* Argument objects. */
336 Tcl_WrongNumArgs(interp, 1, objv, "bitmap");
339 Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),
340 Tcl_GetString(objv[1])));
345 *----------------------------------------------------------------------
347 * TestborderObjCmd --
349 * This function implements the "testborder" command, which is used to
350 * test color resource handling in tkBorder.c.
353 * A standard Tcl result.
358 *----------------------------------------------------------------------
363 TCL_UNUSED(ClientData), /* Main window for application. */
364 Tcl_Interp *interp, /* Current interpreter. */
365 int objc, /* Number of arguments. */
366 Tcl_Obj *const objv[]) /* Argument objects. */
370 Tcl_WrongNumArgs(interp, 1, objv, "border");
373 Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),
374 Tcl_GetString(objv[1])));
379 *----------------------------------------------------------------------
383 * This function implements the "testcolor" command, which is used to
384 * test color resource handling in tkColor.c.
387 * A standard Tcl result.
392 *----------------------------------------------------------------------
397 TCL_UNUSED(void *), /* Main window for application. */
398 Tcl_Interp *interp, /* Current interpreter. */
399 int objc, /* Number of arguments. */
400 Tcl_Obj *const objv[]) /* Argument objects. */
403 Tcl_WrongNumArgs(interp, 1, objv, "color");
406 Tcl_SetObjResult(interp, TkDebugColor(Tk_MainWindow(interp),
407 Tcl_GetString(objv[1])));
412 *----------------------------------------------------------------------
414 * TestcursorObjCmd --
416 * This function implements the "testcursor" command, which is used to
417 * test color resource handling in tkCursor.c.
420 * A standard Tcl result.
425 *----------------------------------------------------------------------
430 TCL_UNUSED(void *), /* Main window for application. */
431 Tcl_Interp *interp, /* Current interpreter. */
432 int objc, /* Number of arguments. */
433 Tcl_Obj *const objv[]) /* Argument objects. */
436 Tcl_WrongNumArgs(interp, 1, objv, "cursor");
439 Tcl_SetObjResult(interp, TkDebugCursor(Tk_MainWindow(interp),
440 Tcl_GetString(objv[1])));
445 *----------------------------------------------------------------------
447 * TestdeleteappsObjCmd --
449 * This function implements the "testdeleteapps" command. It cleans up
450 * all the interpreters left behind by the "testnewapp" command.
453 * A standard Tcl result.
456 * All the interpreters created by previous calls to "testnewapp" get
459 *----------------------------------------------------------------------
463 TestdeleteappsObjCmd(
464 TCL_UNUSED(void *), /* Main window for application. */
465 TCL_UNUSED(Tcl_Interp *), /* Current interpreter. */
466 TCL_UNUSED(int), /* Number of arguments. */
467 TCL_UNUSED(Tcl_Obj *const *)) /* Argument strings. */
471 while (newAppPtr != NULL) {
472 nextPtr = newAppPtr->nextPtr;
473 Tcl_DeleteInterp(newAppPtr->interp);
482 *----------------------------------------------------------------------
484 * TestobjconfigObjCmd --
486 * This function implements the "testobjconfig" command, which is used to
487 * test the functions in tkConfig.c.
490 * A standard Tcl result.
495 *----------------------------------------------------------------------
500 ClientData clientData, /* Main window for application. */
501 Tcl_Interp *interp, /* Current interpreter. */
502 int objc, /* Number of arguments. */
503 Tcl_Obj *const objv[]) /* Argument objects. */
505 static const char *const options[] = {
506 "alltypes", "chain1", "chain2", "chain3", "configerror", "delete", "info",
507 "internal", "new", "notenoughparams", "twowindows", NULL
510 ALL_TYPES, CHAIN1, CHAIN2, CHAIN3, CONFIG_ERROR,
511 DEL, /* Can't use DELETE: VC++ compiler barfs. */
512 INFO, INTERNAL, NEW, NOT_ENOUGH_PARAMS, TWO_WINDOWS
514 static Tk_OptionTable tables[11];
515 /* Holds pointers to option tables created by
516 * commands below; indexed with same values as
517 * "options" array. */
518 static const Tk_ObjCustomOption CustomOption = {
526 Tk_Window mainWin = (Tk_Window) clientData;
528 int index, result = TCL_OK;
531 * Structures used by the "chain1" subcommand and also shared by the
532 * "chain2" subcommand:
535 typedef struct ExtensionWidgetRecord {
536 TrivialCommandHeader header;
537 Tcl_Obj *base1ObjPtr;
538 Tcl_Obj *base2ObjPtr;
539 Tcl_Obj *extension3ObjPtr;
540 Tcl_Obj *extension4ObjPtr;
541 Tcl_Obj *extension5ObjPtr;
542 } ExtensionWidgetRecord;
543 static const Tk_OptionSpec baseSpecs[] = {
544 {TK_OPTION_STRING, "-one", "one", "One", "one",
545 Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1, 0, NULL, 0},
546 {TK_OPTION_STRING, "-two", "two", "Two", "two",
547 Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
548 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
552 Tcl_WrongNumArgs(interp, 1, objv, "command");
556 if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
557 sizeof(char *), "command", 0, &index)!= TCL_OK) {
563 typedef struct TypesRecord {
564 TrivialCommandHeader header;
569 Tcl_Obj *stringTablePtr;
576 Tcl_Obj *activeCursorPtr;
583 TypesRecord *recordPtr;
584 static const char *const stringTable[] = {
585 "one", "two", "three", "four", NULL
587 static const Tk_OptionSpec typesSpecs[] = {
588 {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
589 Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1},
590 {TK_OPTION_INT, "-integer", "integer", "Integer", "7",
591 Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2},
592 {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
593 Tk_Offset(TypesRecord, doublePtr), -1, 0, 0, 0x4},
594 {TK_OPTION_STRING, "-string", "string", "String",
595 "foo", Tk_Offset(TypesRecord, stringPtr), -1,
596 TK_CONFIG_NULL_OK, 0, 0x8},
597 {TK_OPTION_STRING_TABLE,
598 "-stringtable", "StringTable", "stringTable",
599 "one", Tk_Offset(TypesRecord, stringTablePtr), -1,
600 TK_CONFIG_NULL_OK, stringTable, 0x10},
601 {TK_OPTION_COLOR, "-color", "color", "Color",
602 "red", Tk_Offset(TypesRecord, colorPtr), -1,
603 TK_CONFIG_NULL_OK, "black", 0x20},
604 {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
605 Tk_Offset(TypesRecord, fontPtr), -1,
606 TK_CONFIG_NULL_OK, 0, 0x40},
607 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
608 Tk_Offset(TypesRecord, bitmapPtr), -1,
609 TK_CONFIG_NULL_OK, 0, 0x80},
610 {TK_OPTION_BORDER, "-border", "border", "Border",
611 "blue", Tk_Offset(TypesRecord, borderPtr), -1,
612 TK_CONFIG_NULL_OK, "white", 0x100},
613 {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
614 Tk_Offset(TypesRecord, reliefPtr), -1,
615 TK_CONFIG_NULL_OK, 0, 0x200},
616 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
617 Tk_Offset(TypesRecord, cursorPtr), -1,
618 TK_CONFIG_NULL_OK, 0, 0x400},
619 {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
620 Tk_Offset(TypesRecord, justifyPtr), -1,
621 TK_CONFIG_NULL_OK, 0, 0x800},
622 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
623 Tk_Offset(TypesRecord, anchorPtr), -1,
624 TK_CONFIG_NULL_OK, 0, 0x1000},
625 {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel",
626 "1", Tk_Offset(TypesRecord, pixelPtr), -1,
627 TK_CONFIG_NULL_OK, 0, 0x2000},
628 {TK_OPTION_CUSTOM, "-custom", NULL, NULL,
629 "", Tk_Offset(TypesRecord, customPtr), -1,
630 TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
631 {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
632 NULL, 0, -1, 0, "-color", 0x8000},
633 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
635 Tk_OptionTable optionTable;
637 optionTable = Tk_CreateOptionTable(interp, typesSpecs);
638 tables[index] = optionTable;
639 tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
640 Tcl_GetString(objv[2]), NULL);
644 Tk_SetClass(tkwin, "Test");
646 recordPtr = (TypesRecord *)ckalloc(sizeof(TypesRecord));
647 recordPtr->header.interp = interp;
648 recordPtr->header.optionTable = optionTable;
649 recordPtr->header.tkwin = tkwin;
650 recordPtr->booleanPtr = NULL;
651 recordPtr->integerPtr = NULL;
652 recordPtr->doublePtr = NULL;
653 recordPtr->stringPtr = NULL;
654 recordPtr->colorPtr = NULL;
655 recordPtr->fontPtr = NULL;
656 recordPtr->bitmapPtr = NULL;
657 recordPtr->borderPtr = NULL;
658 recordPtr->reliefPtr = NULL;
659 recordPtr->cursorPtr = NULL;
660 recordPtr->justifyPtr = NULL;
661 recordPtr->anchorPtr = NULL;
662 recordPtr->pixelPtr = NULL;
663 recordPtr->mmPtr = NULL;
664 recordPtr->stringTablePtr = NULL;
665 recordPtr->customPtr = NULL;
666 result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
668 if (result == TCL_OK) {
669 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
670 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
671 (ClientData) recordPtr, TrivialCmdDeletedProc);
672 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
673 TrivialEventProc, (ClientData) recordPtr);
674 result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
675 objc-3, objv+3, tkwin, NULL, NULL);
676 if (result != TCL_OK) {
677 Tk_DestroyWindow(tkwin);
680 Tk_DestroyWindow(tkwin);
683 if (result == TCL_OK) {
684 Tcl_SetObjResult(interp, objv[2]);
690 ExtensionWidgetRecord *recordPtr;
691 Tk_OptionTable optionTable;
693 tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
694 Tcl_GetString(objv[2]), NULL);
698 Tk_SetClass(tkwin, "Test");
699 optionTable = Tk_CreateOptionTable(interp, baseSpecs);
700 tables[index] = optionTable;
702 recordPtr = (ExtensionWidgetRecord *)ckalloc(sizeof(ExtensionWidgetRecord));
703 recordPtr->header.interp = interp;
704 recordPtr->header.optionTable = optionTable;
705 recordPtr->header.tkwin = tkwin;
706 recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
707 recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
708 result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
709 if (result == TCL_OK) {
710 result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
711 objc-3, objv+3, tkwin, NULL, NULL);
712 if (result != TCL_OK) {
713 Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
716 if (result == TCL_OK) {
717 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
718 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
719 (ClientData) recordPtr, TrivialCmdDeletedProc);
720 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
721 TrivialEventProc, (ClientData) recordPtr);
722 Tcl_SetObjResult(interp, objv[2]);
729 ExtensionWidgetRecord *recordPtr;
730 static const Tk_OptionSpec extensionSpecs[] = {
731 {TK_OPTION_STRING, "-three", "three", "Three", "three",
732 Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr), -1, 0, NULL, 0},
733 {TK_OPTION_STRING, "-four", "four", "Four", "four",
734 Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr), -1, 0, NULL, 0},
735 {TK_OPTION_STRING, "-two", "two", "Two", "two and a half",
736 Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1, 0, NULL, 0},
738 "-oneAgain", "oneAgain", "OneAgain", "one again",
739 Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr), -1, 0, NULL, 0},
740 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0,
741 (ClientData) baseSpecs, 0}
743 Tk_OptionTable optionTable;
745 tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
746 Tcl_GetString(objv[2]), NULL);
750 Tk_SetClass(tkwin, "Test");
751 optionTable = Tk_CreateOptionTable(interp, extensionSpecs);
752 tables[index] = optionTable;
754 recordPtr = (ExtensionWidgetRecord *)ckalloc(sizeof(ExtensionWidgetRecord));
755 recordPtr->header.interp = interp;
756 recordPtr->header.optionTable = optionTable;
757 recordPtr->header.tkwin = tkwin;
758 recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
759 recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
760 recordPtr->extension5ObjPtr = NULL;
761 result = Tk_InitOptions(interp, (char *)recordPtr, optionTable, tkwin);
762 if (result == TCL_OK) {
763 result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
764 objc-3, objv+3, tkwin, NULL, NULL);
765 if (result != TCL_OK) {
766 Tk_FreeConfigOptions((char *) recordPtr, optionTable, tkwin);
769 if (result == TCL_OK) {
770 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
771 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
772 (ClientData) recordPtr, TrivialCmdDeletedProc);
773 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
774 TrivialEventProc, (ClientData) recordPtr);
775 Tcl_SetObjResult(interp, objv[2]);
781 typedef struct ErrorWidgetRecord {
784 ErrorWidgetRecord widgetRecord;
785 static const Tk_OptionSpec errorSpecs[] = {
786 {TK_OPTION_INT, "-int", "integer", "Integer", "bogus",
787 Tk_Offset(ErrorWidgetRecord, intPtr), 0, 0, NULL, 0},
788 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
790 Tk_OptionTable optionTable;
792 widgetRecord.intPtr = NULL;
793 optionTable = Tk_CreateOptionTable(interp, errorSpecs);
794 tables[index] = optionTable;
795 return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable,
801 Tcl_WrongNumArgs(interp, 2, objv, "tableName");
804 if (Tcl_GetIndexFromObjStruct(interp, objv[2], options,
805 sizeof(char *), "table", 0, &index) != TCL_OK) {
808 if (tables[index] != NULL) {
809 Tk_DeleteOptionTable(tables[index]);
810 /* Make sure that Tk_DeleteOptionTable() is never done
811 * twice for the same table. */
812 tables[index] = NULL;
818 Tcl_WrongNumArgs(interp, 2, objv, "tableName");
821 if (Tcl_GetIndexFromObjStruct(interp, objv[2], options,
822 sizeof(char *), "table", 0, &index) != TCL_OK) {
825 Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index]));
830 * This command is similar to the "alltypes" command except that it
831 * stores all the configuration options as internal forms instead of
835 typedef struct InternalRecord {
836 TrivialCommandHeader header;
855 InternalRecord *recordPtr;
856 static const char *const internalStringTable[] = {
857 "one", "two", "three", "four", NULL
859 static const Tk_OptionSpec internalSpecs[] = {
860 {TK_OPTION_BOOLEAN, "-boolean", "boolean", "Boolean", "1",
861 -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1},
862 {TK_OPTION_INT, "-integer", "integer", "Integer", "148962237",
863 -1, Tk_Offset(InternalRecord, integer), 0, 0, 0x2},
864 {TK_OPTION_DOUBLE, "-double", "double", "Double", "3.14159",
865 -1, Tk_Offset(InternalRecord, doubleValue), 0, 0, 0x4},
866 {TK_OPTION_STRING, "-string", "string", "String", "foo",
867 -1, Tk_Offset(InternalRecord, string),
868 TK_CONFIG_NULL_OK, 0, 0x8},
869 {TK_OPTION_STRING_TABLE,
870 "-stringtable", "StringTable", "stringTable", "one",
871 -1, Tk_Offset(InternalRecord, index),
872 TK_CONFIG_NULL_OK, internalStringTable, 0x10},
873 {TK_OPTION_COLOR, "-color", "color", "Color", "red",
874 -1, Tk_Offset(InternalRecord, colorPtr),
875 TK_CONFIG_NULL_OK, "black", 0x20},
876 {TK_OPTION_FONT, "-font", "font", "Font", "Helvetica 12",
877 -1, Tk_Offset(InternalRecord, tkfont),
878 TK_CONFIG_NULL_OK, 0, 0x40},
879 {TK_OPTION_BITMAP, "-bitmap", "bitmap", "Bitmap", "gray50",
880 -1, Tk_Offset(InternalRecord, bitmap),
881 TK_CONFIG_NULL_OK, 0, 0x80},
882 {TK_OPTION_BORDER, "-border", "border", "Border", "blue",
883 -1, Tk_Offset(InternalRecord, border),
884 TK_CONFIG_NULL_OK, "white", 0x100},
885 {TK_OPTION_RELIEF, "-relief", "relief", "Relief", "raised",
886 -1, Tk_Offset(InternalRecord, relief),
887 TK_CONFIG_NULL_OK, 0, 0x200},
888 {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor", "xterm",
889 -1, Tk_Offset(InternalRecord, cursor),
890 TK_CONFIG_NULL_OK, 0, 0x400},
891 {TK_OPTION_JUSTIFY, "-justify", NULL, NULL, "left",
892 -1, Tk_Offset(InternalRecord, justify),
893 TK_CONFIG_NULL_OK, 0, 0x800},
894 {TK_OPTION_ANCHOR, "-anchor", "anchor", "Anchor", NULL,
895 -1, Tk_Offset(InternalRecord, anchor),
896 TK_CONFIG_NULL_OK, 0, 0x1000},
897 {TK_OPTION_PIXELS, "-pixel", "pixel", "Pixel", "1",
898 -1, Tk_Offset(InternalRecord, pixels),
899 TK_CONFIG_NULL_OK, 0, 0x2000},
900 {TK_OPTION_WINDOW, "-window", "window", "Window", NULL,
901 -1, Tk_Offset(InternalRecord, tkwin),
902 TK_CONFIG_NULL_OK, 0, 0},
903 {TK_OPTION_CUSTOM, "-custom", NULL, NULL, "",
904 -1, Tk_Offset(InternalRecord, custom),
905 TK_CONFIG_NULL_OK, &CustomOption, 0x4000},
906 {TK_OPTION_SYNONYM, "-synonym", NULL, NULL,
907 NULL, -1, -1, 0, "-color", 0x8000},
908 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
910 Tk_OptionTable optionTable;
912 optionTable = Tk_CreateOptionTable(interp, internalSpecs);
913 tables[index] = optionTable;
914 tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData,
915 Tcl_GetString(objv[2]), NULL);
919 Tk_SetClass(tkwin, "Test");
921 recordPtr = ckalloc(sizeof(InternalRecord));
922 recordPtr->header.interp = interp;
923 recordPtr->header.optionTable = optionTable;
924 recordPtr->header.tkwin = tkwin;
925 recordPtr->boolean = 0;
926 recordPtr->integer = 0;
927 recordPtr->doubleValue = 0.0;
928 recordPtr->string = NULL;
929 recordPtr->index = 0;
930 recordPtr->colorPtr = NULL;
931 recordPtr->tkfont = NULL;
932 recordPtr->bitmap = None;
933 recordPtr->border = NULL;
934 recordPtr->relief = TK_RELIEF_FLAT;
935 recordPtr->cursor = NULL;
936 recordPtr->justify = TK_JUSTIFY_LEFT;
937 recordPtr->anchor = TK_ANCHOR_N;
938 recordPtr->pixels = 0;
940 recordPtr->tkwin = NULL;
941 recordPtr->custom = NULL;
942 result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
944 if (result == TCL_OK) {
945 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
946 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
947 recordPtr, TrivialCmdDeletedProc);
948 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
949 TrivialEventProc, recordPtr);
950 result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
951 objc - 3, objv + 3, tkwin, NULL, NULL);
952 if (result != TCL_OK) {
953 Tk_DestroyWindow(tkwin);
956 Tk_DestroyWindow(tkwin);
959 if (result == TCL_OK) {
960 Tcl_SetObjResult(interp, objv[2]);
966 typedef struct FiveRecord {
967 TrivialCommandHeader header;
974 FiveRecord *recordPtr;
975 static const Tk_OptionSpec smallSpecs[] = {
976 {TK_OPTION_INT, "-one", "one", "One", "1",
977 Tk_Offset(FiveRecord, one), -1, 0, NULL, 0},
978 {TK_OPTION_INT, "-two", "two", "Two", "2",
979 Tk_Offset(FiveRecord, two), -1, 0, NULL, 0},
980 {TK_OPTION_INT, "-three", "three", "Three", "3",
981 Tk_Offset(FiveRecord, three), -1, 0, NULL, 0},
982 {TK_OPTION_INT, "-four", "four", "Four", "4",
983 Tk_Offset(FiveRecord, four), -1, 0, NULL, 0},
984 {TK_OPTION_STRING, "-five", NULL, NULL, NULL,
985 Tk_Offset(FiveRecord, five), -1, 0, NULL, 0},
986 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
990 Tcl_WrongNumArgs(interp, 1, objv, "new name ?-option value ...?");
994 recordPtr = ckalloc(sizeof(FiveRecord));
995 recordPtr->header.interp = interp;
996 recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
998 tables[index] = recordPtr->header.optionTable;
999 recordPtr->header.tkwin = NULL;
1000 recordPtr->one = recordPtr->two = recordPtr->three = NULL;
1001 recordPtr->four = recordPtr->five = NULL;
1002 Tcl_SetObjResult(interp, objv[2]);
1003 result = Tk_InitOptions(interp, (char *) recordPtr,
1004 recordPtr->header.optionTable, (Tk_Window) NULL);
1005 if (result == TCL_OK) {
1006 result = Tk_SetOptions(interp, (char *) recordPtr,
1007 recordPtr->header.optionTable, objc - 3, objv + 3,
1008 (Tk_Window) NULL, NULL, NULL);
1009 if (result == TCL_OK) {
1010 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
1011 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
1012 (ClientData) recordPtr, TrivialCmdDeletedProc);
1014 Tk_FreeConfigOptions((char *) recordPtr,
1015 recordPtr->header.optionTable, (Tk_Window) NULL);
1018 if (result != TCL_OK) {
1024 case NOT_ENOUGH_PARAMS: {
1025 typedef struct NotEnoughRecord {
1028 NotEnoughRecord record;
1029 static const Tk_OptionSpec errorSpecs[] = {
1030 {TK_OPTION_INT, "-foo", "foo", "Foo", "0",
1031 Tk_Offset(NotEnoughRecord, fooObjPtr), 0, 0, NULL, 0},
1032 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
1034 Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1);
1035 Tk_OptionTable optionTable;
1037 record.fooObjPtr = NULL;
1039 tkwin = Tk_CreateWindowFromPath(interp, mainWin, ".config", NULL);
1040 Tk_SetClass(tkwin, "Config");
1041 optionTable = Tk_CreateOptionTable(interp, errorSpecs);
1042 tables[index] = optionTable;
1043 Tk_InitOptions(interp, (char *) &record, optionTable, tkwin);
1044 if (Tk_SetOptions(interp, (char *) &record, optionTable, 1,
1045 &newObjPtr, tkwin, NULL, NULL) != TCL_OK) {
1048 Tcl_DecrRefCount(newObjPtr);
1049 Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin);
1050 Tk_DestroyWindow(tkwin);
1055 typedef struct ContentRecord {
1056 TrivialCommandHeader header;
1059 ContentRecord *recordPtr;
1060 static const Tk_OptionSpec contentSpecs[] = {
1061 {TK_OPTION_WINDOW, "-window", "window", "Window", ".bar",
1062 Tk_Offset(ContentRecord, windowPtr), -1, TK_CONFIG_NULL_OK, NULL, 0},
1063 {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0}
1065 tkwin = Tk_CreateWindowFromPath(interp,
1066 (Tk_Window) clientData, Tcl_GetString(objv[2]), NULL);
1068 if (tkwin == NULL) {
1071 Tk_SetClass(tkwin, "Test");
1073 recordPtr = (ContentRecord *)ckalloc(sizeof(ContentRecord));
1074 recordPtr->header.interp = interp;
1075 recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
1077 tables[index] = recordPtr->header.optionTable;
1078 recordPtr->header.tkwin = tkwin;
1079 recordPtr->windowPtr = NULL;
1081 result = Tk_InitOptions(interp, (char *) recordPtr,
1082 recordPtr->header.optionTable, tkwin);
1083 if (result == TCL_OK) {
1084 result = Tk_SetOptions(interp, (char *) recordPtr,
1085 recordPtr->header.optionTable, objc - 3, objv + 3,
1087 if (result == TCL_OK) {
1088 recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
1089 Tcl_GetString(objv[2]), TrivialConfigObjCmd,
1090 recordPtr, TrivialCmdDeletedProc);
1091 Tk_CreateEventHandler(tkwin, StructureNotifyMask,
1092 TrivialEventProc, recordPtr);
1093 Tcl_SetObjResult(interp, objv[2]);
1095 Tk_FreeConfigOptions((char *) recordPtr,
1096 recordPtr->header.optionTable, tkwin);
1099 if (result != TCL_OK) {
1100 Tk_DestroyWindow(tkwin);
1110 *----------------------------------------------------------------------
1112 * TrivialConfigObjCmd --
1114 * This command is used to test the configuration package. It only
1115 * handles the "configure" and "cget" subcommands.
1118 * A standard Tcl result.
1123 *----------------------------------------------------------------------
1127 TrivialConfigObjCmd(
1128 ClientData clientData, /* Main window for application. */
1129 Tcl_Interp *interp, /* Current interpreter. */
1130 int objc, /* Number of arguments. */
1131 Tcl_Obj *const objv[]) /* Argument objects. */
1133 int result = TCL_OK;
1134 static const char *const options[] = {
1135 "cget", "configure", "csave", NULL
1138 CGET, CONFIGURE, CSAVE
1140 Tcl_Obj *resultObjPtr;
1142 TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
1143 Tk_Window tkwin = headerPtr->tkwin;
1144 Tk_SavedOptions saved;
1147 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
1151 if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
1152 sizeof(char *), "command", 0, &index) != TCL_OK) {
1156 Tcl_Preserve(clientData);
1161 Tcl_WrongNumArgs(interp, 2, objv, "option");
1165 resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData,
1166 headerPtr->optionTable, objv[2], tkwin);
1167 if (resultObjPtr != NULL) {
1168 Tcl_SetObjResult(interp, resultObjPtr);
1176 resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
1177 headerPtr->optionTable, NULL, tkwin);
1178 if (resultObjPtr == NULL) {
1181 Tcl_SetObjResult(interp, resultObjPtr);
1183 } else if (objc == 3) {
1184 resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
1185 headerPtr->optionTable, objv[2], tkwin);
1186 if (resultObjPtr == NULL) {
1189 Tcl_SetObjResult(interp, resultObjPtr);
1192 result = Tk_SetOptions(interp, (char *) clientData,
1193 headerPtr->optionTable, objc - 2, objv + 2,
1194 tkwin, NULL, &mask);
1195 if (result == TCL_OK) {
1196 Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
1201 result = Tk_SetOptions(interp, (char *) clientData,
1202 headerPtr->optionTable, objc - 2, objv + 2,
1203 tkwin, &saved, &mask);
1204 Tk_FreeSavedOptions(&saved);
1205 if (result == TCL_OK) {
1206 Tcl_SetObjResult(interp, Tcl_NewIntObj(mask));
1211 Tcl_Release(clientData);
1216 *----------------------------------------------------------------------
1218 * TrivialCmdDeletedProc --
1220 * This function is invoked when a widget command is deleted. If the
1221 * widget isn't already in the process of being destroyed, this command
1228 * The widget is destroyed.
1230 *----------------------------------------------------------------------
1234 TrivialCmdDeletedProc(
1235 ClientData clientData) /* Pointer to widget record for widget. */
1237 TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;
1238 Tk_Window tkwin = headerPtr->tkwin;
1240 if (tkwin != NULL) {
1241 Tk_DestroyWindow(tkwin);
1242 } else if (headerPtr->optionTable != NULL) {
1244 * This is a "new" object, which doesn't have a window, so we can't
1245 * depend on cleaning up in the event function. Free its resources
1249 Tk_FreeConfigOptions((char *)clientData,
1250 headerPtr->optionTable, NULL);
1251 Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
1256 *--------------------------------------------------------------
1258 * TrivialEventProc --
1260 * A dummy event proc.
1266 * When the window gets deleted, internal structures get cleaned up.
1268 *--------------------------------------------------------------
1273 ClientData clientData, /* Information about window. */
1274 XEvent *eventPtr) /* Information about event. */
1276 TrivialCommandHeader *headerPtr = (TrivialCommandHeader *)clientData;
1278 if (eventPtr->type == DestroyNotify) {
1279 if (headerPtr->tkwin != NULL) {
1280 Tk_FreeConfigOptions((char *)clientData,
1281 headerPtr->optionTable, headerPtr->tkwin);
1282 headerPtr->optionTable = NULL;
1283 headerPtr->tkwin = NULL;
1284 Tcl_DeleteCommandFromToken(headerPtr->interp,
1285 headerPtr->widgetCmd);
1287 Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
1292 *----------------------------------------------------------------------
1296 * This function implements the "testfont" command, which is used to test
1300 * A standard Tcl result.
1305 *----------------------------------------------------------------------
1310 ClientData clientData, /* Main window for application. */
1311 Tcl_Interp *interp, /* Current interpreter. */
1312 int objc, /* Number of arguments. */
1313 Tcl_Obj *const objv[]) /* Argument objects. */
1315 static const char *const options[] = {"counts", "subfonts", NULL};
1316 enum option {COUNTS, SUBFONTS};
1321 tkwin = (Tk_Window)clientData;
1324 Tcl_WrongNumArgs(interp, 1, objv, "option fontName");
1328 if (Tcl_GetIndexFromObjStruct(interp, objv[1], options,
1329 sizeof(char *), "command", 0, &index)!= TCL_OK) {
1333 switch ((enum option) index) {
1335 Tcl_SetObjResult(interp,
1336 TkDebugFont(Tk_MainWindow(interp), Tcl_GetString(objv[2])));
1339 tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
1340 if (tkfont == NULL) {
1343 TkpGetSubFonts(interp, tkfont);
1344 Tk_FreeFont(tkfont);
1352 *----------------------------------------------------------------------
1356 * This function is called by the Tk image code to create "test" images.
1359 * A standard Tcl result.
1362 * The data structure for a new image is allocated.
1364 *----------------------------------------------------------------------
1369 Tcl_Interp *interp, /* Interpreter for application containing
1371 const char *name, /* Name to use for image. */
1372 int objc, /* Number of arguments. */
1373 Tcl_Obj *const objv[], /* Argument strings for options (doesn't
1374 * include image name or type). */
1375 TCL_UNUSED(const Tk_ImageType *), /* Pointer to our type record (not used). */
1376 Tk_ImageModel model, /* Token for image, to be used by us in later
1378 ClientData *clientDataPtr) /* Store manager's token for image here; it
1379 * will be returned in later callbacks. */
1381 TImageModel *timPtr;
1382 const char *varName;
1386 for (i = 0; i < objc; i += 2) {
1387 if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) {
1388 Tcl_AppendResult(interp, "bad option name \"",
1389 Tcl_GetString(objv[i]), "\"", NULL);
1392 if ((i+1) == objc) {
1393 Tcl_AppendResult(interp, "no value given for \"",
1394 Tcl_GetString(objv[i]), "\" option", NULL);
1397 varName = Tcl_GetString(objv[i+1]);
1400 timPtr = (TImageModel *)ckalloc(sizeof(TImageModel));
1401 timPtr->model = model;
1402 timPtr->interp = interp;
1404 timPtr->height = 15;
1405 timPtr->imageName = (char *)ckalloc(strlen(name) + 1);
1406 strcpy(timPtr->imageName, name);
1407 timPtr->varName = (char *)ckalloc(strlen(varName) + 1);
1408 strcpy(timPtr->varName, varName);
1409 Tcl_CreateObjCommand(interp, name, ImageObjCmd, timPtr, NULL);
1410 *clientDataPtr = timPtr;
1411 Tk_ImageChanged(model, 0, 0, 30, 15, 30, 15);
1416 *----------------------------------------------------------------------
1420 * This function implements the commands corresponding to individual
1424 * A standard Tcl result.
1427 * Forces windows to be created.
1429 *----------------------------------------------------------------------
1434 ClientData clientData, /* Main window for application. */
1435 Tcl_Interp *interp, /* Current interpreter. */
1436 int objc, /* Number of arguments. */
1437 Tcl_Obj *const objv[]) /* Argument strings. */
1439 TImageModel *timPtr = (TImageModel *)clientData;
1440 int x, y, width, height;
1443 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
1446 if (strcmp(Tcl_GetString(objv[1]), "changed") == 0) {
1448 Tcl_WrongNumArgs(interp, 1, objv, "changed x y width height"
1449 " imageWidth imageHeight");
1452 if ((Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK)
1453 || (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK)
1454 || (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK)
1455 || (Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK)
1456 || (Tcl_GetIntFromObj(interp, objv[6], &timPtr->width) != TCL_OK)
1457 || (Tcl_GetIntFromObj(interp, objv[7], &timPtr->height) != TCL_OK)) {
1460 Tk_ImageChanged(timPtr->model, x, y, width, height, timPtr->width,
1463 Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
1464 "\": must be changed", NULL);
1471 *----------------------------------------------------------------------
1475 * This function is called by Tk to set things up for using a test image
1476 * in a particular widget.
1479 * The return value is a token for the image instance, which is used in
1480 * future callbacks to ImageDisplay and ImageFree.
1485 *----------------------------------------------------------------------
1490 Tk_Window tkwin, /* Token for window in which image will be
1492 ClientData clientData) /* Pointer to TImageModel for image. */
1494 TImageModel *timPtr = (TImageModel *)clientData;
1495 TImageInstance *instPtr;
1499 sprintf(buffer, "%s get", timPtr->imageName);
1500 Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
1501 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1503 instPtr = (TImageInstance *)ckalloc(sizeof(TImageInstance));
1504 instPtr->modelPtr = timPtr;
1505 instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
1506 gcValues.foreground = instPtr->fg->pixel;
1507 instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
1508 instPtr->displayFailed = False;
1513 *----------------------------------------------------------------------
1517 * This function is invoked to redisplay part or all of an image in a
1524 * The image gets partially redrawn, as an "X" that shows the exact
1527 *----------------------------------------------------------------------
1532 ClientData clientData, /* Pointer to TImageInstance for image. */
1533 Display *display, /* Display to use for drawing. */
1534 Drawable drawable, /* Where to redraw image. */
1535 int imageX, int imageY, /* Origin of area to redraw, relative to
1536 * origin of image. */
1537 int width, int height, /* Dimensions of area to redraw. */
1538 int drawableX, int drawableY)
1539 /* Coordinates in drawable corresponding to
1540 * imageX and imageY. */
1542 TImageInstance *instPtr = (TImageInstance *)clientData;
1545 * The purpose of the test image type is to track the calls to an image
1546 * display proc and record the parameters passed in each call. On macOS a
1547 * display proc must be run inside of the drawRect method of an NSView in
1548 * order for the graphics operations to have any effect. To deal with
1549 * this, whenever a display proc is called outside of any drawRect method
1550 * it schedules a redraw of the NSView.
1552 * In an attempt to work around this, each image instance maintains it own
1553 * copy of the log message which gets written on the first call to the
1554 * display proc. This usually means that the message created on macOS is
1555 * the same as that created on other platforms. However it is possible
1556 * for the messages to differ for other reasons, namely differences in
1557 * how damage regions are computed.
1560 if (LOG_DISPLAY(drawable)) {
1561 if (instPtr->displayFailed == False) {
1564 * Drawing is possible on the first call to DisplayImage.
1568 sprintf(instPtr->buffer, "%s display %d %d %d %d",
1569 instPtr->modelPtr->imageName, imageX, imageY, width, height);
1571 Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName,
1572 NULL, instPtr->buffer,
1573 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1574 instPtr->displayFailed = False;
1578 * Drawing is not possible on the first call to DisplayImage.
1579 * Save the message, but do not log it until the actual display.
1582 if (instPtr->displayFailed == False) {
1583 sprintf(instPtr->buffer, "%s display %d %d %d %d",
1584 instPtr->modelPtr->imageName, imageX, imageY, width, height);
1586 instPtr->displayFailed = True;
1588 if (width > (instPtr->modelPtr->width - imageX)) {
1589 width = instPtr->modelPtr->width - imageX;
1591 if (height > (instPtr->modelPtr->height - imageY)) {
1592 height = instPtr->modelPtr->height - imageY;
1595 XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
1596 (unsigned) (width-1), (unsigned) (height-1));
1597 XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
1598 (int) (drawableX + width - 1), (int) (drawableY + height - 1));
1599 XDrawLine(display, drawable, instPtr->gc, drawableX,
1600 (int) (drawableY + height - 1),
1601 (int) (drawableX + width - 1), drawableY);
1605 *----------------------------------------------------------------------
1609 * This function is called when an instance of an image is no longer
1616 * Information related to the instance is freed.
1618 *----------------------------------------------------------------------
1623 ClientData clientData, /* Pointer to TImageInstance for instance. */
1624 Display *display) /* Display where image was to be drawn. */
1626 TImageInstance *instPtr = (TImageInstance *)clientData;
1629 sprintf(buffer, "%s free", instPtr->modelPtr->imageName);
1630 Tcl_SetVar2(instPtr->modelPtr->interp, instPtr->modelPtr->varName, NULL,
1631 buffer, TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1632 Tk_FreeColor(instPtr->fg);
1633 Tk_FreeGC(display, instPtr->gc);
1638 *----------------------------------------------------------------------
1642 * This function is called to clean up a test image when an application
1649 * Information about the image is deleted.
1651 *----------------------------------------------------------------------
1656 ClientData clientData) /* Pointer to TImageModel for image. When
1657 * this function is called, no more instances
1660 TImageModel *timPtr = (TImageModel *)clientData;
1663 sprintf(buffer, "%s delete", timPtr->imageName);
1664 Tcl_SetVar2(timPtr->interp, timPtr->varName, NULL, buffer,
1665 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
1667 Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
1668 ckfree(timPtr->imageName);
1669 ckfree(timPtr->varName);
1674 *----------------------------------------------------------------------
1676 * TestmakeexistObjCmd --
1678 * This function implements the "testmakeexist" command. It calls
1679 * Tk_MakeWindowExist on each of its arguments to force the windows to be
1683 * A standard Tcl result.
1686 * Forces windows to be created.
1688 *----------------------------------------------------------------------
1692 TestmakeexistObjCmd(
1693 ClientData clientData, /* Main window for application. */
1694 Tcl_Interp *interp, /* Current interpreter. */
1695 int objc, /* Number of arguments. */
1696 Tcl_Obj *const objv[]) /* Argument strings. */
1698 Tk_Window mainWin = (Tk_Window)clientData;
1702 for (i = 1; i < objc; i++) {
1703 tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), mainWin);
1704 if (tkwin == NULL) {
1707 Tk_MakeWindowExist(tkwin);
1714 *----------------------------------------------------------------------
1716 * TestmenubarObjCmd --
1718 * This function implements the "testmenubar" command. It is used to test
1719 * the Unix facilities for creating space above a toplevel window for a
1723 * A standard Tcl result.
1726 * Changes menubar related stuff.
1728 *----------------------------------------------------------------------
1731 #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
1734 ClientData clientData, /* Main window for application. */
1735 Tcl_Interp *interp, /* Current interpreter. */
1736 int objc, /* Number of arguments. */
1737 Tcl_Obj *const objv[]) /* Argument strings. */
1740 Tk_Window mainWin = (Tk_Window)clientData;
1741 Tk_Window tkwin, menubar;
1744 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
1748 if (strcmp(Tcl_GetString(objv[1]), "window") == 0) {
1750 Tcl_WrongNumArgs(interp, 1, objv, "windows toplevel menubar");
1753 tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainWin);
1754 if (tkwin == NULL) {
1757 if (Tcl_GetString(objv[3])[0] == 0) {
1758 TkUnixSetMenubar(tkwin, NULL);
1760 menubar = Tk_NameToWindow(interp, Tcl_GetString(objv[3]), mainWin);
1761 if (menubar == NULL) {
1764 TkUnixSetMenubar(tkwin, menubar);
1767 Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
1768 "\": must be window", NULL);
1774 Tcl_AppendResult(interp, "testmenubar is supported only under Unix", NULL);
1781 *----------------------------------------------------------------------
1783 * TestmetricsObjCmd --
1785 * This function implements the testmetrics command. It provides a way to
1786 * determine the size of various widget components.
1789 * A standard Tcl result.
1794 *----------------------------------------------------------------------
1800 TCL_UNUSED(void *), /* Main window for application. */
1801 Tcl_Interp *interp, /* Current interpreter. */
1802 int objc, /* Number of arguments. */
1803 Tcl_Obj *const objv[]) /* Argument strings. */
1805 char buf[TCL_INTEGER_SPACE];
1809 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?");
1813 if (strcmp(Tcl_GetString(objv[1]), "cyvscroll") == 0) {
1814 val = GetSystemMetrics(SM_CYVSCROLL);
1815 } else if (strcmp(Tcl_GetString(objv[1]), "cxhscroll") == 0) {
1816 val = GetSystemMetrics(SM_CXHSCROLL);
1818 Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
1819 "\": must be cxhscroll or cyvscroll", NULL);
1822 sprintf(buf, "%d", val);
1823 Tcl_AppendResult(interp, buf, NULL);
1829 *----------------------------------------------------------------------
1833 * This function implements the "testprop" command. It fetches and prints
1834 * the value of a property on a window.
1837 * A standard Tcl result.
1842 *----------------------------------------------------------------------
1847 ClientData clientData, /* Main window for application. */
1848 Tcl_Interp *interp, /* Current interpreter. */
1849 int objc, /* Number of arguments. */
1850 Tcl_Obj *const objv[]) /* Argument strings. */
1852 Tk_Window mainWin = (Tk_Window)clientData;
1853 int result, actualFormat;
1854 unsigned long bytesAfter, length, value;
1855 Atom actualType, propName;
1856 unsigned char *property, *p;
1862 Tcl_WrongNumArgs(interp, 1, objv, "window property");
1866 w = strtoul(Tcl_GetString(objv[1]), &end, 0);
1867 propName = Tk_InternAtom(mainWin, Tcl_GetString(objv[2]));
1869 result = XGetWindowProperty(Tk_Display(mainWin),
1870 w, propName, 0, 100000, False, AnyPropertyType,
1871 &actualType, &actualFormat, &length,
1872 &bytesAfter, &property);
1873 if ((result == Success) && (actualType != None)) {
1874 if ((actualFormat == 8) && (actualType == XA_STRING)) {
1875 for (p = property; ((unsigned long)(p-property)) < length; p++) {
1880 Tcl_SetObjResult(interp, Tcl_NewStringObj((/*!unsigned*/char*)property, -1));
1882 for (p = property; length > 0; length--) {
1883 if (actualFormat == 32) {
1884 value = *((long *) p);
1886 } else if (actualFormat == 16) {
1887 value = 0xffff & (*((short *) p));
1893 sprintf(buffer, "0x%lx", value);
1894 Tcl_AppendElement(interp, buffer);
1898 if (property != NULL) {
1904 #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__))
1906 *----------------------------------------------------------------------
1908 * TestwrapperObjCmd --
1910 * This function implements the "testwrapper" command. It provides a way
1911 * from Tcl to determine the extra window Tk adds in between the toplevel
1912 * window and the window decorations.
1915 * A standard Tcl result.
1920 *----------------------------------------------------------------------
1925 ClientData clientData, /* Main window for application. */
1926 Tcl_Interp *interp, /* Current interpreter. */
1927 int objc, /* Number of arguments. */
1928 Tcl_Obj *const objv[]) /* Argument strings. */
1930 TkWindow *winPtr, *wrapperPtr;
1934 Tcl_WrongNumArgs(interp, 1, objv, "window");
1938 tkwin = (Tk_Window)clientData;
1939 winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]), tkwin);
1940 if (winPtr == NULL) {
1944 wrapperPtr = TkpGetWrapperWindow(winPtr);
1945 if (wrapperPtr != NULL) {
1946 char buf[TCL_INTEGER_SPACE];
1948 TkpPrintWindowId(buf, Tk_WindowId(wrapperPtr));
1949 Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, -1));
1956 *----------------------------------------------------------------------
1958 * CustomOptionSet, CustomOptionGet, CustomOptionRestore, CustomOptionFree --
1960 * Handlers for object-based custom configuration options. See
1961 * Testobjconfigcommand.
1964 * See user documentation for expected results from these functions.
1965 * CustomOptionSet Standard Tcl Result.
1966 * CustomOptionGet Tcl_Obj * containing value.
1967 * CustomOptionRestore None.
1968 * CustomOptionFree None.
1971 * Depends on the function.
1972 * CustomOptionSet Sets option value to new setting.
1973 * CustomOptionGet Creates a new Tcl_Obj.
1974 * CustomOptionRestore Resets option value to original value.
1975 * CustomOptionFree Free storage for internal rep of option.
1977 *----------------------------------------------------------------------
1984 TCL_UNUSED(Tk_Window),
1988 char *saveInternalPtr,
1992 char *newStr, *string, *internalPtr;
1996 if (internalOffset >= 0) {
1997 internalPtr = recordPtr + internalOffset;
2003 * See if the object is empty.
2006 if (value == NULL) {
2008 CLANG_ASSERT(value);
2009 } else if ((*value)->bytes != NULL) {
2010 objEmpty = ((*value)->length == 0);
2012 (void)Tcl_GetString(*value);
2013 objEmpty = ((*value)->length == 0);
2016 if ((flags & TK_OPTION_NULL_OK) && objEmpty) {
2019 string = Tcl_GetString(*value);
2020 Tcl_UtfToUpper(string);
2021 if (strcmp(string, "BAD") == 0) {
2022 Tcl_SetObjResult(interp, Tcl_NewStringObj("expected good value, got \"BAD\"", -1));
2026 if (internalPtr != NULL) {
2027 if (*value != NULL) {
2028 string = Tcl_GetString(*value);
2029 newStr = (char *)ckalloc((*value)->length + 1);
2030 strcpy(newStr, string);
2034 *((char **) saveInternalPtr) = *((char **) internalPtr);
2035 *((char **) internalPtr) = newStr;
2044 TCL_UNUSED(Tk_Window),
2048 return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), -1));
2052 CustomOptionRestore(
2053 ClientData clientData,
2056 char *saveInternalPtr)
2058 *(char **)internalPtr = *(char **)saveInternalPtr;
2064 ClientData clientData,
2068 if (*(char **)internalPtr != NULL) {
2069 ckfree(*(char **)internalPtr);