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

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkObj.c --
  3.  *
  4.  * This file contains procedures that implement the common Tk object
  5.  * types
  6.  *
  7.  * Copyright (c) 1997 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkObj.c,v 1.8.2.2 2005/01/11 16:05:16 dkf Exp $
  13.  */
  14. #include "tkInt.h"
  15. /*
  16.  * The following structure is the internal representation for pixel objects.
  17.  */
  18.  
  19. typedef struct PixelRep {
  20.     double value;
  21.     int units;
  22.     Tk_Window tkwin;
  23.     int returnValue;
  24. } PixelRep;
  25. #define SIMPLE_PIXELREP(objPtr)
  26.     ((objPtr)->internalRep.twoPtrValue.ptr2 == 0)
  27. #define SET_SIMPLEPIXEL(objPtr, intval)
  28.     (objPtr)->internalRep.twoPtrValue.ptr1 = (VOID *) (intval);
  29.     (objPtr)->internalRep.twoPtrValue.ptr2 = 0
  30. #define GET_SIMPLEPIXEL(objPtr)
  31.     ((int) (objPtr)->internalRep.twoPtrValue.ptr1)
  32. #define SET_COMPLEXPIXEL(objPtr, repPtr)
  33.     (objPtr)->internalRep.twoPtrValue.ptr1 = 0;
  34.     (objPtr)->internalRep.twoPtrValue.ptr2 = (VOID *) repPtr
  35. #define GET_COMPLEXPIXEL(objPtr)
  36.     ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2)
  37. /*
  38.  * The following structure is the internal representation for mm objects.
  39.  */
  40.  
  41. typedef struct MMRep {
  42.     double value;
  43.     int units;
  44.     Tk_Window tkwin;
  45.     double returnValue;
  46. } MMRep;
  47. /*
  48.  * The following structure is the internal representation for window objects.
  49.  * A WindowRep caches name-to-window lookups.  The cache is invalid
  50.  * if tkwin is NULL or if mainPtr->deletionEpoch does not match epoch.
  51.  */
  52. typedef struct WindowRep {
  53.     Tk_Window tkwin; /* Cached window; NULL if not found */
  54.     TkMainInfo *mainPtr; /* MainWindow associated with tkwin */
  55.     long epoch; /* Value of mainPtr->deletionEpoch at last
  56.  * successful lookup.  */
  57. } WindowRep;
  58. /*
  59.  * Prototypes for procedures defined later in this file:
  60.  */
  61. static void DupMMInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
  62.     Tcl_Obj *copyPtr));
  63. static void DupPixelInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
  64.     Tcl_Obj *copyPtr));
  65. static void DupWindowInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
  66.     Tcl_Obj *copyPtr));
  67. static void FreeMMInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
  68. static void FreePixelInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
  69. static void FreeWindowInternalRep _ANSI_ARGS_((Tcl_Obj *objPtr));
  70. static void UpdateStringOfMM _ANSI_ARGS_((Tcl_Obj *objPtr));
  71. static int SetMMFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  72.     Tcl_Obj *objPtr));
  73. static int SetPixelFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  74.     Tcl_Obj *objPtr));
  75. static int SetWindowFromAny _ANSI_ARGS_((Tcl_Interp *interp,
  76.     Tcl_Obj *objPtr));
  77. /*
  78.  * The following structure defines the implementation of the "pixel"
  79.  * Tcl object, used for measuring distances.  The pixel object remembers
  80.  * its initial display-independant settings.
  81.  */
  82. static Tcl_ObjType pixelObjType = {
  83.     "pixel", /* name */
  84.     FreePixelInternalRep, /* freeIntRepProc */
  85.     DupPixelInternalRep, /* dupIntRepProc */
  86.     NULL, /* updateStringProc */
  87.     SetPixelFromAny /* setFromAnyProc */
  88. };
  89. /*
  90.  * The following structure defines the implementation of the "pixel"
  91.  * Tcl object, used for measuring distances.  The pixel object remembers
  92.  * its initial display-independant settings.
  93.  */
  94. static Tcl_ObjType mmObjType = {
  95.     "mm", /* name */
  96.     FreeMMInternalRep, /* freeIntRepProc */
  97.     DupMMInternalRep, /* dupIntRepProc */
  98.     UpdateStringOfMM, /* updateStringProc */
  99.     SetMMFromAny /* setFromAnyProc */
  100. };
  101. /*
  102.  * The following structure defines the implementation of the "window"
  103.  * Tcl object.
  104.  */
  105. static Tcl_ObjType windowObjType = {
  106.     "window", /* name */
  107.     FreeWindowInternalRep, /* freeIntRepProc */
  108.     DupWindowInternalRep, /* dupIntRepProc */
  109.     NULL, /* updateStringProc */
  110.     SetWindowFromAny /* setFromAnyProc */
  111. };
  112. /*
  113.  *----------------------------------------------------------------------
  114.  *
  115.  * Tk_GetPixelsFromObj --
  116.  *
  117.  * Attempt to return a pixel value from the Tcl object "objPtr". If the
  118.  * object is not already a pixel value, an attempt will be made to convert
  119.  * it to one.
  120.  *
  121.  * Results:
  122.  * The return value is a standard Tcl object result. If an error occurs
  123.  * during conversion, an error message is left in the interpreter's
  124.  * result unless "interp" is NULL.
  125.  *
  126.  * Side effects:
  127.  * If the object is not already a pixel, the conversion will free
  128.  * any old internal representation. 
  129.  *
  130.  *----------------------------------------------------------------------
  131.  */
  132. int
  133. Tk_GetPixelsFromObj(interp, tkwin, objPtr, intPtr)
  134.     Tcl_Interp *interp;  /* Used for error reporting if not NULL. */
  135.     Tk_Window tkwin;
  136.     Tcl_Obj *objPtr; /* The object from which to get pixels. */
  137.     int *intPtr; /* Place to store resulting pixels. */
  138. {
  139.     int result;
  140.     double d;
  141.     PixelRep *pixelPtr;
  142.     static double bias[] = {
  143. 1.0, 10.0, 25.4, 25.4 / 72.0
  144.     };
  145.     if (objPtr->typePtr != &pixelObjType) {
  146. result = SetPixelFromAny(interp, objPtr);
  147. if (result != TCL_OK) {
  148.     return result;
  149. }
  150.     }
  151.     if (SIMPLE_PIXELREP(objPtr)) {
  152. *intPtr = GET_SIMPLEPIXEL(objPtr);
  153.     } else {
  154. pixelPtr = GET_COMPLEXPIXEL(objPtr);
  155. if (pixelPtr->tkwin != tkwin) {
  156.     d = pixelPtr->value;
  157.     if (pixelPtr->units >= 0) {
  158. d *= bias[pixelPtr->units] * WidthOfScreen(Tk_Screen(tkwin));
  159. d /= WidthMMOfScreen(Tk_Screen(tkwin));
  160.     }
  161.     if (d < 0) {
  162. pixelPtr->returnValue = (int) (d - 0.5);
  163.     } else {
  164. pixelPtr->returnValue = (int) (d + 0.5);
  165.     }
  166.     pixelPtr->tkwin = tkwin;
  167. }
  168.         *intPtr = pixelPtr->returnValue;
  169.     }
  170.     return TCL_OK;
  171. }
  172. /*
  173.  *----------------------------------------------------------------------
  174.  *
  175.  * FreePixelInternalRep --
  176.  *
  177.  * Deallocate the storage associated with a pixel object's internal
  178.  * representation.
  179.  *
  180.  * Results:
  181.  * None.
  182.  *
  183.  * Side effects:
  184.  * Frees objPtr's internal representation and sets objPtr's
  185.  * internalRep to NULL.
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189. static void
  190. FreePixelInternalRep(objPtr)
  191.     Tcl_Obj *objPtr; /* Pixel object with internal rep to free. */
  192. {
  193.     PixelRep *pixelPtr;
  194.     
  195.     if (!SIMPLE_PIXELREP(objPtr)) {
  196. pixelPtr = GET_COMPLEXPIXEL(objPtr);
  197. ckfree((char *) pixelPtr);
  198.     }
  199.     SET_SIMPLEPIXEL(objPtr, 0);
  200.     objPtr->typePtr = NULL;
  201. }
  202. /*
  203.  *----------------------------------------------------------------------
  204.  *
  205.  * DupPixelInternalRep --
  206.  *
  207.  * Initialize the internal representation of a pixel Tcl_Obj to a
  208.  * copy of the internal representation of an existing pixel object. 
  209.  *
  210.  * Results:
  211.  * None.
  212.  *
  213.  * Side effects:
  214.  * copyPtr's internal rep is set to the pixel corresponding to
  215.  * srcPtr's internal rep.
  216.  *
  217.  *----------------------------------------------------------------------
  218.  */
  219. static void
  220. DupPixelInternalRep(srcPtr, copyPtr)
  221.     register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
  222.     register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
  223. {
  224.     PixelRep *oldPtr, *newPtr;
  225.     
  226.     copyPtr->typePtr = srcPtr->typePtr;
  227.     if (SIMPLE_PIXELREP(srcPtr)) {
  228. SET_SIMPLEPIXEL(copyPtr, GET_SIMPLEPIXEL(srcPtr));
  229.     } else {
  230. oldPtr = GET_COMPLEXPIXEL(srcPtr);
  231. newPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
  232. newPtr->value = oldPtr->value;
  233. newPtr->units = oldPtr->units;
  234. newPtr->tkwin = oldPtr->tkwin;
  235. newPtr->returnValue = oldPtr->returnValue;
  236. SET_COMPLEXPIXEL(copyPtr, newPtr);
  237.     }
  238. }
  239. /*
  240.  *----------------------------------------------------------------------
  241.  *
  242.  * SetPixelFromAny --
  243.  *
  244.  * Attempt to generate a pixel internal form for the Tcl object
  245.  * "objPtr".
  246.  *
  247.  * Results:
  248.  * The return value is a standard Tcl result. If an error occurs during
  249.  * conversion, an error message is left in the interpreter's result
  250.  * unless "interp" is NULL.
  251.  *
  252.  * Side effects:
  253.  * If no error occurs, a pixel representation of the object is
  254.  * stored internally and the type of "objPtr" is set to pixel.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. static int
  259. SetPixelFromAny(interp, objPtr)
  260.     Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  261.     Tcl_Obj *objPtr; /* The object to convert. */
  262. {
  263.     Tcl_ObjType *typePtr;
  264.     char *string, *rest;
  265.     double d;
  266.     int i, units;
  267.     PixelRep *pixelPtr;
  268.     string = Tcl_GetStringFromObj(objPtr, NULL);
  269.     d = strtod(string, &rest);
  270.     if (rest == string) {
  271. /*
  272.  * Must copy string before resetting the result in case a caller
  273.  * is trying to convert the interpreter's result to pixels.
  274.  */
  275. char buf[100];
  276. error:
  277. sprintf(buf, "bad screen distance "%.50s"", string);
  278. Tcl_ResetResult(interp);
  279. Tcl_AppendResult(interp, buf, NULL);
  280. return TCL_ERROR;
  281.     }
  282.     while ((*rest != '') && isspace(UCHAR(*rest))) {
  283. rest++;
  284.     }
  285.     switch (*rest) {
  286. case '':
  287.     units = -1;
  288.     break;
  289. case 'm':
  290.     units = 0;
  291.     break;
  292. case 'c':
  293.     units = 1;
  294.     break;
  295. case 'i':
  296.     units = 2;
  297.     break;
  298. case 'p':
  299.     units = 3;
  300.     break;
  301. default:
  302.     goto error;
  303.     }
  304.     /*
  305.      * Free the old internalRep before setting the new one. 
  306.      */
  307.     typePtr = objPtr->typePtr;
  308.     if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  309. (*typePtr->freeIntRepProc)(objPtr);
  310.     }
  311.     objPtr->typePtr = &pixelObjType;
  312.     i = (int) d;
  313.     if ((units < 0) && (i == d)) {
  314. SET_SIMPLEPIXEL(objPtr, i);
  315.     } else {
  316. pixelPtr = (PixelRep *) ckalloc(sizeof(PixelRep));
  317. pixelPtr->value = d;
  318. pixelPtr->units = units;
  319. pixelPtr->tkwin = NULL;
  320. pixelPtr->returnValue = i;
  321. SET_COMPLEXPIXEL(objPtr, pixelPtr);
  322.     }
  323.     return TCL_OK;
  324. }
  325. /*
  326.  *----------------------------------------------------------------------
  327.  *
  328.  * Tk_GetMMFromObj --
  329.  *
  330.  * Attempt to return an mm value from the Tcl object "objPtr". If the
  331.  * object is not already an mm value, an attempt will be made to convert
  332.  * it to one.
  333.  *
  334.  * Results:
  335.  * The return value is a standard Tcl object result. If an error occurs
  336.  * during conversion, an error message is left in the interpreter's
  337.  * result unless "interp" is NULL.
  338.  *
  339.  * Side effects:
  340.  * If the object is not already a pixel, the conversion will free
  341.  * any old internal representation. 
  342.  *
  343.  *----------------------------------------------------------------------
  344.  */
  345. int
  346. Tk_GetMMFromObj(interp, tkwin, objPtr, doublePtr)
  347.     Tcl_Interp *interp;  /* Used for error reporting if not NULL. */
  348.     Tk_Window tkwin;
  349.     Tcl_Obj *objPtr; /* The object from which to get mms. */
  350.     double *doublePtr; /* Place to store resulting millimeters. */
  351. {
  352.     int result;
  353.     double d;
  354.     MMRep *mmPtr;
  355.     static double bias[] = {
  356. 10.0, 25.4, 1.0, 25.4 / 72.0
  357.     };
  358.     if (objPtr->typePtr != &mmObjType) {
  359. result = SetMMFromAny(interp, objPtr);
  360. if (result != TCL_OK) {
  361.     return result;
  362. }
  363.     }
  364.     mmPtr = (MMRep *) objPtr->internalRep.otherValuePtr;
  365.     if (mmPtr->tkwin != tkwin) {
  366. d = mmPtr->value;
  367. if (mmPtr->units == -1) {
  368.     d /= WidthOfScreen(Tk_Screen(tkwin));
  369.     d *= WidthMMOfScreen(Tk_Screen(tkwin));
  370. } else {
  371.     d *= bias[mmPtr->units];
  372. }
  373. mmPtr->tkwin = tkwin;
  374. mmPtr->returnValue = d;
  375.     }
  376.     *doublePtr = mmPtr->returnValue;
  377.     return TCL_OK;
  378. }
  379. /*
  380.  *----------------------------------------------------------------------
  381.  *
  382.  * FreeMMInternalRep --
  383.  *
  384.  * Deallocate the storage associated with a mm object's internal
  385.  * representation.
  386.  *
  387.  * Results:
  388.  * None.
  389.  *
  390.  * Side effects:
  391.  * Frees objPtr's internal representation and sets objPtr's
  392.  * internalRep to NULL.
  393.  *
  394.  *----------------------------------------------------------------------
  395.  */
  396. static void
  397. FreeMMInternalRep(objPtr)
  398.     Tcl_Obj *objPtr; /* MM object with internal rep to free. */
  399. {
  400.     ckfree((char *) objPtr->internalRep.otherValuePtr);
  401.     objPtr->internalRep.otherValuePtr = NULL;
  402.     objPtr->typePtr = NULL;
  403. }
  404. /*
  405.  *----------------------------------------------------------------------
  406.  *
  407.  * DupMMInternalRep --
  408.  *
  409.  * Initialize the internal representation of a pixel Tcl_Obj to a
  410.  * copy of the internal representation of an existing pixel object. 
  411.  *
  412.  * Results:
  413.  * None.
  414.  *
  415.  * Side effects:
  416.  * copyPtr's internal rep is set to the pixel corresponding to
  417.  * srcPtr's internal rep.
  418.  *
  419.  *----------------------------------------------------------------------
  420.  */
  421. static void
  422. DupMMInternalRep(srcPtr, copyPtr)
  423.     register Tcl_Obj *srcPtr; /* Object with internal rep to copy. */
  424.     register Tcl_Obj *copyPtr; /* Object with internal rep to set. */
  425. {
  426.     MMRep *oldPtr, *newPtr;
  427.     
  428.     copyPtr->typePtr = srcPtr->typePtr;
  429.     oldPtr = (MMRep *) srcPtr->internalRep.otherValuePtr;
  430.     newPtr = (MMRep *) ckalloc(sizeof(MMRep));
  431.     newPtr->value = oldPtr->value;
  432.     newPtr->units = oldPtr->units;
  433.     newPtr->tkwin = oldPtr->tkwin;
  434.     newPtr->returnValue = oldPtr->returnValue;
  435.     copyPtr->internalRep.otherValuePtr = (VOID *) newPtr;
  436. }
  437. /*
  438.  *----------------------------------------------------------------------
  439.  *
  440.  * UpdateStringOfMM --
  441.  *
  442.  *      Update the string representation for a pixel Tcl_Obj
  443.  *      this function is only called, if the pixel Tcl_Obj has no unit,
  444.  *      because with units the string representation is created by
  445.  *      SetMMFromAny
  446.  *
  447.  * Results:
  448.  *      None.
  449.  *
  450.  * Side effects:
  451.  *      The object's string is set to a valid string that results from
  452.  *      the double-to-string conversion.
  453.  *
  454.  *----------------------------------------------------------------------
  455.  */
  456. static void
  457. UpdateStringOfMM(objPtr)
  458.     register Tcl_Obj *objPtr;   /* pixel obj with string rep to update. */
  459. {
  460.     MMRep *mmPtr;
  461.     char buffer[TCL_DOUBLE_SPACE];
  462.     register int len;
  463.     mmPtr = (MMRep *) objPtr->internalRep.otherValuePtr;
  464.     /* assert( mmPtr->units == -1 && objPtr->bytes == NULL ); */
  465.     if ((mmPtr->units != -1) || (objPtr->bytes != NULL)) {
  466.         panic("UpdateStringOfMM: false precondition");
  467.     }
  468.     Tcl_PrintDouble((Tcl_Interp *) NULL, mmPtr->value, buffer);
  469.     len = strlen(buffer);
  470.     objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
  471.     strcpy(objPtr->bytes, buffer);
  472.     objPtr->length = len;
  473. }
  474. /*
  475.  *----------------------------------------------------------------------
  476.  *
  477.  * SetMMFromAny --
  478.  *
  479.  * Attempt to generate a mm internal form for the Tcl object
  480.  * "objPtr".
  481.  *
  482.  * Results:
  483.  * The return value is a standard Tcl result. If an error occurs during
  484.  * conversion, an error message is left in the interpreter's result
  485.  * unless "interp" is NULL.
  486.  *
  487.  * Side effects:
  488.  * If no error occurs, a mm representation of the object is
  489.  * stored internally and the type of "objPtr" is set to mm.
  490.  *
  491.  *----------------------------------------------------------------------
  492.  */
  493. static int
  494. SetMMFromAny(interp, objPtr)
  495.     Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  496.     Tcl_Obj *objPtr; /* The object to convert. */
  497. {
  498.     Tcl_ObjType *typePtr;
  499.     char *string, *rest;
  500.     double d;
  501.     int units;
  502.     MMRep *mmPtr;
  503.     static Tcl_ObjType *tclDoubleObjType = NULL;
  504.     static Tcl_ObjType *tclIntObjType = NULL;
  505.     if (tclDoubleObjType == NULL) {
  506. /*
  507.  * Cache the object types for comaprison below.
  508.  * This allows optimized checks for standard cases.
  509.  */
  510. tclDoubleObjType = Tcl_GetObjType("double");
  511. tclIntObjType    = Tcl_GetObjType("int");
  512.     }
  513.     if (objPtr->typePtr == tclDoubleObjType) {
  514. Tcl_GetDoubleFromObj(interp, objPtr, &d);
  515. units = -1;
  516.     } else if (objPtr->typePtr == tclIntObjType) {
  517. Tcl_GetIntFromObj(interp, objPtr, &units);
  518. d = (double) units;
  519. units = -1;
  520. /*
  521.  * In the case of ints, we need to ensure that a valid
  522.  * string exists in order for int-but-not-string objects
  523.  * to be converted back to ints again from mm obj types.
  524.  */
  525. (void) Tcl_GetStringFromObj(objPtr, NULL);
  526.     } else {
  527. /*
  528.  * It wasn't a known int or double, so parse it.
  529.  */
  530. string = Tcl_GetStringFromObj(objPtr, NULL);
  531. d = strtod(string, &rest);
  532. if (rest == string) {
  533.     /*
  534.      * Must copy string before resetting the result in case a caller
  535.      * is trying to convert the interpreter's result to mms.
  536.      */
  537.     error:
  538.             Tcl_AppendResult(interp, "bad screen distance "", string,
  539.                     """, (char *) NULL);
  540.             return TCL_ERROR;
  541.         }
  542.         while ((*rest != '') && isspace(UCHAR(*rest))) {
  543.             rest++;
  544.         }
  545.         switch (*rest) {
  546.     case '':
  547. units = -1;
  548. break;
  549.     case 'c':
  550. units = 0;
  551. break;
  552.     case 'i':
  553. units = 1;
  554. break;
  555.     case 'm':
  556. units = 2;
  557. break;
  558.     case 'p':
  559. units = 3;
  560. break;
  561.     default:
  562. goto error;
  563. }
  564.     }
  565.     /*
  566.      * Free the old internalRep before setting the new one. 
  567.      */
  568.     typePtr = objPtr->typePtr;
  569.     if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  570. (*typePtr->freeIntRepProc)(objPtr);
  571.     }
  572.     objPtr->typePtr = &mmObjType;
  573.     mmPtr = (MMRep *) ckalloc(sizeof(MMRep));
  574.     mmPtr->value = d;
  575.     mmPtr->units = units;
  576.     mmPtr->tkwin = NULL;
  577.     mmPtr->returnValue = d;
  578.     objPtr->internalRep.otherValuePtr = (VOID *) mmPtr;
  579.     return TCL_OK;
  580. }
  581. /*
  582.  *----------------------------------------------------------------------
  583.  *
  584.  * TkGetWindowFromObj --
  585.  *
  586.  * Attempt to return a Tk_Window from the Tcl object "objPtr". If the
  587.  * object is not already a Tk_Window, an attempt will be made to convert
  588.  * it to one.
  589.  *
  590.  * Results:
  591.  * The return value is a standard Tcl object result. If an error occurs
  592.  * during conversion, an error message is left in the interpreter's
  593.  * result unless "interp" is NULL.
  594.  *
  595.  * Side effects:
  596.  * If the object is not already a Tk_Window, the conversion will free
  597.  * any old internal representation. 
  598.  *
  599.  *----------------------------------------------------------------------
  600.  */
  601. int
  602. TkGetWindowFromObj(interp, tkwin, objPtr, windowPtr)
  603.     Tcl_Interp *interp;  /* Used for error reporting if not NULL. */
  604.     Tk_Window tkwin; /* A token to get the main window from. */
  605.     Tcl_Obj *objPtr; /* The object from which to get window. */
  606.     Tk_Window *windowPtr; /* Place to store resulting window. */
  607. {
  608.     TkMainInfo *mainPtr = ((TkWindow *)tkwin)->mainPtr;
  609.     register WindowRep *winPtr;
  610.     int result;
  611.     result = Tcl_ConvertToType(interp, objPtr, &windowObjType);
  612.     if (result != TCL_OK) {
  613. return result;
  614.     }
  615.     winPtr = (WindowRep *) objPtr->internalRep.otherValuePtr;
  616.     if (    winPtr->tkwin == NULL
  617.  || winPtr->mainPtr == NULL
  618.  || winPtr->mainPtr != mainPtr 
  619.  || winPtr->epoch != mainPtr->deletionEpoch) 
  620.     {
  621. /* Cache is invalid.
  622.  */
  623. winPtr->tkwin = Tk_NameToWindow(interp,
  624. Tcl_GetStringFromObj(objPtr, NULL), tkwin);
  625. winPtr->mainPtr = mainPtr;
  626. winPtr->epoch = mainPtr ? mainPtr->deletionEpoch : 0;
  627.     }
  628.     *windowPtr = winPtr->tkwin;
  629.     if (winPtr->tkwin == NULL) {
  630. /* ASSERT: Tk_NameToWindow has left error message in interp */
  631. return TCL_ERROR;
  632.     }
  633.     return TCL_OK;
  634. }
  635. /*
  636.  *----------------------------------------------------------------------
  637.  *
  638.  * SetWindowFromAny --
  639.  * Generate a windowObj internal form for the Tcl object "objPtr".
  640.  *
  641.  * Results:
  642.  * Always returns TCL_OK. 
  643.  *
  644.  * Side effects:
  645.  * Sets objPtr's internal representation to an uninitialized
  646.  * windowObj. Frees the old internal representation, if any.
  647.  *
  648.  * See also:
  649.  *  TkGetWindowFromObj, which initializes the WindowRep cache.
  650.  *
  651.  *----------------------------------------------------------------------
  652.  */
  653. static int
  654. SetWindowFromAny(interp, objPtr)
  655.     Tcl_Interp *interp; /* Used for error reporting if not NULL. */
  656.     register Tcl_Obj *objPtr; /* The object to convert. */
  657. {
  658.     Tcl_ObjType *typePtr;
  659.     WindowRep *winPtr;
  660.     /*
  661.      * Free the old internalRep before setting the new one. 
  662.      */
  663.     Tcl_GetStringFromObj(objPtr, NULL);
  664.     typePtr = objPtr->typePtr;
  665.     if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
  666. (*typePtr->freeIntRepProc)(objPtr);
  667.     }
  668.     winPtr = (WindowRep *) ckalloc(sizeof(WindowRep));
  669.     winPtr->tkwin = NULL;
  670.     winPtr->mainPtr = NULL;
  671.     winPtr->epoch = 0;
  672.     objPtr->internalRep.otherValuePtr = (VOID*)winPtr;
  673.     objPtr->typePtr = &windowObjType;
  674.     return TCL_OK;
  675. }
  676. /*
  677.  *----------------------------------------------------------------------
  678.  *
  679.  * DupWindowInternalRep --
  680.  *
  681.  * Initialize the internal representation of a window Tcl_Obj to a
  682.  * copy of the internal representation of an existing window object. 
  683.  *
  684.  * Results:
  685.  * None.
  686.  *
  687.  * Side effects:
  688.  * copyPtr's internal rep is set to refer to the same window as
  689.  * srcPtr's internal rep.
  690.  *
  691.  *----------------------------------------------------------------------
  692.  */
  693. static void
  694. DupWindowInternalRep(srcPtr, copyPtr)
  695.     register Tcl_Obj *srcPtr;
  696.     register Tcl_Obj *copyPtr;
  697. {
  698.     register WindowRep *oldPtr, *newPtr;
  699.     oldPtr = srcPtr->internalRep.otherValuePtr;
  700.     newPtr = (WindowRep *) ckalloc(sizeof(WindowRep));
  701.     newPtr->tkwin = oldPtr->tkwin;
  702.     newPtr->mainPtr = oldPtr->mainPtr;
  703.     newPtr->epoch = oldPtr->epoch;
  704.     copyPtr->internalRep.otherValuePtr = (VOID *)newPtr;
  705.     copyPtr->typePtr = srcPtr->typePtr;
  706. }
  707. /*
  708.  *----------------------------------------------------------------------
  709.  *
  710.  * FreeWindowInternalRep --
  711.  *
  712.  * Deallocate the storage associated with a window object's internal
  713.  * representation.
  714.  *
  715.  * Results:
  716.  * None.
  717.  *
  718.  * Side effects:
  719.  * Frees objPtr's internal representation and sets objPtr's
  720.  * internalRep to NULL.
  721.  *
  722.  *----------------------------------------------------------------------
  723.  */
  724. static void
  725. FreeWindowInternalRep(objPtr)
  726.     Tcl_Obj *objPtr; /* Window object with internal rep to free. */
  727. {
  728.     ckfree((char *) objPtr->internalRep.otherValuePtr);
  729.     objPtr->internalRep.otherValuePtr = NULL;
  730.     objPtr->typePtr = NULL;
  731. }
  732. /*
  733.  *--------------------------------------------------------------
  734.  *
  735.  * TkParsePadAmount --
  736.  *
  737.  * This procedure parses a padding specification and returns
  738.  * the appropriate padding values.  A padding specification can
  739.  * be either a single pixel width, or a list of two pixel widths.
  740.  * If a single pixel width, the amount specified is used for 
  741.  * padding on both sides.  If two amounts are specified, then
  742.  * they specify the left/right or top/bottom padding.
  743.  *
  744.  * Results:
  745.  * A standard Tcl return value.
  746.  *
  747.  * Side effects:
  748.  * An error message is written to the interpreter is something
  749.  * is not right.
  750.  *
  751.  *--------------------------------------------------------------
  752.  */
  753. int
  754. TkParsePadAmount(interp, tkwin, specObj, halfPtr, allPtr)
  755.     Tcl_Interp *interp; /* Interpreter for error reporting. */
  756.     Tk_Window tkwin; /* A window.  Needed by Tk_GetPixels() */
  757.     Tcl_Obj *specObj; /* The argument to "-padx", "-pady", "-ipadx",
  758.  * or "-ipady".  The thing to be parsed. */
  759.     int *halfPtr; /* Write the left/top part of padding here */
  760.     int *allPtr; /* Write the total padding here */
  761. {
  762.     int firstInt, secondInt;    /* The two components of the padding */
  763.     int objc; /* The length of the list (should be 1 or 2) */
  764.     Tcl_Obj **objv; /* The objects in the list */
  765.     /*
  766.      * Check for a common case where a single object would otherwise
  767.      * be shimmered between a list and a pixel spec.
  768.      */
  769.     if (specObj->typePtr == &pixelObjType) {
  770. if (Tk_GetPixelsFromObj(interp, tkwin, specObj, &firstInt) != TCL_OK) {
  771.     Tcl_ResetResult(interp);
  772.     Tcl_AppendResult(interp, "bad pad value "",
  773.     Tcl_GetString(specObj),
  774.     "": must be positive screen distance", (char *) NULL);
  775.     return TCL_ERROR;
  776. }
  777. secondInt = firstInt;
  778. goto done;
  779.     }
  780.     /*
  781.      * Pad specifications are a list of one or two elements, each of
  782.      * which is a pixel specification.
  783.      */
  784.     if (Tcl_ListObjGetElements(interp, specObj, &objc, &objv) != TCL_OK) {
  785. return TCL_ERROR;
  786.     }
  787.     if (objc != 1 && objc != 2) {
  788. Tcl_AppendResult(interp,
  789. "wrong number of parts to pad specification", NULL);
  790. return TCL_ERROR;
  791.     }
  792.     /*
  793.      * Parse the first part.
  794.      */
  795.     if (Tk_GetPixelsFromObj(interp, tkwin, objv[0], &firstInt) != TCL_OK ||
  796.     (firstInt < 0)) {
  797. Tcl_ResetResult(interp);
  798. Tcl_AppendResult(interp, "bad pad value "", Tcl_GetString(objv[0]),
  799. "": must be positive screen distance", (char *) NULL);
  800. return TCL_ERROR;
  801.     }
  802.     /*
  803.      * Parse the second part if it exists, otherwise it is as if it
  804.      * was the same as the first part.
  805.      */
  806.     if (objc == 1) {
  807. secondInt = firstInt;
  808.     } else if (Tk_GetPixelsFromObj(interp, tkwin, objv[1],
  809.     &secondInt) != TCL_OK || (secondInt < 0)) {
  810. Tcl_ResetResult(interp);
  811. Tcl_AppendResult(interp, "bad 2nd pad value "",
  812. Tcl_GetString(objv[1]),
  813. "": must be positive screen distance", (char *) NULL);
  814. return TCL_ERROR;
  815.     }
  816.     /*
  817.      * Write the parsed bits back into the receiving variables.
  818.      */
  819.   done:
  820.     if (halfPtr != 0) {
  821. *halfPtr = firstInt;
  822.     }
  823.     *allPtr = firstInt + secondInt;
  824.     return TCL_OK;
  825. }
  826. /*
  827.  *----------------------------------------------------------------------
  828.  *
  829.  * TkRegisterObjTypes --
  830.  *
  831.  * Registers Tk's Tcl_ObjType structures with the Tcl run-time.
  832.  *
  833.  * Results:
  834.  * None
  835.  *
  836.  * Side effects:
  837.  * All instances of Tcl_ObjType structues used in Tk are registered
  838.  * with Tcl.
  839.  *
  840.  *----------------------------------------------------------------------
  841.  */
  842. void
  843. TkRegisterObjTypes()
  844. {
  845.     Tcl_RegisterObjType(&tkBorderObjType);
  846.     Tcl_RegisterObjType(&tkBitmapObjType);
  847.     Tcl_RegisterObjType(&tkColorObjType);
  848.     Tcl_RegisterObjType(&tkCursorObjType);
  849.     Tcl_RegisterObjType(&tkFontObjType);
  850.     Tcl_RegisterObjType(&mmObjType);
  851.     Tcl_RegisterObjType(&tkOptionObjType);
  852.     Tcl_RegisterObjType(&pixelObjType);
  853.     Tcl_RegisterObjType(&tkStateKeyObjType);
  854.     Tcl_RegisterObjType(&windowObjType);
  855. }