tkTest.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:72k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkTest.c --
  3.  *
  4.  * This file contains C command procedures for a bunch of additional
  5.  * Tcl commands that are used for testing out Tcl's C interfaces.
  6.  * These commands are not normally included in Tcl applications;
  7.  * they're only used for testing.
  8.  *
  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.
  12.  *
  13.  * See the file "license.terms" for information on usage and redistribution
  14.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15.  *
  16.  * RCS: @(#) $Id: tkTest.c,v 1.21.2.2 2005/11/27 02:44:25 das Exp $
  17.  */
  18. #include "tkInt.h"
  19. #include "tkPort.h"
  20. #include "tkText.h"
  21. #ifdef __WIN32__
  22. #include "tkWinInt.h"
  23. #endif
  24. #if defined(MAC_TCL) || defined(MAC_OSX_TK)
  25. #include "tkScrollbar.h"
  26. #endif
  27. #ifdef __UNIX__
  28. #include "tkUnixInt.h"
  29. #endif
  30. /*
  31.  * The following data structure represents the master for a test
  32.  * image:
  33.  */
  34. typedef struct TImageMaster {
  35.     Tk_ImageMaster master; /* Tk's token for image master. */
  36.     Tcl_Interp *interp; /* Interpreter for application. */
  37.     int width, height; /* Dimensions of image. */
  38.     char *imageName; /* Name of image (malloc-ed). */
  39.     char *varName; /* Name of variable in which to log
  40.  * events for image (malloc-ed). */
  41. } TImageMaster;
  42. /*
  43.  * The following data structure represents a particular use of a
  44.  * particular test image.
  45.  */
  46. typedef struct TImageInstance {
  47.     TImageMaster *masterPtr; /* Pointer to master for image. */
  48.     XColor *fg; /* Foreground color for drawing in image. */
  49.     GC gc; /* Graphics context for drawing in image. */
  50. } TImageInstance;
  51. /*
  52.  * The type record for test images:
  53.  */
  54. #ifdef USE_OLD_IMAGE
  55. static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp,
  56.     char *name, int argc, char **argv,
  57.     Tk_ImageType *typePtr, Tk_ImageMaster master,
  58.     ClientData *clientDataPtr));
  59. #else
  60. static int ImageCreate _ANSI_ARGS_((Tcl_Interp *interp,
  61.     char *name, int argc, Tcl_Obj *CONST objv[],
  62.     Tk_ImageType *typePtr, Tk_ImageMaster master,
  63.     ClientData *clientDataPtr));
  64. #endif
  65. static ClientData ImageGet _ANSI_ARGS_((Tk_Window tkwin,
  66.     ClientData clientData));
  67. static void ImageDisplay _ANSI_ARGS_((ClientData clientData,
  68.     Display *display, Drawable drawable, 
  69.     int imageX, int imageY, int width,
  70.     int height, int drawableX,
  71.     int drawableY));
  72. static void ImageFree _ANSI_ARGS_((ClientData clientData,
  73.     Display *display));
  74. static void ImageDelete _ANSI_ARGS_((ClientData clientData));
  75. static Tk_ImageType imageType = {
  76.     "test", /* name */
  77.     (Tk_ImageCreateProc *) ImageCreate, /* createProc */
  78.     ImageGet, /* getProc */
  79.     ImageDisplay, /* displayProc */
  80.     ImageFree, /* freeProc */
  81.     ImageDelete, /* deleteProc */
  82.     (Tk_ImagePostscriptProc *) NULL,/* postscriptPtr */
  83.     (Tk_ImageType *) NULL /* nextPtr */
  84. };
  85. /*
  86.  * One of the following structures describes each of the interpreters
  87.  * created by the "testnewapp" command.  This information is used by
  88.  * the "testdeleteinterps" command to destroy all of those interpreters.
  89.  */
  90. typedef struct NewApp {
  91.     Tcl_Interp *interp; /* Token for interpreter. */
  92.     struct NewApp *nextPtr; /* Next in list of new interpreters. */
  93. } NewApp;
  94. static NewApp *newAppPtr = NULL;
  95. /* First in list of all new interpreters. */
  96. /*
  97.  * Declaration for the square widget's class command procedure:
  98.  */
  99. extern int SquareObjCmd _ANSI_ARGS_((ClientData clientData,
  100. Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]));
  101. typedef struct CBinding {
  102.     Tcl_Interp *interp;
  103.     char *command;
  104.     char *delete;
  105. } CBinding;
  106. /*
  107.  * Header for trivial configuration command items.
  108.  */
  109. #define ODD TK_CONFIG_USER_BIT
  110. #define EVEN (TK_CONFIG_USER_BIT << 1)
  111. enum {
  112.     NONE,
  113.     ODD_TYPE, 
  114.     EVEN_TYPE
  115. };
  116. typedef struct TrivialCommandHeader {
  117.     Tcl_Interp *interp; /* The interp that this command 
  118.  * lives in. */
  119.     Tk_OptionTable optionTable; /* The option table that go with
  120.  * this command. */
  121.     Tk_Window tkwin; /* For widgets, the window associated
  122.  * with this widget. */
  123.     Tcl_Command widgetCmd; /* For widgets, the command associated
  124.  * with this widget. */
  125. } TrivialCommandHeader;
  126. /*
  127.  * Forward declarations for procedures defined later in this file:
  128.  */
  129. static int CBindingEvalProc _ANSI_ARGS_((ClientData clientData, 
  130.     Tcl_Interp *interp, XEvent *eventPtr,
  131.     Tk_Window tkwin, KeySym keySym));
  132. static void CBindingFreeProc _ANSI_ARGS_((ClientData clientData));
  133. int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp));
  134. static int ImageCmd _ANSI_ARGS_((ClientData dummy,
  135.     Tcl_Interp *interp, int argc, CONST char **argv));
  136. static int TestcbindCmd _ANSI_ARGS_((ClientData dummy,
  137.     Tcl_Interp *interp, int argc, CONST char **argv));
  138. static int TestbitmapObjCmd _ANSI_ARGS_((ClientData dummy,
  139.     Tcl_Interp *interp, int objc,
  140.     Tcl_Obj * CONST objv[]));
  141. static int TestborderObjCmd _ANSI_ARGS_((ClientData dummy,
  142.     Tcl_Interp *interp, int objc,
  143.     Tcl_Obj * CONST objv[]));
  144. static int TestcolorObjCmd _ANSI_ARGS_((ClientData dummy,
  145.     Tcl_Interp *interp, int objc,
  146.     Tcl_Obj * CONST objv[]));
  147. static int TestcursorObjCmd _ANSI_ARGS_((ClientData dummy,
  148.     Tcl_Interp *interp, int objc,
  149.     Tcl_Obj * CONST objv[]));
  150. static int TestdeleteappsCmd _ANSI_ARGS_((ClientData dummy,
  151.     Tcl_Interp *interp, int argc, CONST char **argv));
  152. static int TestfontObjCmd _ANSI_ARGS_((ClientData dummy,
  153.     Tcl_Interp *interp, int objc,
  154.     Tcl_Obj *CONST objv[]));
  155. static int TestmakeexistCmd _ANSI_ARGS_((ClientData dummy,
  156.     Tcl_Interp *interp, int argc, CONST char **argv));
  157. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  158. static int TestmenubarCmd _ANSI_ARGS_((ClientData dummy,
  159.     Tcl_Interp *interp, int argc, CONST char **argv));
  160. #endif
  161. #if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)
  162. static int TestmetricsCmd _ANSI_ARGS_((ClientData dummy,
  163.     Tcl_Interp *interp, int argc, CONST char **argv));
  164. #endif
  165. static int TestobjconfigObjCmd _ANSI_ARGS_((ClientData dummy,
  166.     Tcl_Interp *interp, int objc,
  167.     Tcl_Obj * CONST objv[]));
  168. static int CustomOptionSet _ANSI_ARGS_((ClientData clientData,
  169. Tcl_Interp *interp, Tk_Window tkwin,
  170. Tcl_Obj **value, char *recordPtr, int internalOffset,
  171. char *saveInternalPtr, int flags));
  172. static Tcl_Obj *CustomOptionGet _ANSI_ARGS_((ClientData clientData,
  173. Tk_Window tkwin, char *recordPtr, int internalOffset));
  174. static void CustomOptionRestore _ANSI_ARGS_((ClientData clientData,
  175. Tk_Window tkwin, char *internalPtr,
  176. char *saveInternalPtr));
  177. static void CustomOptionFree _ANSI_ARGS_((ClientData clientData,
  178. Tk_Window tkwin, char *internalPtr));
  179. static int TestpropCmd _ANSI_ARGS_((ClientData dummy,
  180.     Tcl_Interp *interp, int argc, CONST char **argv));
  181. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  182. static int TestsendCmd _ANSI_ARGS_((ClientData dummy,
  183.     Tcl_Interp *interp, int argc, CONST char **argv));
  184. #endif
  185. static int TesttextCmd _ANSI_ARGS_((ClientData dummy,
  186.     Tcl_Interp *interp, int argc, CONST char **argv));
  187. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  188. static int TestwrapperCmd _ANSI_ARGS_((ClientData dummy,
  189.     Tcl_Interp *interp, int argc, CONST char **argv));
  190. #endif
  191. static void TrivialCmdDeletedProc _ANSI_ARGS_((
  192.     ClientData clientData));
  193. static int TrivialConfigObjCmd _ANSI_ARGS_((ClientData dummy,
  194.     Tcl_Interp *interp, int objc,
  195.     Tcl_Obj * CONST objv[]));
  196. static void TrivialEventProc _ANSI_ARGS_((ClientData clientData,
  197.     XEvent *eventPtr));
  198. /*
  199.  * External (platform specific) initialization routine:
  200.  */
  201. extern int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp));
  202. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  203. #define TkplatformtestInit(x) TCL_OK
  204. #endif
  205. /*
  206.  *----------------------------------------------------------------------
  207.  *
  208.  * Tktest_Init --
  209.  *
  210.  * This procedure performs intialization for the Tk test
  211.  * suite exensions.
  212.  *
  213.  * Results:
  214.  * Returns a standard Tcl completion code, and leaves an error
  215.  * message in the interp's result if an error occurs.
  216.  *
  217.  * Side effects:
  218.  * Creates several test commands.
  219.  *
  220.  *----------------------------------------------------------------------
  221.  */
  222. int
  223. Tktest_Init(interp)
  224.     Tcl_Interp *interp; /* Interpreter for application. */
  225. {
  226.     static int initialized = 0;
  227.     /*
  228.      * Create additional commands for testing Tk.
  229.      */
  230.     if (Tcl_PkgProvide(interp, "Tktest", TK_VERSION) == TCL_ERROR) {
  231.         return TCL_ERROR;
  232.     }
  233.     Tcl_CreateObjCommand(interp, "square", SquareObjCmd,
  234.     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
  235.     Tcl_CreateCommand(interp, "testcbind", TestcbindCmd,
  236.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  237.     Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd,
  238.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  239.     Tcl_CreateObjCommand(interp, "testborder", TestborderObjCmd,
  240.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  241.     Tcl_CreateObjCommand(interp, "testcolor", TestcolorObjCmd,
  242.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  243.     Tcl_CreateObjCommand(interp, "testcursor", TestcursorObjCmd,
  244.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  245.     Tcl_CreateCommand(interp, "testdeleteapps", TestdeleteappsCmd,
  246.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  247.     Tcl_CreateCommand(interp, "testembed", TkpTestembedCmd,
  248.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  249.     Tcl_CreateObjCommand(interp, "testobjconfig", TestobjconfigObjCmd,
  250.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  251.     Tcl_CreateObjCommand(interp, "testfont", TestfontObjCmd,
  252.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  253.     Tcl_CreateCommand(interp, "testmakeexist", TestmakeexistCmd,
  254.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  255. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  256.     Tcl_CreateCommand(interp, "testmenubar", TestmenubarCmd,
  257.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  258. #endif
  259. #if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)
  260.     Tcl_CreateCommand(interp, "testmetrics", TestmetricsCmd,
  261.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  262. #endif
  263.     Tcl_CreateCommand(interp, "testprop", TestpropCmd,
  264.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  265. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  266.     Tcl_CreateCommand(interp, "testsend", TestsendCmd,
  267.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  268. #endif
  269.     Tcl_CreateCommand(interp, "testtext", TesttextCmd,
  270.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  271. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  272.     Tcl_CreateCommand(interp, "testwrapper", TestwrapperCmd,
  273.     (ClientData) Tk_MainWindow(interp), (Tcl_CmdDeleteProc *) NULL);
  274. #endif
  275.     /*
  276.      * Create test image type.
  277.      */
  278.     if (!initialized) {
  279. initialized = 1;
  280. Tk_CreateImageType(&imageType);
  281.     }
  282.     /*
  283.      * And finally add any platform specific test commands.
  284.      */
  285.     
  286.     return TkplatformtestInit(interp);
  287. }
  288. /*
  289.  *----------------------------------------------------------------------
  290.  *
  291.  * TestcbindCmd --
  292.  *
  293.  * This procedure implements the "testcbinding" command.  It provides
  294.  * a set of functions for testing C bindings in tkBind.c.
  295.  *
  296.  * Results:
  297.  * A standard Tcl result.
  298.  *
  299.  * Side effects:
  300.  * Depends on option;  see below.
  301.  *
  302.  *----------------------------------------------------------------------
  303.  */
  304. static int
  305. TestcbindCmd(clientData, interp, argc, argv)
  306.     ClientData clientData; /* Main window for application. */
  307.     Tcl_Interp *interp; /* Current interpreter. */
  308.     int argc; /* Number of arguments. */
  309.     CONST char **argv; /* Argument strings. */
  310. {
  311.     TkWindow *winPtr;
  312.     Tk_Window tkwin;
  313.     ClientData object;
  314.     CBinding *cbindPtr;
  315.     
  316.     
  317.     if (argc < 4 || argc > 5) {
  318. Tcl_AppendResult(interp, "wrong # args: should be "", argv[0],
  319. " bindtag pattern command ?deletecommand?", (char *) NULL);
  320. return TCL_ERROR;
  321.     }
  322.     tkwin = (Tk_Window) clientData;
  323.     if (argv[1][0] == '.') {
  324. winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
  325. if (winPtr == NULL) {
  326.     return TCL_ERROR;
  327. }
  328. object = (ClientData) winPtr->pathName;
  329.     } else {
  330. winPtr = (TkWindow *) clientData;
  331. object = (ClientData) Tk_GetUid(argv[1]);
  332.     }
  333.     if (argv[3][0] == '') {
  334. return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,
  335. object, argv[2]);
  336.     }
  337.     cbindPtr = (CBinding *) ckalloc(sizeof(CBinding));
  338.     cbindPtr->interp = interp;
  339.     cbindPtr->command =
  340.     strcpy((char *) ckalloc(strlen(argv[3]) + 1), argv[3]);
  341.     if (argc == 4) {
  342. cbindPtr->delete = NULL;
  343.     } else {
  344. cbindPtr->delete =
  345. strcpy((char *) ckalloc(strlen(argv[4]) + 1), argv[4]);
  346.     }
  347.     if (TkCreateBindingProcedure(interp, winPtr->mainPtr->bindingTable,
  348.     object, argv[2], CBindingEvalProc, CBindingFreeProc,
  349.     (ClientData) cbindPtr) == 0) {
  350. ckfree((char *) cbindPtr->command);
  351. if (cbindPtr->delete != NULL) {
  352.     ckfree((char *) cbindPtr->delete);
  353. }
  354. ckfree((char *) cbindPtr);
  355. return TCL_ERROR;
  356.     }
  357.     return TCL_OK;
  358. }
  359. static int
  360. CBindingEvalProc(clientData, interp, eventPtr, tkwin, keySym)
  361.     ClientData clientData;
  362.     Tcl_Interp *interp;
  363.     XEvent *eventPtr;
  364.     Tk_Window tkwin;
  365.     KeySym keySym;
  366. {
  367.     CBinding *cbindPtr;
  368.     cbindPtr = (CBinding *) clientData;
  369.     
  370.     return Tcl_GlobalEval(interp, cbindPtr->command);
  371. }
  372. static void
  373. CBindingFreeProc(clientData)
  374.     ClientData clientData;
  375. {
  376.     CBinding *cbindPtr = (CBinding *) clientData;
  377.     
  378.     if (cbindPtr->delete != NULL) {
  379. Tcl_GlobalEval(cbindPtr->interp, cbindPtr->delete);
  380. ckfree((char *) cbindPtr->delete);
  381.     }
  382.     ckfree((char *) cbindPtr->command);
  383.     ckfree((char *) cbindPtr);
  384. }
  385. /*
  386.  *----------------------------------------------------------------------
  387.  *
  388.  * TestbitmapObjCmd --
  389.  *
  390.  * This procedure implements the "testbitmap" command, which is used
  391.  * to test color resource handling in tkBitmap tmp.c.
  392.  *
  393.  * Results:
  394.  * A standard Tcl result.
  395.  *
  396.  * Side effects:
  397.  * None.
  398.  *
  399.  *----------------------------------------------------------------------
  400.  */
  401. /* ARGSUSED */
  402. static int
  403. TestbitmapObjCmd(clientData, interp, objc, objv)
  404.     ClientData clientData; /* Main window for application. */
  405.     Tcl_Interp *interp; /* Current interpreter. */
  406.     int objc; /* Number of arguments. */
  407.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  408. {
  409.     if (objc < 2) {
  410. Tcl_WrongNumArgs(interp, 1, objv, "bitmap");
  411. return TCL_ERROR;
  412.     }
  413.     Tcl_SetObjResult(interp, TkDebugBitmap(Tk_MainWindow(interp),
  414.     Tcl_GetString(objv[1])));
  415.     return TCL_OK;
  416. }
  417. /*
  418.  *----------------------------------------------------------------------
  419.  *
  420.  * TestborderObjCmd --
  421.  *
  422.  * This procedure implements the "testborder" command, which is used
  423.  * to test color resource handling in tkBorder.c.
  424.  *
  425.  * Results:
  426.  * A standard Tcl result.
  427.  *
  428.  * Side effects:
  429.  * None.
  430.  *
  431.  *----------------------------------------------------------------------
  432.  */
  433. /* ARGSUSED */
  434. static int
  435. TestborderObjCmd(clientData, interp, objc, objv)
  436.     ClientData clientData; /* Main window for application. */
  437.     Tcl_Interp *interp; /* Current interpreter. */
  438.     int objc; /* Number of arguments. */
  439.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  440. {
  441.     if (objc < 2) {
  442. Tcl_WrongNumArgs(interp, 1, objv, "border");
  443. return TCL_ERROR;
  444.     }
  445.     Tcl_SetObjResult(interp, TkDebugBorder(Tk_MainWindow(interp),
  446.     Tcl_GetString(objv[1])));
  447.     return TCL_OK;
  448. }
  449. /*
  450.  *----------------------------------------------------------------------
  451.  *
  452.  * TestcolorObjCmd --
  453.  *
  454.  * This procedure implements the "testcolor" command, which is used
  455.  * to test color resource handling in tkColor.c.
  456.  *
  457.  * Results:
  458.  * A standard Tcl result.
  459.  *
  460.  * Side effects:
  461.  * None.
  462.  *
  463.  *----------------------------------------------------------------------
  464.  */
  465. /* ARGSUSED */
  466. static int
  467. TestcolorObjCmd(clientData, interp, objc, objv)
  468.     ClientData clientData; /* Main window for application. */
  469.     Tcl_Interp *interp; /* Current interpreter. */
  470.     int objc; /* Number of arguments. */
  471.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  472. {
  473.     if (objc < 2) {
  474. Tcl_WrongNumArgs(interp, 1, objv, "color");
  475. return TCL_ERROR;
  476.     }
  477.     Tcl_SetObjResult(interp, TkDebugColor(Tk_MainWindow(interp),
  478.     Tcl_GetString(objv[1])));
  479.     return TCL_OK;
  480. }
  481. /*
  482.  *----------------------------------------------------------------------
  483.  *
  484.  * TestcursorObjCmd --
  485.  *
  486.  * This procedure implements the "testcursor" command, which is used
  487.  * to test color resource handling in tkCursor.c.
  488.  *
  489.  * Results:
  490.  * A standard Tcl result.
  491.  *
  492.  * Side effects:
  493.  * None.
  494.  *
  495.  *----------------------------------------------------------------------
  496.  */
  497. /* ARGSUSED */
  498. static int
  499. TestcursorObjCmd(clientData, interp, objc, objv)
  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. */
  504. {
  505.     if (objc < 2) {
  506. Tcl_WrongNumArgs(interp, 1, objv, "cursor");
  507. return TCL_ERROR;
  508.     }
  509.     Tcl_SetObjResult(interp, TkDebugCursor(Tk_MainWindow(interp),
  510.     Tcl_GetString(objv[1])));
  511.     return TCL_OK;
  512. }
  513. /*
  514.  *----------------------------------------------------------------------
  515.  *
  516.  * TestdeleteappsCmd --
  517.  *
  518.  * This procedure implements the "testdeleteapps" command.  It cleans
  519.  * up all the interpreters left behind by the "testnewapp" command.
  520.  *
  521.  * Results:
  522.  * A standard Tcl result.
  523.  *
  524.  * Side effects:
  525.  * All the intepreters created by previous calls to "testnewapp"
  526.  * get deleted.
  527.  *
  528.  *----------------------------------------------------------------------
  529.  */
  530. /* ARGSUSED */
  531. static int
  532. TestdeleteappsCmd(clientData, interp, argc, argv)
  533.     ClientData clientData; /* Main window for application. */
  534.     Tcl_Interp *interp; /* Current interpreter. */
  535.     int argc; /* Number of arguments. */
  536.     CONST char **argv; /* Argument strings. */
  537. {
  538.     NewApp *nextPtr;
  539.     while (newAppPtr != NULL) {
  540. nextPtr = newAppPtr->nextPtr;
  541. Tcl_DeleteInterp(newAppPtr->interp);
  542. ckfree((char *) newAppPtr);
  543. newAppPtr = nextPtr;
  544.     }
  545.     return TCL_OK;
  546. }
  547. /*
  548.  *----------------------------------------------------------------------
  549.  *
  550.  * TestobjconfigObjCmd --
  551.  *
  552.  * This procedure implements the "testobjconfig" command,
  553.  * which is used to test the procedures in tkConfig.c.
  554.  *
  555.  * Results:
  556.  * A standard Tcl result.
  557.  *
  558.  * Side effects:
  559.  * None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563. /* ARGSUSED */
  564. static int
  565. TestobjconfigObjCmd(clientData, interp, objc, objv)
  566.     ClientData clientData; /* Main window for application. */
  567.     Tcl_Interp *interp; /* Current interpreter. */
  568.     int objc; /* Number of arguments. */
  569.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  570. {
  571.     static CONST char *options[] = {"alltypes", "chain1", "chain2",
  572.     "configerror", "delete", "info", "internal", "new",
  573.     "notenoughparams", "twowindows", (char *) NULL};
  574.     enum {
  575. ALL_TYPES,
  576. CHAIN1,
  577. CHAIN2,
  578. CONFIG_ERROR,
  579. DEL, /* Can't use DELETE: VC++ compiler barfs. */
  580. INFO,
  581. INTERNAL,
  582. NEW,
  583. NOT_ENOUGH_PARAMS,
  584. TWO_WINDOWS
  585.     };
  586.     static Tk_OptionTable tables[11]; /* Holds pointers to option tables
  587.  * created by commands below; indexed
  588.  * with same values as "options"
  589.  * array. */
  590.     static Tk_ObjCustomOption CustomOption = {
  591. "custom option",
  592.     CustomOptionSet,
  593.     CustomOptionGet,
  594.     CustomOptionRestore,
  595.     CustomOptionFree,
  596.     (ClientData) 1
  597.     };
  598.     Tk_Window mainWin = (Tk_Window) clientData;
  599.     Tk_Window tkwin;
  600.     int index, result = TCL_OK;
  601.     /*
  602.      * Structures used by the "chain1" subcommand and also shared by
  603.      * the "chain2" subcommand:
  604.      */
  605.     typedef struct ExtensionWidgetRecord {
  606. TrivialCommandHeader header;
  607. Tcl_Obj *base1ObjPtr;
  608. Tcl_Obj *base2ObjPtr;
  609. Tcl_Obj *extension3ObjPtr;
  610. Tcl_Obj *extension4ObjPtr;
  611. Tcl_Obj *extension5ObjPtr;
  612.     } ExtensionWidgetRecord;
  613.     static Tk_OptionSpec baseSpecs[] = {
  614. {TK_OPTION_STRING,
  615. "-one", "one", "One", "one",
  616. Tk_Offset(ExtensionWidgetRecord, base1ObjPtr), -1},
  617. {TK_OPTION_STRING,
  618. "-two", "two", "Two", "two",
  619. Tk_Offset(ExtensionWidgetRecord, base2ObjPtr), -1},
  620. {TK_OPTION_END}
  621.     };
  622.     if (objc < 2) {
  623. Tcl_WrongNumArgs(interp, 1, objv, "command");
  624. return TCL_ERROR;
  625.     }
  626.     if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index)
  627.     != TCL_OK) {
  628. return TCL_ERROR;
  629.     }
  630.     switch (index) {
  631. case ALL_TYPES: {
  632.     typedef struct TypesRecord {
  633. TrivialCommandHeader header;
  634. Tcl_Obj *booleanPtr;
  635. Tcl_Obj *integerPtr;
  636. Tcl_Obj *doublePtr;
  637. Tcl_Obj *stringPtr;
  638. Tcl_Obj *stringTablePtr;
  639. Tcl_Obj *colorPtr;
  640. Tcl_Obj *fontPtr;
  641. Tcl_Obj *bitmapPtr;
  642. Tcl_Obj *borderPtr;
  643. Tcl_Obj *reliefPtr;
  644. Tcl_Obj *cursorPtr;
  645. Tcl_Obj *activeCursorPtr;
  646. Tcl_Obj *justifyPtr;
  647. Tcl_Obj *anchorPtr;
  648. Tcl_Obj *pixelPtr;
  649. Tcl_Obj *mmPtr;
  650. Tcl_Obj *customPtr;
  651.     } TypesRecord;
  652.     TypesRecord *recordPtr;
  653.     static char *stringTable[] = {"one", "two", "three", "four", 
  654.     (char *) NULL};
  655.     static Tk_OptionSpec typesSpecs[] = {
  656. {TK_OPTION_BOOLEAN,
  657. "-boolean", "boolean", "Boolean",
  658. "1", Tk_Offset(TypesRecord, booleanPtr), -1, 0, 0, 0x1},
  659. {TK_OPTION_INT,
  660. "-integer", "integer", "Integer",
  661. "7", Tk_Offset(TypesRecord, integerPtr), -1, 0, 0, 0x2},
  662. {TK_OPTION_DOUBLE,
  663. "-double", "double", "Double",
  664. "3.14159", Tk_Offset(TypesRecord, doublePtr), -1, 0, 0,
  665. 0x4},
  666. {TK_OPTION_STRING,
  667. "-string", "string", "String",
  668. "foo", Tk_Offset(TypesRecord, stringPtr), -1, 
  669. TK_CONFIG_NULL_OK, 0, 0x8},
  670. {TK_OPTION_STRING_TABLE,
  671. "-stringtable", "StringTable", "stringTable",
  672. "one", Tk_Offset(TypesRecord, stringTablePtr), -1,
  673. TK_CONFIG_NULL_OK, (ClientData) stringTable, 0x10},
  674. {TK_OPTION_COLOR,
  675. "-color", "color", "Color",
  676. "red", Tk_Offset(TypesRecord, colorPtr), -1, 
  677. TK_CONFIG_NULL_OK, (ClientData) "black", 0x20},
  678. {TK_OPTION_FONT,
  679. "-font", "font", "Font",
  680. "Helvetica 12",
  681. Tk_Offset(TypesRecord, fontPtr), -1,
  682. TK_CONFIG_NULL_OK, 0, 0x40},
  683. {TK_OPTION_BITMAP,
  684. "-bitmap", "bitmap", "Bitmap",
  685. "gray50",
  686. Tk_Offset(TypesRecord, bitmapPtr), -1,
  687. TK_CONFIG_NULL_OK, 0, 0x80},
  688. {TK_OPTION_BORDER,
  689. "-border", "border", "Border",
  690. "blue", Tk_Offset(TypesRecord, borderPtr), -1,
  691. TK_CONFIG_NULL_OK, (ClientData) "white", 0x100},
  692. {TK_OPTION_RELIEF,
  693. "-relief", "relief", "Relief",
  694. "raised",
  695. Tk_Offset(TypesRecord, reliefPtr), -1,
  696. TK_CONFIG_NULL_OK, 0, 0x200},
  697. {TK_OPTION_CURSOR,
  698. "-cursor", "cursor", "Cursor",
  699. "xterm",
  700. Tk_Offset(TypesRecord, cursorPtr), -1,
  701. TK_CONFIG_NULL_OK, 0, 0x400},
  702. {TK_OPTION_JUSTIFY,
  703. "-justify", (char *) NULL, (char *) NULL,
  704. "left",
  705. Tk_Offset(TypesRecord, justifyPtr), -1,
  706. TK_CONFIG_NULL_OK, 0, 0x800},
  707. {TK_OPTION_ANCHOR,
  708. "-anchor", "anchor", "Anchor",
  709. (char *) NULL,
  710. Tk_Offset(TypesRecord, anchorPtr), -1,
  711. TK_CONFIG_NULL_OK, 0, 0x1000},
  712. {TK_OPTION_PIXELS,
  713. "-pixel", "pixel", "Pixel",
  714. "1", Tk_Offset(TypesRecord, pixelPtr), -1,
  715. TK_CONFIG_NULL_OK, 0, 0x2000},
  716. {TK_OPTION_CUSTOM,
  717.         "-custom", (char *) NULL, (char *) NULL,
  718.         "", Tk_Offset(TypesRecord, customPtr), -1,
  719.            TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000},
  720. {TK_OPTION_SYNONYM,
  721. "-synonym", (char *) NULL, (char *) NULL,
  722. (char *) NULL, 0, -1, 0, (ClientData) "-color",
  723. 0x8000},
  724. {TK_OPTION_END}
  725.     };
  726.     Tk_OptionTable optionTable;
  727.     Tk_Window tkwin;
  728.     optionTable = Tk_CreateOptionTable(interp,
  729.     typesSpecs);
  730.     tables[index] = optionTable;
  731.     tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, 
  732.     Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL);
  733.     if (tkwin == NULL) {
  734. return TCL_ERROR;
  735.     }
  736.     Tk_SetClass(tkwin, "Test");
  737.     recordPtr = (TypesRecord *) ckalloc(sizeof(TypesRecord));
  738.     recordPtr->header.interp = interp;
  739.     recordPtr->header.optionTable = optionTable;
  740.     recordPtr->header.tkwin = tkwin;
  741.     recordPtr->booleanPtr = NULL;
  742.     recordPtr->integerPtr = NULL;
  743.     recordPtr->doublePtr = NULL;
  744.     recordPtr->stringPtr = NULL;
  745.     recordPtr->colorPtr = NULL;
  746.     recordPtr->fontPtr = NULL;
  747.     recordPtr->bitmapPtr = NULL;
  748.     recordPtr->borderPtr = NULL;
  749.     recordPtr->reliefPtr = NULL;
  750.     recordPtr->cursorPtr = NULL;
  751.     recordPtr->justifyPtr = NULL;
  752.     recordPtr->anchorPtr = NULL;
  753.     recordPtr->pixelPtr = NULL;
  754.     recordPtr->mmPtr = NULL;
  755.     recordPtr->stringTablePtr = NULL;
  756.     recordPtr->customPtr = NULL;
  757.     result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
  758.     tkwin);
  759.     if (result == TCL_OK) {
  760. recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
  761. Tcl_GetStringFromObj(objv[2], NULL),
  762. TrivialConfigObjCmd, (ClientData) recordPtr,
  763. TrivialCmdDeletedProc);
  764. Tk_CreateEventHandler(tkwin, StructureNotifyMask,
  765. TrivialEventProc, (ClientData) recordPtr);
  766. result = Tk_SetOptions(interp, (char *) recordPtr,
  767. optionTable, objc - 3, objv + 3, tkwin,
  768. (Tk_SavedOptions *) NULL, (int *) NULL);
  769. if (result != TCL_OK) {
  770.     Tk_DestroyWindow(tkwin);
  771. }
  772.     } else {
  773. Tk_DestroyWindow(tkwin);
  774. ckfree((char *) recordPtr);
  775.     }
  776.     if (result == TCL_OK) {
  777. Tcl_SetObjResult(interp, objv[2]);
  778.     }
  779.     break;
  780. }
  781. case CHAIN1: {
  782.     ExtensionWidgetRecord *recordPtr;
  783.     Tk_Window tkwin;
  784.     Tk_OptionTable optionTable;
  785.     tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, 
  786.     Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL);
  787.     if (tkwin == NULL) {
  788. return TCL_ERROR;
  789.     }
  790.     Tk_SetClass(tkwin, "Test");
  791.     optionTable = Tk_CreateOptionTable(interp, baseSpecs);
  792.     tables[index] = optionTable;
  793.     recordPtr = (ExtensionWidgetRecord *) ckalloc(
  794.          sizeof(ExtensionWidgetRecord));
  795.     recordPtr->header.interp = interp;
  796.     recordPtr->header.optionTable = optionTable;
  797.     recordPtr->header.tkwin = tkwin;
  798.     recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
  799.     recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
  800.     result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
  801.     tkwin);
  802.     if (result == TCL_OK) {
  803. result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
  804. objc - 3, objv + 3, tkwin, (Tk_SavedOptions *) NULL,
  805. (int *) NULL);
  806. if (result != TCL_OK) {
  807.     Tk_FreeConfigOptions((char *) recordPtr, optionTable,
  808.     tkwin);
  809. }
  810.     }
  811.     if (result == TCL_OK) {
  812. recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
  813. Tcl_GetStringFromObj(objv[2], NULL),
  814. TrivialConfigObjCmd, (ClientData) recordPtr,
  815. TrivialCmdDeletedProc);
  816. Tk_CreateEventHandler(tkwin, StructureNotifyMask,
  817. TrivialEventProc, (ClientData) recordPtr);
  818. Tcl_SetObjResult(interp, objv[2]);
  819.     }
  820.     break;
  821. }
  822. case CHAIN2: {
  823.     ExtensionWidgetRecord *recordPtr;
  824.     static Tk_OptionSpec extensionSpecs[] = {
  825. {TK_OPTION_STRING,
  826. "-three", "three", "Three", "three",
  827. Tk_Offset(ExtensionWidgetRecord, extension3ObjPtr),
  828. -1},
  829. {TK_OPTION_STRING,
  830. "-four", "four", "Four", "four",
  831. Tk_Offset(ExtensionWidgetRecord, extension4ObjPtr),
  832. -1},
  833. {TK_OPTION_STRING,
  834. "-two", "two", "Two", "two and a half",
  835. Tk_Offset(ExtensionWidgetRecord, base2ObjPtr),
  836. -1},
  837. {TK_OPTION_STRING,
  838. "-oneAgain", "oneAgain", "OneAgain", "one again",
  839. Tk_Offset(ExtensionWidgetRecord, extension5ObjPtr),
  840. -1},
  841. {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
  842. (char *) NULL, 0, -1, 0, (ClientData) baseSpecs}
  843.     };
  844.     Tk_Window tkwin;
  845.     Tk_OptionTable optionTable;
  846.     tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, 
  847.     Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL);
  848.     if (tkwin == NULL) {
  849. return TCL_ERROR;
  850.     }
  851.     Tk_SetClass(tkwin, "Test");
  852.     optionTable = Tk_CreateOptionTable(interp, extensionSpecs);
  853.     tables[index] = optionTable;
  854.     recordPtr = (ExtensionWidgetRecord *) ckalloc(
  855.          sizeof(ExtensionWidgetRecord));
  856.     recordPtr->header.interp = interp;
  857.     recordPtr->header.optionTable = optionTable;
  858.     recordPtr->header.tkwin = tkwin;
  859.     recordPtr->base1ObjPtr = recordPtr->base2ObjPtr = NULL;
  860.     recordPtr->extension3ObjPtr = recordPtr->extension4ObjPtr = NULL;
  861.     recordPtr->extension5ObjPtr = NULL;
  862.     result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
  863.     tkwin);
  864.     if (result == TCL_OK) {
  865. result = Tk_SetOptions(interp, (char *) recordPtr, optionTable,
  866. objc - 3, objv + 3, tkwin, (Tk_SavedOptions *) NULL,
  867. (int *) NULL);
  868. if (result != TCL_OK) {
  869.     Tk_FreeConfigOptions((char *) recordPtr, optionTable,
  870.     tkwin);
  871. }
  872.     }
  873.     if (result == TCL_OK) {
  874. recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
  875. Tcl_GetStringFromObj(objv[2], NULL),
  876. TrivialConfigObjCmd, (ClientData) recordPtr,
  877. TrivialCmdDeletedProc);
  878. Tk_CreateEventHandler(tkwin, StructureNotifyMask,
  879. TrivialEventProc, (ClientData) recordPtr);
  880. Tcl_SetObjResult(interp, objv[2]);
  881.     }
  882.     break;
  883. }
  884. case CONFIG_ERROR: {
  885.     typedef struct ErrorWidgetRecord {
  886. Tcl_Obj *intPtr;
  887.     } ErrorWidgetRecord;
  888.     ErrorWidgetRecord widgetRecord;
  889.     static Tk_OptionSpec errorSpecs[] = {
  890. {TK_OPTION_INT, 
  891. "-int", "integer", "Integer",
  892. "bogus", Tk_Offset(ErrorWidgetRecord, intPtr)},
  893. {TK_OPTION_END}
  894.     };
  895.     Tk_OptionTable optionTable;
  896.     widgetRecord.intPtr = NULL;
  897.     optionTable = Tk_CreateOptionTable(interp, errorSpecs);
  898.     tables[index] = optionTable;
  899.     return Tk_InitOptions(interp, (char *) &widgetRecord, optionTable,
  900.     (Tk_Window) NULL);
  901. }
  902. case DEL: {
  903.     if (objc != 3) {
  904. Tcl_WrongNumArgs(interp, 2, objv, "tableName");
  905. return TCL_ERROR;
  906.     }
  907.     if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0,
  908.     &index) != TCL_OK) {
  909. return TCL_ERROR;
  910.     }
  911.     if (tables[index] != NULL) {
  912. Tk_DeleteOptionTable(tables[index]);
  913.     }
  914.     break;
  915. }
  916. case INFO: {
  917.     if (objc != 3) {
  918. Tcl_WrongNumArgs(interp, 2, objv, "tableName");
  919. return TCL_ERROR;
  920.     }
  921.     if (Tcl_GetIndexFromObj(interp, objv[2], options, "table", 0,
  922.     &index) != TCL_OK) {
  923. return TCL_ERROR;
  924.     }
  925.     Tcl_SetObjResult(interp, TkDebugConfig(interp, tables[index]));
  926.     break;
  927. }
  928. case INTERNAL: {
  929.     /*
  930.      * This command is similar to the "alltypes" command except
  931.      * that it stores all the configuration options as internal
  932.      * forms instead of objects.
  933.      */
  934.     typedef struct InternalRecord {
  935. TrivialCommandHeader header;
  936. int boolean;
  937. int integer;
  938. double doubleValue;
  939. char *string;
  940. int index;
  941. XColor *colorPtr;
  942. Tk_Font tkfont;
  943. Pixmap bitmap;
  944. Tk_3DBorder border;
  945. int relief;
  946. Tk_Cursor cursor;
  947. Tk_Justify justify;
  948. Tk_Anchor anchor;
  949. int pixels;
  950. double mm;
  951. Tk_Window tkwin;
  952. char *custom;
  953.     } InternalRecord;
  954.     InternalRecord *recordPtr;
  955.     static char *internalStringTable[] = {
  956.     "one", "two", "three", "four", (char *) NULL
  957.     };
  958.     static Tk_OptionSpec internalSpecs[] = {
  959. {TK_OPTION_BOOLEAN,
  960. "-boolean", "boolean", "Boolean",
  961. "1", -1, Tk_Offset(InternalRecord, boolean), 0, 0, 0x1},
  962. {TK_OPTION_INT,
  963. "-integer", "integer", "Integer",
  964. "148962237", -1, Tk_Offset(InternalRecord, integer),
  965. 0, 0, 0x2},
  966. {TK_OPTION_DOUBLE,
  967. "-double", "double", "Double",
  968. "3.14159", -1, Tk_Offset(InternalRecord, doubleValue),
  969. 0, 0, 0x4},
  970. {TK_OPTION_STRING,
  971. "-string", "string", "String",
  972. "foo", -1, Tk_Offset(InternalRecord, string), 
  973. TK_CONFIG_NULL_OK, 0, 0x8},
  974. {TK_OPTION_STRING_TABLE,
  975. "-stringtable", "StringTable", "stringTable",
  976. "one", -1, Tk_Offset(InternalRecord, index),
  977. TK_CONFIG_NULL_OK, (ClientData) internalStringTable,
  978. 0x10},
  979. {TK_OPTION_COLOR,
  980. "-color", "color", "Color",
  981. "red", -1, Tk_Offset(InternalRecord, colorPtr), 
  982. TK_CONFIG_NULL_OK, (ClientData) "black", 0x20},
  983. {TK_OPTION_FONT,
  984. "-font", "font", "Font",
  985. "Helvetica 12", -1, Tk_Offset(InternalRecord, tkfont),
  986. TK_CONFIG_NULL_OK, 0, 0x40},
  987. {TK_OPTION_BITMAP,
  988. "-bitmap", "bitmap", "Bitmap",
  989. "gray50", -1, Tk_Offset(InternalRecord, bitmap),
  990. TK_CONFIG_NULL_OK, 0, 0x80},
  991. {TK_OPTION_BORDER,
  992. "-border", "border", "Border",
  993. "blue", -1, Tk_Offset(InternalRecord, border),
  994. TK_CONFIG_NULL_OK, (ClientData) "white", 0x100},
  995. {TK_OPTION_RELIEF,
  996. "-relief", "relief", "Relief",
  997. "raised", -1, Tk_Offset(InternalRecord, relief),
  998. TK_CONFIG_NULL_OK, 0, 0x200},
  999. {TK_OPTION_CURSOR,
  1000. "-cursor", "cursor", "Cursor",
  1001. "xterm", -1, Tk_Offset(InternalRecord, cursor),
  1002. TK_CONFIG_NULL_OK, 0, 0x400},
  1003. {TK_OPTION_JUSTIFY,
  1004. "-justify", (char *) NULL, (char *) NULL,
  1005. "left", -1, Tk_Offset(InternalRecord, justify),
  1006. TK_CONFIG_NULL_OK, 0, 0x800},
  1007. {TK_OPTION_ANCHOR,
  1008. "-anchor", "anchor", "Anchor",
  1009. (char *) NULL, -1, Tk_Offset(InternalRecord, anchor),
  1010. TK_CONFIG_NULL_OK, 0, 0x1000},
  1011. {TK_OPTION_PIXELS,
  1012. "-pixel", "pixel", "Pixel",
  1013. "1", -1, Tk_Offset(InternalRecord, pixels),
  1014. TK_CONFIG_NULL_OK, 0, 0x2000},
  1015. {TK_OPTION_WINDOW,
  1016. "-window", "window", "Window",
  1017. (char *) NULL, -1, Tk_Offset(InternalRecord, tkwin),
  1018. TK_CONFIG_NULL_OK, 0, 0},
  1019. {TK_OPTION_CUSTOM,
  1020.         "-custom", (char *) NULL, (char *) NULL,
  1021.         "", -1, Tk_Offset(InternalRecord, custom),
  1022.         TK_CONFIG_NULL_OK, (ClientData)&CustomOption, 0x4000},
  1023. {TK_OPTION_SYNONYM,
  1024. "-synonym", (char *) NULL, (char *) NULL,
  1025. (char *) NULL, -1, -1, 0, (ClientData) "-color",
  1026. 0x8000},
  1027. {TK_OPTION_END}
  1028.     };
  1029.     Tk_OptionTable optionTable;
  1030.     Tk_Window tkwin;
  1031.     optionTable = Tk_CreateOptionTable(interp, internalSpecs);
  1032.     tables[index] = optionTable;
  1033.     tkwin = Tk_CreateWindowFromPath(interp, (Tk_Window) clientData, 
  1034.     Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL);
  1035.     if (tkwin == NULL) {
  1036. return TCL_ERROR;
  1037.     }
  1038.     Tk_SetClass(tkwin, "Test");
  1039.     recordPtr = (InternalRecord *) ckalloc(sizeof(InternalRecord));
  1040.     recordPtr->header.interp = interp;
  1041.     recordPtr->header.optionTable = optionTable;
  1042.     recordPtr->header.tkwin = tkwin;
  1043.     recordPtr->boolean = 0;
  1044.     recordPtr->integer = 0;
  1045.     recordPtr->doubleValue = 0.0;
  1046.     recordPtr->string = NULL;
  1047.     recordPtr->index = 0;
  1048.     recordPtr->colorPtr = NULL;
  1049.     recordPtr->tkfont = NULL;
  1050.     recordPtr->bitmap = None;
  1051.     recordPtr->border = NULL;
  1052.     recordPtr->relief = TK_RELIEF_FLAT;
  1053.     recordPtr->cursor = NULL;
  1054.     recordPtr->justify = TK_JUSTIFY_LEFT;
  1055.     recordPtr->anchor = TK_ANCHOR_N;
  1056.     recordPtr->pixels = 0;
  1057.     recordPtr->mm = 0.0;
  1058.     recordPtr->tkwin = NULL;
  1059.     recordPtr->custom = NULL;
  1060.     result = Tk_InitOptions(interp, (char *) recordPtr, optionTable,
  1061.     tkwin);
  1062.     if (result == TCL_OK) {
  1063. recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
  1064. Tcl_GetStringFromObj(objv[2], NULL),
  1065. TrivialConfigObjCmd, (ClientData) recordPtr,
  1066. TrivialCmdDeletedProc);
  1067. Tk_CreateEventHandler(tkwin, StructureNotifyMask,
  1068. TrivialEventProc, (ClientData) recordPtr);
  1069. result = Tk_SetOptions(interp, (char *) recordPtr,
  1070. optionTable, objc - 3, objv + 3, tkwin,
  1071. (Tk_SavedOptions *) NULL, (int *) NULL);
  1072. if (result != TCL_OK) {
  1073.     Tk_DestroyWindow(tkwin);
  1074. }
  1075.     } else {
  1076. Tk_DestroyWindow(tkwin);
  1077. ckfree((char *) recordPtr);
  1078.     }
  1079.     if (result == TCL_OK) {
  1080. Tcl_SetObjResult(interp, objv[2]);
  1081.     }
  1082.     break;
  1083. }
  1084. case NEW: {
  1085.     typedef struct FiveRecord {
  1086. TrivialCommandHeader header;
  1087. Tcl_Obj *one;
  1088. Tcl_Obj *two;
  1089. Tcl_Obj *three;
  1090. Tcl_Obj *four;
  1091. Tcl_Obj *five;
  1092.     } FiveRecord;
  1093.     FiveRecord *recordPtr;
  1094.     static Tk_OptionSpec smallSpecs[] = {
  1095. {TK_OPTION_INT,
  1096. "-one", "one", "One",
  1097. "1",
  1098. Tk_Offset(FiveRecord, one), -1},
  1099. {TK_OPTION_INT,
  1100. "-two", "two", "Two",
  1101. "2",
  1102. Tk_Offset(FiveRecord, two), -1},
  1103. {TK_OPTION_INT,
  1104. "-three", "three", "Three",
  1105. "3",
  1106. Tk_Offset(FiveRecord, three), -1},
  1107. {TK_OPTION_INT,
  1108. "-four", "four", "Four",
  1109. "4",
  1110. Tk_Offset(FiveRecord, four), -1},
  1111. {TK_OPTION_STRING,
  1112. "-five", NULL, NULL,
  1113. NULL,
  1114. Tk_Offset(FiveRecord, five), -1},
  1115. {TK_OPTION_END}
  1116.     };
  1117.     if (objc < 3) {
  1118. Tcl_WrongNumArgs(interp, 1, objv, "new name ?options?");
  1119. return TCL_ERROR;
  1120.     }
  1121.     recordPtr = (FiveRecord *) ckalloc(sizeof(FiveRecord));
  1122.     recordPtr->header.interp = interp;
  1123.     recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
  1124.     smallSpecs);
  1125.     tables[index] = recordPtr->header.optionTable;
  1126.     recordPtr->header.tkwin = NULL;
  1127.     recordPtr->one = recordPtr->two = recordPtr->three = NULL;
  1128.     recordPtr->four = recordPtr->five = NULL;
  1129.     Tcl_SetObjResult(interp, objv[2]);
  1130.     result = Tk_InitOptions(interp, (char *) recordPtr, 
  1131.     recordPtr->header.optionTable, (Tk_Window) NULL);
  1132.     if (result == TCL_OK) {
  1133. result = Tk_SetOptions(interp, (char *) recordPtr,
  1134. recordPtr->header.optionTable, objc - 3, objv + 3,
  1135. (Tk_Window) NULL, (Tk_SavedOptions *) NULL,
  1136. (int *) NULL);
  1137. if (result == TCL_OK) {
  1138.     recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp, 
  1139.     Tcl_GetStringFromObj(objv[2], NULL),
  1140.     TrivialConfigObjCmd, (ClientData) recordPtr,
  1141.     TrivialCmdDeletedProc);
  1142. } else {
  1143.     Tk_FreeConfigOptions((char *) recordPtr,
  1144.     recordPtr->header.optionTable, (Tk_Window) NULL);
  1145. }
  1146.     }
  1147.     if (result != TCL_OK) {
  1148. ckfree((char *) recordPtr);
  1149.     }
  1150.     break;
  1151. }
  1152. case NOT_ENOUGH_PARAMS: {
  1153.     typedef struct NotEnoughRecord {
  1154. Tcl_Obj *fooObjPtr;
  1155.     } NotEnoughRecord;
  1156.     NotEnoughRecord record;
  1157.     static Tk_OptionSpec errorSpecs[] = {
  1158. {TK_OPTION_INT, 
  1159. "-foo", "foo", "Foo",
  1160. "0", Tk_Offset(NotEnoughRecord, fooObjPtr)},
  1161. {TK_OPTION_END}
  1162.     };
  1163.     Tcl_Obj *newObjPtr = Tcl_NewStringObj("-foo", -1);
  1164.     Tk_OptionTable optionTable;
  1165.     record.fooObjPtr = NULL;
  1166.     tkwin = Tk_CreateWindowFromPath(interp, mainWin,
  1167.     ".config", (char *) NULL);
  1168.     Tk_SetClass(tkwin, "Config");
  1169.     optionTable = Tk_CreateOptionTable(interp, errorSpecs);
  1170.     tables[index] = optionTable;
  1171.     Tk_InitOptions(interp, (char *) &record, optionTable, tkwin);
  1172.     if (Tk_SetOptions(interp, (char *) &record, optionTable,
  1173.     1, &newObjPtr, tkwin, (Tk_SavedOptions *) NULL,
  1174.     (int *) NULL)
  1175.     != TCL_OK) {
  1176. result = TCL_ERROR;
  1177.     }
  1178.     Tcl_DecrRefCount(newObjPtr);
  1179.     Tk_FreeConfigOptions( (char *) &record, optionTable, tkwin);
  1180.     Tk_DestroyWindow(tkwin);
  1181.     return result;
  1182. }
  1183. case TWO_WINDOWS: {
  1184.     typedef struct SlaveRecord {
  1185. TrivialCommandHeader header;
  1186. Tcl_Obj *windowPtr;
  1187.     } SlaveRecord;
  1188.     SlaveRecord *recordPtr;
  1189.     static Tk_OptionSpec slaveSpecs[] = {
  1190. {TK_OPTION_WINDOW,
  1191. "-window", "window", "Window",
  1192. ".bar", Tk_Offset(SlaveRecord, windowPtr), -1,
  1193. TK_CONFIG_NULL_OK},
  1194.        {TK_OPTION_END}
  1195.     };
  1196.     Tk_Window tkwin = Tk_CreateWindowFromPath(interp,
  1197.     (Tk_Window) clientData,
  1198.     Tcl_GetStringFromObj(objv[2], NULL), (char *) NULL);
  1199.     if (tkwin == NULL) {
  1200. return TCL_ERROR;
  1201.     }
  1202.     Tk_SetClass(tkwin, "Test");
  1203.     recordPtr = (SlaveRecord *) ckalloc(sizeof(SlaveRecord));
  1204.     recordPtr->header.interp = interp;
  1205.     recordPtr->header.optionTable = Tk_CreateOptionTable(interp,
  1206.     slaveSpecs);
  1207.     tables[index] = recordPtr->header.optionTable;
  1208.     recordPtr->header.tkwin = tkwin;
  1209.     recordPtr->windowPtr = NULL;
  1210.     result = Tk_InitOptions(interp,  (char *) recordPtr, 
  1211.     recordPtr->header.optionTable, tkwin);
  1212.     if (result == TCL_OK) {
  1213. result = Tk_SetOptions(interp, (char *) recordPtr, 
  1214. recordPtr->header.optionTable, objc - 3, objv + 3,
  1215. tkwin, (Tk_SavedOptions *) NULL, (int *) NULL);
  1216. if (result == TCL_OK) {
  1217.     recordPtr->header.widgetCmd = Tcl_CreateObjCommand(interp,
  1218.     Tcl_GetStringFromObj(objv[2], NULL),
  1219.     TrivialConfigObjCmd, (ClientData) recordPtr,
  1220.     TrivialCmdDeletedProc);
  1221.     Tk_CreateEventHandler(tkwin, StructureNotifyMask,
  1222.     TrivialEventProc, (ClientData) recordPtr);
  1223.     Tcl_SetObjResult(interp, objv[2]);
  1224. } else {
  1225.     Tk_FreeConfigOptions((char *) recordPtr, 
  1226.     recordPtr->header.optionTable, tkwin);
  1227. }
  1228.     }
  1229.     if (result != TCL_OK) {
  1230. Tk_DestroyWindow(tkwin);
  1231. ckfree((char *) recordPtr);
  1232.     }
  1233. }
  1234.     }
  1235.     return result;
  1236. }
  1237. /*
  1238.  *----------------------------------------------------------------------
  1239.  *
  1240.  * TrivialConfigObjCmd --
  1241.  *
  1242.  * This command is used to test the configuration package. It only
  1243.  * handles the "configure" and "cget" subcommands.
  1244.  *
  1245.  * Results:
  1246.  * A standard Tcl result.
  1247.  *
  1248.  * Side effects:
  1249.  * None.
  1250.  *
  1251.  *----------------------------------------------------------------------
  1252.  */
  1253. /* ARGSUSED */
  1254. static int
  1255. TrivialConfigObjCmd(clientData, interp, objc, objv)
  1256.     ClientData clientData; /* Main window for application. */
  1257.     Tcl_Interp *interp; /* Current interpreter. */
  1258.     int objc; /* Number of arguments. */
  1259.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1260. {
  1261.     int result = TCL_OK;
  1262.     static CONST char *options[] = {
  1263. "cget", "configure", "csave", (char *) NULL
  1264.     };
  1265.     enum {
  1266. CGET, CONFIGURE, CSAVE
  1267.     };
  1268.     Tcl_Obj *resultObjPtr;
  1269.     int index, mask;
  1270.     TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
  1271.     Tk_Window tkwin = headerPtr->tkwin;
  1272.     Tk_SavedOptions saved;
  1273.     if (objc < 2) {
  1274. Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg...?");
  1275. return TCL_ERROR;
  1276.     }
  1277.     if (Tcl_GetIndexFromObj(interp, objv[1], options, "command",
  1278.     0, &index) != TCL_OK) {
  1279. return TCL_ERROR;
  1280.     }
  1281.     Tcl_Preserve(clientData);
  1282.     
  1283.     switch (index) {
  1284. case CGET: {
  1285.     if (objc != 3) {
  1286. Tcl_WrongNumArgs(interp, 2, objv, "option");
  1287. result = TCL_ERROR;
  1288. goto done;
  1289.     }
  1290.     resultObjPtr = Tk_GetOptionValue(interp, (char *) clientData, 
  1291.     headerPtr->optionTable, objv[2], tkwin);
  1292.     if (resultObjPtr != NULL) {
  1293. Tcl_SetObjResult(interp, resultObjPtr);
  1294. result = TCL_OK;
  1295.     } else {
  1296. result = TCL_ERROR;
  1297.     }
  1298.     break;
  1299. }
  1300. case CONFIGURE: {
  1301.     if (objc == 2) {
  1302. resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData, 
  1303. headerPtr->optionTable, (Tcl_Obj *) NULL, tkwin);
  1304. if (resultObjPtr == NULL) {
  1305.     result = TCL_ERROR;
  1306. } else {
  1307.     Tcl_SetObjResult(interp, resultObjPtr);
  1308. }
  1309.     } else if (objc == 3) {
  1310. resultObjPtr = Tk_GetOptionInfo(interp, (char *) clientData,
  1311. headerPtr->optionTable, objv[2], tkwin);
  1312. if (resultObjPtr == NULL) {
  1313.     result = TCL_ERROR;
  1314. } else {
  1315.     Tcl_SetObjResult(interp, resultObjPtr);
  1316. }
  1317.     } else {
  1318. result = Tk_SetOptions(interp, (char *) clientData,
  1319. headerPtr->optionTable, objc - 2, objv + 2, 
  1320. tkwin, (Tk_SavedOptions *) NULL, &mask);
  1321. if (result == TCL_OK) {
  1322.     Tcl_SetIntObj(Tcl_GetObjResult(interp), mask);
  1323. }
  1324.     }
  1325.     break;
  1326. }
  1327. case CSAVE: {
  1328.     result = Tk_SetOptions(interp, (char *) clientData,
  1329. headerPtr->optionTable, objc - 2, objv + 2, 
  1330. tkwin, &saved, &mask);
  1331.     Tk_FreeSavedOptions(&saved);
  1332.     if (result == TCL_OK) {
  1333. Tcl_SetIntObj(Tcl_GetObjResult(interp), mask);
  1334.     }
  1335.     break;
  1336. }
  1337.     }
  1338. done:
  1339.     Tcl_Release(clientData);
  1340.     return result;
  1341. }
  1342. /*
  1343.  *----------------------------------------------------------------------
  1344.  *
  1345.  * TrivialCmdDeletedProc --
  1346.  *
  1347.  * This procedure is invoked when a widget command is deleted.  If
  1348.  * the widget isn't already in the process of being destroyed,
  1349.  * this command destroys it.
  1350.  *
  1351.  * Results:
  1352.  * None.
  1353.  *
  1354.  * Side effects:
  1355.  * The widget is destroyed.
  1356.  *
  1357.  *----------------------------------------------------------------------
  1358.  */
  1359. static void
  1360. TrivialCmdDeletedProc(clientData)
  1361.     ClientData clientData; /* Pointer to widget record for widget. */
  1362. {
  1363.     TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
  1364.     Tk_Window tkwin = headerPtr->tkwin;
  1365.     if (tkwin != NULL) {
  1366. Tk_DestroyWindow(tkwin);
  1367.     } else if (headerPtr->optionTable != NULL) {
  1368. /*
  1369.  * This is a "new" object, which doesn't have a window, so
  1370.  * we can't depend on cleaning up in the event procedure.
  1371.  * Free its resources here.
  1372.  */
  1373. Tk_FreeConfigOptions((char *) clientData,
  1374. headerPtr->optionTable, (Tk_Window) NULL);
  1375. Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
  1376.     }
  1377. }
  1378. /*
  1379.  *--------------------------------------------------------------
  1380.  *
  1381.  * TrivialEventProc --
  1382.  *
  1383.  * A dummy event proc.
  1384.  *
  1385.  * Results:
  1386.  * None.
  1387.  *
  1388.  * Side effects:
  1389.  * When the window gets deleted, internal structures get
  1390.  * cleaned up.
  1391.  *
  1392.  *--------------------------------------------------------------
  1393.  */
  1394. static void
  1395. TrivialEventProc(clientData, eventPtr)
  1396.     ClientData clientData; /* Information about window. */
  1397.     XEvent *eventPtr; /* Information about event. */
  1398. {
  1399.     TrivialCommandHeader *headerPtr = (TrivialCommandHeader *) clientData;
  1400.     if (eventPtr->type == DestroyNotify) {
  1401. if (headerPtr->tkwin != NULL) {
  1402.     Tk_FreeConfigOptions((char *) clientData,
  1403.     headerPtr->optionTable, headerPtr->tkwin);
  1404.     headerPtr->optionTable = NULL;
  1405.     headerPtr->tkwin = NULL;
  1406.     Tcl_DeleteCommandFromToken(headerPtr->interp,
  1407.     headerPtr->widgetCmd);
  1408. }
  1409. Tcl_EventuallyFree(clientData, TCL_DYNAMIC);
  1410.     }
  1411. }
  1412. /*
  1413.  *----------------------------------------------------------------------
  1414.  *
  1415.  * TestfontObjCmd --
  1416.  *
  1417.  * This procedure implements the "testfont" command, which is used
  1418.  * to test TkFont objects.
  1419.  *
  1420.  * Results:
  1421.  * A standard Tcl result.
  1422.  *
  1423.  * Side effects:
  1424.  * None.
  1425.  *
  1426.  *----------------------------------------------------------------------
  1427.  */
  1428. /* ARGSUSED */
  1429. static int
  1430. TestfontObjCmd(clientData, interp, objc, objv)
  1431.     ClientData clientData; /* Main window for application. */
  1432.     Tcl_Interp *interp; /* Current interpreter. */
  1433.     int objc; /* Number of arguments. */
  1434.     Tcl_Obj *CONST objv[]; /* Argument objects. */
  1435. {
  1436.     static CONST char *options[] = {"counts", "subfonts", (char *) NULL};
  1437.     enum option {COUNTS, SUBFONTS};
  1438.     int index;
  1439.     Tk_Window tkwin;
  1440.     Tk_Font tkfont;
  1441.     
  1442.     tkwin = (Tk_Window) clientData;
  1443.     if (objc < 3) {
  1444. Tcl_WrongNumArgs(interp, 1, objv, "option fontName");
  1445. return TCL_ERROR;
  1446.     }
  1447.     if (Tcl_GetIndexFromObj(interp, objv[1], options, "command", 0, &index)
  1448.     != TCL_OK) {
  1449. return TCL_ERROR;
  1450.     }
  1451.     switch ((enum option) index) {
  1452. case COUNTS: {
  1453.     Tcl_SetObjResult(interp, TkDebugFont(Tk_MainWindow(interp),
  1454.     Tcl_GetString(objv[2])));
  1455.     break;
  1456. }
  1457. case SUBFONTS: {
  1458.     tkfont = Tk_AllocFontFromObj(interp, tkwin, objv[2]);
  1459.     if (tkfont == NULL) {
  1460. return TCL_ERROR;
  1461.     }
  1462.     TkpGetSubFonts(interp, tkfont);
  1463.     Tk_FreeFont(tkfont);
  1464.     break;
  1465. }
  1466.     }
  1467.     return TCL_OK;
  1468. }
  1469. /*
  1470.  *----------------------------------------------------------------------
  1471.  *
  1472.  * ImageCreate --
  1473.  *
  1474.  * This procedure is called by the Tk image code to create "test"
  1475.  * images.
  1476.  *
  1477.  * Results:
  1478.  * A standard Tcl result.
  1479.  *
  1480.  * Side effects:
  1481.  * The data structure for a new image is allocated.
  1482.  *
  1483.  *----------------------------------------------------------------------
  1484.  */
  1485. /* ARGSUSED */
  1486. #ifdef USE_OLD_IMAGE
  1487. static int
  1488. ImageCreate(interp, name, argc, argv, typePtr, master, clientDataPtr)
  1489.     Tcl_Interp *interp; /* Interpreter for application containing
  1490.  * image. */
  1491.     char *name; /* Name to use for image. */
  1492.     int argc; /* Number of arguments. */
  1493.     char **argv; /* Argument strings for options (doesn't
  1494.  * include image name or type). */
  1495.     Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
  1496.     Tk_ImageMaster master; /* Token for image, to be used by us in
  1497.  * later callbacks. */
  1498.     ClientData *clientDataPtr; /* Store manager's token for image here;
  1499.  * it will be returned in later callbacks. */
  1500. {
  1501.     TImageMaster *timPtr;
  1502.     char *varName;
  1503.     int i;
  1504.     Tk_InitImageArgs(interp, argc, &argv);
  1505.     varName = "log";
  1506.     for (i = 0; i < argc; i += 2) {
  1507. if (strcmp(argv[i], "-variable") != 0) {
  1508.     Tcl_AppendResult(interp, "bad option name "",
  1509.     argv[i], """, (char *) NULL);
  1510.     return TCL_ERROR;
  1511. }
  1512. if ((i+1) == argc) {
  1513.     Tcl_AppendResult(interp, "no value given for "",
  1514.     argv[i], "" option", (char *) NULL);
  1515.     return TCL_ERROR;
  1516. }
  1517. varName = argv[i+1];
  1518.     }
  1519. #else
  1520. static int
  1521. ImageCreate(interp, name, objc, objv, typePtr, master, clientDataPtr)
  1522.     Tcl_Interp *interp; /* Interpreter for application containing
  1523.  * image. */
  1524.     char *name; /* Name to use for image. */
  1525.     int objc; /* Number of arguments. */
  1526.     Tcl_Obj *CONST objv[]; /* Argument strings for options (doesn't
  1527.  * include image name or type). */
  1528.     Tk_ImageType *typePtr; /* Pointer to our type record (not used). */
  1529.     Tk_ImageMaster master; /* Token for image, to be used by us in
  1530.  * later callbacks. */
  1531.     ClientData *clientDataPtr; /* Store manager's token for image here;
  1532.  * it will be returned in later callbacks. */
  1533. {
  1534.     TImageMaster *timPtr;
  1535.     char *varName;
  1536.     int i;
  1537.     varName = "log";
  1538.     for (i = 0; i < objc; i += 2) {
  1539. if (strcmp(Tcl_GetString(objv[i]), "-variable") != 0) {
  1540.     Tcl_AppendResult(interp, "bad option name "",
  1541.     Tcl_GetString(objv[i]), """, (char *) NULL);
  1542.     return TCL_ERROR;
  1543. }
  1544. if ((i+1) == objc) {
  1545.     Tcl_AppendResult(interp, "no value given for "",
  1546.     Tcl_GetString(objv[i]), "" option", (char *) NULL);
  1547.     return TCL_ERROR;
  1548. }
  1549. varName = Tcl_GetString(objv[i+1]);
  1550.     }
  1551. #endif
  1552.     timPtr = (TImageMaster *) ckalloc(sizeof(TImageMaster));
  1553.     timPtr->master = master;
  1554.     timPtr->interp = interp;
  1555.     timPtr->width = 30;
  1556.     timPtr->height = 15;
  1557.     timPtr->imageName = (char *) ckalloc((unsigned) (strlen(name) + 1));
  1558.     strcpy(timPtr->imageName, name);
  1559.     timPtr->varName = (char *) ckalloc((unsigned) (strlen(varName) + 1));
  1560.     strcpy(timPtr->varName, varName);
  1561.     Tcl_CreateCommand(interp, name, ImageCmd, (ClientData) timPtr,
  1562.     (Tcl_CmdDeleteProc *) NULL);
  1563.     *clientDataPtr = (ClientData) timPtr;
  1564.     Tk_ImageChanged(master, 0, 0, 30, 15, 30, 15);
  1565.     return TCL_OK;
  1566. }
  1567. /*
  1568.  *----------------------------------------------------------------------
  1569.  *
  1570.  * ImageCmd --
  1571.  *
  1572.  * This procedure implements the commands corresponding to individual
  1573.  * images. 
  1574.  *
  1575.  * Results:
  1576.  * A standard Tcl result.
  1577.  *
  1578.  * Side effects:
  1579.  * Forces windows to be created.
  1580.  *
  1581.  *----------------------------------------------------------------------
  1582.  */
  1583. /* ARGSUSED */
  1584. static int
  1585. ImageCmd(clientData, interp, argc, argv)
  1586.     ClientData clientData; /* Main window for application. */
  1587.     Tcl_Interp *interp; /* Current interpreter. */
  1588.     int argc; /* Number of arguments. */
  1589.     CONST char **argv; /* Argument strings. */
  1590. {
  1591.     TImageMaster *timPtr = (TImageMaster *) clientData;
  1592.     int x, y, width, height;
  1593.     if (argc < 2) {
  1594. Tcl_AppendResult(interp, "wrong # args: should be "",
  1595. argv[0], "option ?arg arg ...?", (char *) NULL);
  1596. return TCL_ERROR;
  1597.     }
  1598.     if (strcmp(argv[1], "changed") == 0) {
  1599. if (argc != 8) {
  1600.     Tcl_AppendResult(interp, "wrong # args: should be "",
  1601.     argv[0],
  1602.     " changed x y width height imageWidth imageHeight",
  1603.     (char *) NULL);
  1604.     return TCL_ERROR;
  1605. }
  1606. if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
  1607. || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)
  1608. || (Tcl_GetInt(interp, argv[4], &width) != TCL_OK)
  1609. || (Tcl_GetInt(interp, argv[5], &height) != TCL_OK)
  1610. || (Tcl_GetInt(interp, argv[6], &timPtr->width) != TCL_OK)
  1611. || (Tcl_GetInt(interp, argv[7], &timPtr->height) != TCL_OK)) {
  1612.     return TCL_ERROR;
  1613. }
  1614. Tk_ImageChanged(timPtr->master, x, y, width, height, timPtr->width,
  1615. timPtr->height);
  1616.     } else {
  1617. Tcl_AppendResult(interp, "bad option "", argv[1],
  1618. "": must be changed", (char *) NULL);
  1619. return TCL_ERROR;
  1620.     }
  1621.     return TCL_OK;
  1622. }
  1623. /*
  1624.  *----------------------------------------------------------------------
  1625.  *
  1626.  * ImageGet --
  1627.  *
  1628.  * This procedure is called by Tk to set things up for using a
  1629.  * test image in a particular widget.
  1630.  *
  1631.  * Results:
  1632.  * The return value is a token for the image instance, which is
  1633.  * used in future callbacks to ImageDisplay and ImageFree.
  1634.  *
  1635.  * Side effects:
  1636.  * None.
  1637.  *
  1638.  *----------------------------------------------------------------------
  1639.  */
  1640. static ClientData
  1641. ImageGet(tkwin, clientData)
  1642.     Tk_Window tkwin; /* Token for window in which image will
  1643.  * be used. */
  1644.     ClientData clientData; /* Pointer to TImageMaster for image. */
  1645. {
  1646.     TImageMaster *timPtr = (TImageMaster *) clientData;
  1647.     TImageInstance *instPtr;
  1648.     char buffer[100];
  1649.     XGCValues gcValues;
  1650.     sprintf(buffer, "%s get", timPtr->imageName);
  1651.     Tcl_SetVar(timPtr->interp, timPtr->varName, buffer,
  1652.     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
  1653.     instPtr = (TImageInstance *) ckalloc(sizeof(TImageInstance));
  1654.     instPtr->masterPtr = timPtr;
  1655.     instPtr->fg = Tk_GetColor(timPtr->interp, tkwin, "#ff0000");
  1656.     gcValues.foreground = instPtr->fg->pixel;
  1657.     instPtr->gc = Tk_GetGC(tkwin, GCForeground, &gcValues);
  1658.     return (ClientData) instPtr;
  1659. }
  1660. /*
  1661.  *----------------------------------------------------------------------
  1662.  *
  1663.  * ImageDisplay --
  1664.  *
  1665.  * This procedure is invoked to redisplay part or all of an
  1666.  * image in a given drawable.
  1667.  *
  1668.  * Results:
  1669.  * None.
  1670.  *
  1671.  * Side effects:
  1672.  * The image gets partially redrawn, as an "X" that shows the
  1673.  * exact redraw area.
  1674.  *
  1675.  *----------------------------------------------------------------------
  1676.  */
  1677. static void
  1678. ImageDisplay(clientData, display, drawable, imageX, imageY, width, height,
  1679. drawableX, drawableY)
  1680.     ClientData clientData; /* Pointer to TImageInstance for image. */
  1681.     Display *display; /* Display to use for drawing. */
  1682.     Drawable drawable; /* Where to redraw image. */
  1683.     int imageX, imageY; /* Origin of area to redraw, relative to
  1684.  * origin of image. */
  1685.     int width, height; /* Dimensions of area to redraw. */
  1686.     int drawableX, drawableY; /* Coordinates in drawable corresponding to
  1687.  * imageX and imageY. */
  1688. {
  1689.     TImageInstance *instPtr = (TImageInstance *) clientData;
  1690.     char buffer[200 + TCL_INTEGER_SPACE * 6];
  1691.     sprintf(buffer, "%s display %d %d %d %d %d %d",
  1692.     instPtr->masterPtr->imageName, imageX, imageY, width, height,
  1693.     drawableX, drawableY);
  1694.     Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer,
  1695.     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
  1696.     if (width > (instPtr->masterPtr->width - imageX)) {
  1697. width = instPtr->masterPtr->width - imageX;
  1698.     }
  1699.     if (height > (instPtr->masterPtr->height - imageY)) {
  1700. height = instPtr->masterPtr->height - imageY;
  1701.     }
  1702.     XDrawRectangle(display, drawable, instPtr->gc, drawableX, drawableY,
  1703.     (unsigned) (width-1), (unsigned) (height-1));
  1704.     XDrawLine(display, drawable, instPtr->gc, drawableX, drawableY,
  1705.     (int) (drawableX + width - 1), (int) (drawableY + height - 1));
  1706.     XDrawLine(display, drawable, instPtr->gc, drawableX,
  1707.     (int) (drawableY + height - 1),
  1708.     (int) (drawableX + width - 1), drawableY);
  1709. }
  1710. /*
  1711.  *----------------------------------------------------------------------
  1712.  *
  1713.  * ImageFree --
  1714.  *
  1715.  * This procedure is called when an instance of an image is
  1716.  *  no longer used.
  1717.  *
  1718.  * Results:
  1719.  * None.
  1720.  *
  1721.  * Side effects:
  1722.  * Information related to the instance is freed.
  1723.  *
  1724.  *----------------------------------------------------------------------
  1725.  */
  1726. static void
  1727. ImageFree(clientData, display)
  1728.     ClientData clientData; /* Pointer to TImageInstance for instance. */
  1729.     Display *display; /* Display where image was to be drawn. */
  1730. {
  1731.     TImageInstance *instPtr = (TImageInstance *) clientData;
  1732.     char buffer[200];
  1733.     sprintf(buffer, "%s free", instPtr->masterPtr->imageName);
  1734.     Tcl_SetVar(instPtr->masterPtr->interp, instPtr->masterPtr->varName, buffer,
  1735.     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
  1736.     Tk_FreeColor(instPtr->fg);
  1737.     Tk_FreeGC(display, instPtr->gc);
  1738.     ckfree((char *) instPtr);
  1739. }
  1740. /*
  1741.  *----------------------------------------------------------------------
  1742.  *
  1743.  * ImageDelete --
  1744.  *
  1745.  * This procedure is called to clean up a test image when
  1746.  * an application goes away.
  1747.  *
  1748.  * Results:
  1749.  * None.
  1750.  *
  1751.  * Side effects:
  1752.  * Information about the image is deleted.
  1753.  *
  1754.  *----------------------------------------------------------------------
  1755.  */
  1756. static void
  1757. ImageDelete(clientData)
  1758.     ClientData clientData; /* Pointer to TImageMaster for image.  When
  1759.  * this procedure is called, no more
  1760.  * instances exist. */
  1761. {
  1762.     TImageMaster *timPtr = (TImageMaster *) clientData;
  1763.     char buffer[100];
  1764.     sprintf(buffer, "%s delete", timPtr->imageName);
  1765.     Tcl_SetVar(timPtr->interp, timPtr->varName, buffer,
  1766.     TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
  1767.     Tcl_DeleteCommand(timPtr->interp, timPtr->imageName);
  1768.     ckfree(timPtr->imageName);
  1769.     ckfree(timPtr->varName);
  1770.     ckfree((char *) timPtr);
  1771. }
  1772. /*
  1773.  *----------------------------------------------------------------------
  1774.  *
  1775.  * TestmakeexistCmd --
  1776.  *
  1777.  * This procedure implements the "testmakeexist" command.  It calls
  1778.  * Tk_MakeWindowExist on each of its arguments to force the windows
  1779.  * to be created.
  1780.  *
  1781.  * Results:
  1782.  * A standard Tcl result.
  1783.  *
  1784.  * Side effects:
  1785.  * Forces windows to be created.
  1786.  *
  1787.  *----------------------------------------------------------------------
  1788.  */
  1789. /* ARGSUSED */
  1790. static int
  1791. TestmakeexistCmd(clientData, interp, argc, argv)
  1792.     ClientData clientData; /* Main window for application. */
  1793.     Tcl_Interp *interp; /* Current interpreter. */
  1794.     int argc; /* Number of arguments. */
  1795.     CONST char **argv; /* Argument strings. */
  1796. {
  1797.     Tk_Window mainWin = (Tk_Window) clientData;
  1798.     int i;
  1799.     Tk_Window tkwin;
  1800.     for (i = 1; i < argc; i++) {
  1801. tkwin = Tk_NameToWindow(interp, argv[i], mainWin);
  1802. if (tkwin == NULL) {
  1803.     return TCL_ERROR;
  1804. }
  1805. Tk_MakeWindowExist(tkwin);
  1806.     }
  1807.     return TCL_OK;
  1808. }
  1809. /*
  1810.  *----------------------------------------------------------------------
  1811.  *
  1812.  * TestmenubarCmd --
  1813.  *
  1814.  * This procedure implements the "testmenubar" command.  It is used
  1815.  * to test the Unix facilities for creating space above a toplevel
  1816.  * window for a menubar.
  1817.  *
  1818.  * Results:
  1819.  * A standard Tcl result.
  1820.  *
  1821.  * Side effects:
  1822.  * Changes menubar related stuff.
  1823.  *
  1824.  *----------------------------------------------------------------------
  1825.  */
  1826. /* ARGSUSED */
  1827. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  1828. static int
  1829. TestmenubarCmd(clientData, interp, argc, argv)
  1830.     ClientData clientData; /* Main window for application. */
  1831.     Tcl_Interp *interp; /* Current interpreter. */
  1832.     int argc; /* Number of arguments. */
  1833.     CONST char **argv; /* Argument strings. */
  1834. {
  1835. #ifdef __UNIX__
  1836.     Tk_Window mainWin = (Tk_Window) clientData;
  1837.     Tk_Window tkwin, menubar;
  1838.     if (argc < 2) {
  1839. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  1840. " option ?arg ...?"", (char *) NULL);
  1841. return TCL_ERROR;
  1842.     }
  1843.     if (strcmp(argv[1], "window") == 0) {
  1844. if (argc != 4) {
  1845.     Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  1846.     "window toplevel menubar"", (char *) NULL);
  1847.     return TCL_ERROR;
  1848. }
  1849. tkwin = Tk_NameToWindow(interp, argv[2], mainWin);
  1850. if (tkwin == NULL) {
  1851.     return TCL_ERROR;
  1852. }
  1853. if (argv[3][0] == 0) {
  1854.     TkUnixSetMenubar(tkwin, NULL);
  1855. } else {
  1856.     menubar = Tk_NameToWindow(interp, argv[3], mainWin);
  1857.     if (menubar == NULL) {
  1858. return TCL_ERROR;
  1859.     }
  1860.     TkUnixSetMenubar(tkwin, menubar);
  1861. }
  1862.     } else {
  1863. Tcl_AppendResult(interp, "bad option "", argv[1],
  1864. "": must be  window", (char *) NULL);
  1865. return TCL_ERROR;
  1866.     }
  1867.     return TCL_OK;
  1868. #else
  1869.     Tcl_SetResult(interp, "testmenubar is supported only under Unix",
  1870.     TCL_STATIC);
  1871.     return TCL_ERROR;
  1872. #endif
  1873. }
  1874. #endif
  1875. /*
  1876.  *----------------------------------------------------------------------
  1877.  *
  1878.  * TestmetricsCmd --
  1879.  *
  1880.  * This procedure implements the testmetrics command. It provides
  1881.  * a way to determine the size of various widget components.
  1882.  *
  1883.  * Results:
  1884.  * A standard Tcl result.
  1885.  *
  1886.  * Side effects:
  1887.  * None.
  1888.  *
  1889.  *----------------------------------------------------------------------
  1890.  */
  1891. #if defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK)
  1892. static int
  1893. TestmetricsCmd(clientData, interp, argc, argv)
  1894.     ClientData clientData; /* Main window for application. */
  1895.     Tcl_Interp *interp; /* Current interpreter. */
  1896.     int argc; /* Number of arguments. */
  1897.     CONST char **argv; /* Argument strings. */
  1898. {
  1899.     char buf[TCL_INTEGER_SPACE];
  1900.     int val;
  1901. #ifdef __WIN32__
  1902.     if (argc < 2) {
  1903. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  1904. " option ?arg ...?"", (char *) NULL);
  1905. return TCL_ERROR;
  1906.     }
  1907. #else
  1908.     Tk_Window tkwin = (Tk_Window) clientData;
  1909.     TkWindow *winPtr;
  1910.     if (argc != 3) {
  1911. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  1912. " option window"", (char *) NULL);
  1913. return TCL_ERROR;
  1914.     }
  1915.     winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin);
  1916.     if (winPtr == NULL) {
  1917. return TCL_ERROR;
  1918.     }
  1919. #endif
  1920.     if (strcmp(argv[1], "cyvscroll") == 0) {
  1921. #ifdef __WIN32__
  1922. val = GetSystemMetrics(SM_CYVSCROLL);
  1923. #else
  1924. val = ((TkScrollbar *) winPtr->instanceData)->width;
  1925. #endif
  1926.     } else  if (strcmp(argv[1], "cxhscroll") == 0) {
  1927. #ifdef __WIN32__
  1928. val = GetSystemMetrics(SM_CXHSCROLL);
  1929. #else
  1930. val = ((TkScrollbar *) winPtr->instanceData)->width;
  1931. #endif
  1932.     } else {
  1933. Tcl_AppendResult(interp, "bad option "", argv[1],
  1934. "": must be cxhscroll or cyvscroll", (char *) NULL);
  1935. return TCL_ERROR;
  1936.     }
  1937.     sprintf(buf, "%d", val);
  1938.     Tcl_AppendResult(interp, buf, (char *) NULL);
  1939.     return TCL_OK;
  1940. }
  1941. #endif
  1942. /*
  1943.  *----------------------------------------------------------------------
  1944.  *
  1945.  * TestpropCmd --
  1946.  *
  1947.  * This procedure implements the "testprop" command.  It fetches
  1948.  * and prints the value of a property on a window.
  1949.  *
  1950.  * Results:
  1951.  * A standard Tcl result.
  1952.  *
  1953.  * Side effects:
  1954.  * None.
  1955.  *
  1956.  *----------------------------------------------------------------------
  1957.  */
  1958. /* ARGSUSED */
  1959. static int
  1960. TestpropCmd(clientData, interp, argc, argv)
  1961.     ClientData clientData; /* Main window for application. */
  1962.     Tcl_Interp *interp; /* Current interpreter. */
  1963.     int argc; /* Number of arguments. */
  1964.     CONST char **argv; /* Argument strings. */
  1965. {
  1966.     Tk_Window mainWin = (Tk_Window) clientData;
  1967.     int result, actualFormat;
  1968.     unsigned long bytesAfter, length, value;
  1969.     Atom actualType, propName;
  1970.     char *property, *p, *end;
  1971.     Window w;
  1972.     char buffer[30];
  1973.     if (argc != 3) {
  1974. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  1975. " window property"", (char *) NULL);
  1976. return TCL_ERROR;
  1977.     }
  1978.     w = strtoul(argv[1], &end, 0);
  1979.     propName = Tk_InternAtom(mainWin, argv[2]);
  1980.     property = NULL;
  1981.     result = XGetWindowProperty(Tk_Display(mainWin),
  1982.     w, propName, 0, 100000, False, AnyPropertyType,
  1983.     &actualType, &actualFormat, &length,
  1984.     &bytesAfter, (unsigned char **) &property);
  1985.     if ((result == Success) && (actualType != None)) {
  1986. if ((actualFormat == 8) && (actualType == XA_STRING)) {
  1987.     for (p = property; ((unsigned long)(p-property)) < length; p++) {
  1988. if (*p == 0) {
  1989.     *p = 'n';
  1990. }
  1991.     }
  1992.     Tcl_SetResult(interp, property, TCL_VOLATILE);
  1993. } else {
  1994.     for (p = property; length > 0; length--) {
  1995. if (actualFormat == 32) {
  1996.     value = *((long *) p);
  1997.     p += sizeof(long);
  1998. } else if (actualFormat == 16) {
  1999.     value = 0xffff & (*((short *) p));
  2000.     p += sizeof(short);
  2001. } else {
  2002.     value = 0xff & *p;
  2003.     p += 1;
  2004. }
  2005. sprintf(buffer, "0x%lx", value);
  2006. Tcl_AppendElement(interp, buffer);
  2007.     }
  2008. }
  2009.     }
  2010.     if (property != NULL) {
  2011. XFree(property);
  2012.     }
  2013.     return TCL_OK;
  2014. }
  2015. /*
  2016.  *----------------------------------------------------------------------
  2017.  *
  2018.  * TestsendCmd --
  2019.  *
  2020.  * This procedure implements the "testsend" command.  It provides
  2021.  * a set of functions for testing the "send" command and support
  2022.  * procedure in tkSend.c.
  2023.  *
  2024.  * Results:
  2025.  * A standard Tcl result.
  2026.  *
  2027.  * Side effects:
  2028.  * Depends on option;  see below.
  2029.  *
  2030.  *----------------------------------------------------------------------
  2031.  */
  2032. /* ARGSUSED */
  2033. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  2034. static int
  2035. TestsendCmd(clientData, interp, argc, argv)
  2036.     ClientData clientData; /* Main window for application. */
  2037.     Tcl_Interp *interp; /* Current interpreter. */
  2038.     int argc; /* Number of arguments. */
  2039.     CONST char **argv; /* Argument strings. */
  2040. {
  2041.     TkWindow *winPtr = (TkWindow *) clientData;
  2042.     if (argc < 2) {
  2043. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  2044. " option ?arg ...?"", (char *) NULL);
  2045. return TCL_ERROR;
  2046.     }
  2047.     if (strcmp(argv[1], "bogus") == 0) {
  2048. XChangeProperty(winPtr->dispPtr->display,
  2049. RootWindow(winPtr->dispPtr->display, 0),
  2050. winPtr->dispPtr->registryProperty, XA_INTEGER, 32,
  2051. PropModeReplace,
  2052. (unsigned char *) "This is bogus information", 6);
  2053.     } else if (strcmp(argv[1], "prop") == 0) {
  2054. int result, actualFormat;
  2055. unsigned long length, bytesAfter;
  2056. Atom actualType, propName;
  2057. char *property, *p, *end;
  2058. Window w;
  2059. if ((argc != 4) && (argc != 5)) {
  2060.     Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  2061.     " prop window name ?value ?"", (char *) NULL);
  2062.     return TCL_ERROR;
  2063. }
  2064. if (strcmp(argv[2], "root") == 0) {
  2065.     w = RootWindow(winPtr->dispPtr->display, 0);
  2066. } else if (strcmp(argv[2], "comm") == 0) {
  2067.     w = Tk_WindowId(winPtr->dispPtr->commTkwin);
  2068. } else {
  2069.     w = strtoul(argv[2], &end, 0);
  2070. }
  2071. propName = Tk_InternAtom((Tk_Window) winPtr, argv[3]);
  2072. if (argc == 4) {
  2073.     property = NULL;
  2074.     result = XGetWindowProperty(winPtr->dispPtr->display,
  2075.     w, propName, 0, 100000, False, XA_STRING,
  2076.     &actualType, &actualFormat, &length,
  2077.     &bytesAfter, (unsigned char **) &property);
  2078.     if ((result == Success) && (actualType != None)
  2079.     && (actualFormat == 8) && (actualType == XA_STRING)) {
  2080. for (p = property; (p-property) < length; p++) {
  2081.     if (*p == 0) {
  2082. *p = 'n';
  2083.     }
  2084. }
  2085. Tcl_SetResult(interp, property, TCL_VOLATILE);
  2086.     }
  2087.     if (property != NULL) {
  2088. XFree(property);
  2089.     }
  2090. } else {
  2091.     if (argv[4][0] == 0) {
  2092. XDeleteProperty(winPtr->dispPtr->display, w, propName);
  2093.     } else {
  2094. Tcl_DString tmp;
  2095. Tcl_DStringInit(&tmp);
  2096. for (p = Tcl_DStringAppend(&tmp, argv[4],
  2097. (int) strlen(argv[4]));
  2098. *p != 0; p++) {
  2099.     if (*p == 'n') {
  2100. *p = 0;
  2101.     }
  2102. }
  2103. XChangeProperty(winPtr->dispPtr->display,
  2104. w, propName, XA_STRING, 8, PropModeReplace,
  2105. (unsigned char *) Tcl_DStringValue(&tmp),
  2106. p-Tcl_DStringValue(&tmp));
  2107. Tcl_DStringFree(&tmp);
  2108.     }
  2109. }
  2110.     } else if (strcmp(argv[1], "serial") == 0) {
  2111. char buf[TCL_INTEGER_SPACE];
  2112. sprintf(buf, "%d", tkSendSerial+1);
  2113. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2114.     } else {
  2115. Tcl_AppendResult(interp, "bad option "", argv[1],
  2116. "": must be bogus, prop, or serial", (char *) NULL);
  2117. return TCL_ERROR;
  2118.     }
  2119.     return TCL_OK;
  2120. }
  2121. #endif
  2122. /*
  2123.  *----------------------------------------------------------------------
  2124.  *
  2125.  * TesttextCmd --
  2126.  *
  2127.  * This procedure implements the "testtext" command.  It provides
  2128.  * a set of functions for testing text widgets and the associated
  2129.  * functions in tkText*.c.
  2130.  *
  2131.  * Results:
  2132.  * A standard Tcl result.
  2133.  *
  2134.  * Side effects:
  2135.  * Depends on option;  see below.
  2136.  *
  2137.  *----------------------------------------------------------------------
  2138.  */
  2139. static int
  2140. TesttextCmd(clientData, interp, argc, argv)
  2141.     ClientData clientData; /* Main window for application. */
  2142.     Tcl_Interp *interp; /* Current interpreter. */
  2143.     int argc; /* Number of arguments. */
  2144.     CONST char **argv; /* Argument strings. */
  2145. {
  2146.     TkText *textPtr;
  2147.     size_t len;
  2148.     int lineIndex, byteIndex, byteOffset;
  2149.     TkTextIndex index;
  2150.     char buf[64];
  2151.     Tcl_CmdInfo info;
  2152.     if (argc < 3) {
  2153. return TCL_ERROR;
  2154.     }
  2155.     if (Tcl_GetCommandInfo(interp, argv[1], &info) == 0) {
  2156. return TCL_ERROR;
  2157.     }
  2158.     textPtr = (TkText *) info.clientData;
  2159.     len = strlen(argv[2]);
  2160.     if (strncmp(argv[2], "byteindex", len) == 0) {
  2161. if (argc != 5) {
  2162.     return TCL_ERROR;
  2163. }
  2164. lineIndex = atoi(argv[3]) - 1;
  2165. byteIndex = atoi(argv[4]);
  2166. TkTextMakeByteIndex(textPtr->tree, lineIndex, byteIndex, &index);
  2167.     } else if (strncmp(argv[2], "forwbytes", len) == 0) {
  2168. if (argc != 5) {
  2169.     return TCL_ERROR;
  2170. }
  2171. if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
  2172.     return TCL_ERROR;
  2173. }
  2174. byteOffset = atoi(argv[4]);
  2175. TkTextIndexForwBytes(&index, byteOffset, &index);
  2176.     } else if (strncmp(argv[2], "backbytes", len) == 0) {
  2177. if (argc != 5) {
  2178.     return TCL_ERROR;
  2179. }
  2180. if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
  2181.     return TCL_ERROR;
  2182. }
  2183. byteOffset = atoi(argv[4]);
  2184. TkTextIndexBackBytes(&index, byteOffset, &index);
  2185.     } else {
  2186. return TCL_ERROR;
  2187.     }
  2188.     TkTextSetMark(textPtr, "insert", &index);
  2189.     TkTextPrintIndex(&index, buf);
  2190.     sprintf(buf + strlen(buf), " %d", index.byteIndex);
  2191.     Tcl_AppendResult(interp, buf, NULL);
  2192.     return TCL_OK;
  2193. }
  2194. #if !(defined(__WIN32__) || defined(MAC_TCL) || defined(MAC_OSX_TK))
  2195. /*
  2196.  *----------------------------------------------------------------------
  2197.  *
  2198.  * TestwrapperCmd --
  2199.  *
  2200.  * This procedure implements the "testwrapper" command.  It 
  2201.  * provides a way from Tcl to determine the extra window Tk adds
  2202.  * in between the toplevel window and the window decorations.
  2203.  *
  2204.  * Results:
  2205.  * A standard Tcl result.
  2206.  *
  2207.  * Side effects:
  2208.  * None.
  2209.  *
  2210.  *----------------------------------------------------------------------
  2211.  */
  2212. /* ARGSUSED */
  2213. static int
  2214. TestwrapperCmd(clientData, interp, argc, argv)
  2215.     ClientData clientData; /* Main window for application. */
  2216.     Tcl_Interp *interp; /* Current interpreter. */
  2217.     int argc; /* Number of arguments. */
  2218.     CONST char **argv; /* Argument strings. */
  2219. {
  2220.     TkWindow *winPtr, *wrapperPtr;
  2221.     Tk_Window tkwin;
  2222.     if (argc != 2) {
  2223. Tcl_AppendResult(interp, "wrong # args;  must be "", argv[0],
  2224. " window"", (char *) NULL);
  2225. return TCL_ERROR;
  2226.     }
  2227.     
  2228.     tkwin = (Tk_Window) clientData;
  2229.     winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
  2230.     if (winPtr == NULL) {
  2231. return TCL_ERROR;
  2232.     }
  2233.     wrapperPtr = TkpGetWrapperWindow(winPtr);
  2234.     if (wrapperPtr != NULL) {
  2235. char buf[TCL_INTEGER_SPACE];
  2236. TkpPrintWindowId(buf, Tk_WindowId(wrapperPtr));
  2237. Tcl_SetResult(interp, buf, TCL_VOLATILE);
  2238.     }
  2239.     return TCL_OK;
  2240. }
  2241. #endif
  2242. /*
  2243.  *----------------------------------------------------------------------
  2244.  *
  2245.  * CustomOptionSet, CustomOptionGet, CustomOptionRestore, CustomOptionFree --
  2246.  *
  2247.  * Handlers for object-based custom configuration options.  See
  2248.  * Testobjconfigcommand.
  2249.  *
  2250.  * Results:
  2251.  * See user documentation for expected results from these functions.
  2252.  * CustomOptionSet Standard Tcl Result.
  2253.  * CustomOptionGet Tcl_Obj * containing value.
  2254.  * CustomOptionRestore None.
  2255.  * CustomOptionFree None.
  2256.  *
  2257.  * Side effects:
  2258.  * Depends on the function.
  2259.  * CustomOptionSet Sets option value to new setting.
  2260.  * CustomOptionGet Creates a new Tcl_Obj.
  2261.  * CustomOptionRestore Resets option value to original value.
  2262.  * CustomOptionFree Free storage for internal rep of
  2263.  * option.
  2264.  *
  2265.  *----------------------------------------------------------------------
  2266.  */
  2267. static int
  2268. CustomOptionSet(clientData,interp, tkwin, value, recordPtr, internalOffset,
  2269. saveInternalPtr, flags)
  2270.     ClientData clientData;
  2271.     Tcl_Interp *interp;
  2272.     Tk_Window tkwin;
  2273.     Tcl_Obj **value;
  2274.     char *recordPtr;
  2275.     int internalOffset;
  2276.     char *saveInternalPtr;
  2277.     int flags;
  2278. {
  2279.     int objEmpty, length;
  2280.     char *new, *string, *internalPtr;
  2281.     
  2282.     objEmpty = 0;
  2283.     if (internalOffset >= 0) {
  2284. internalPtr = recordPtr + internalOffset;
  2285.     } else {
  2286. internalPtr = NULL;
  2287.     }
  2288.     
  2289.     /*
  2290.      * See if the object is empty.
  2291.      */
  2292.     if (value == NULL) {
  2293. objEmpty = 1;
  2294.     } else {
  2295. if ((*value)->bytes != NULL) {
  2296.     objEmpty = ((*value)->length == 0);
  2297. } else {
  2298.     Tcl_GetStringFromObj((*value), &length);
  2299.     objEmpty = (length == 0);
  2300. }
  2301.     }
  2302.     
  2303.     if ((flags & TK_OPTION_NULL_OK) && objEmpty) {
  2304. *value = NULL;
  2305.     } else {
  2306. string = Tcl_GetStringFromObj((*value), &length);
  2307. Tcl_UtfToUpper(string);
  2308. if (strcmp(string, "BAD") == 0) {
  2309.     Tcl_SetResult(interp, "expected good value, got "BAD"",
  2310.     TCL_STATIC);
  2311.     return TCL_ERROR;
  2312. }
  2313.     }
  2314.     if (internalPtr != NULL) {
  2315. if ((*value) != NULL) {
  2316.     string = Tcl_GetStringFromObj((*value), &length);
  2317.     new = ckalloc((size_t) (length + 1));
  2318.     strcpy(new, string);
  2319. } else {
  2320.     new = NULL;
  2321. }
  2322. *((char **) saveInternalPtr) = *((char **) internalPtr);
  2323. *((char **) internalPtr) = new;
  2324.     }
  2325.     return TCL_OK;
  2326. }
  2327. static Tcl_Obj *
  2328. CustomOptionGet(clientData, tkwin, recordPtr, internalOffset)
  2329.     ClientData clientData;
  2330.     Tk_Window tkwin;
  2331.     char *recordPtr;
  2332.     int internalOffset;
  2333. {
  2334.     return (Tcl_NewStringObj(*(char **)(recordPtr + internalOffset), -1));
  2335. }
  2336. static void
  2337. CustomOptionRestore(clientData, tkwin, internalPtr, saveInternalPtr)
  2338.     ClientData clientData;
  2339.     Tk_Window tkwin;
  2340.     char *internalPtr;
  2341.     char *saveInternalPtr;
  2342. {
  2343.     *(char **)internalPtr = *(char **)saveInternalPtr;
  2344.     return;
  2345. }
  2346. static void
  2347. CustomOptionFree(clientData, tkwin, internalPtr)
  2348.     ClientData clientData;
  2349.     Tk_Window tkwin;
  2350.     char *internalPtr;
  2351. {
  2352.     if (*(char **)internalPtr != NULL) {
  2353. ckfree(*(char **)internalPtr);
  2354.     }
  2355. }