4 * This file contains miscellaneous utility procedures that
5 * are used by the rest of Tk, such as a procedure for drawing
8 * Copyright (c) 1994 The Regents of the University of California.
9 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
11 * See the file "license.terms" for information on usage and redistribution
12 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
21 * The structure below defines the implementation of the "statekey"
22 * Tcl object, used for quickly finding a mapping in a TkStateMap.
25 Tcl_ObjType tkStateKeyObjType = {
26 "statekey", /* name */
27 (Tcl_FreeInternalRepProc *) NULL, /* freeIntRepProc */
28 (Tcl_DupInternalRepProc *) NULL, /* dupIntRepProc */
29 (Tcl_UpdateStringProc *) NULL, /* updateStringProc */
30 (Tcl_SetFromAnyProc *) NULL /* setFromAnyProc */
35 *--------------------------------------------------------------
39 * This procedure is invoked during option processing to handle
40 * the "-state" and "-default" options.
43 * A standard Tcl return value.
46 * The state for a given item gets replaced by the state
47 * indicated in the value argument.
49 *--------------------------------------------------------------
53 TkStateParseProc(clientData, interp, tkwin, value, widgRec, offset)
54 ClientData clientData; /* some flags.*/
55 Tcl_Interp *interp; /* Used for reporting errors. */
56 Tk_Window tkwin; /* Window containing canvas widget. */
57 CONST char *value; /* Value of option. */
58 char *widgRec; /* Pointer to record for item. */
59 int offset; /* Offset into item. */
62 int flags = (int)clientData;
65 register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
67 if(value == NULL || *value == 0) {
68 *statePtr = TK_STATE_NULL;
73 length = strlen(value);
75 if ((c == 'n') && (strncmp(value, "normal", length) == 0)) {
76 *statePtr = TK_STATE_NORMAL;
79 if ((c == 'd') && (strncmp(value, "disabled", length) == 0)) {
80 *statePtr = TK_STATE_DISABLED;
83 if ((c == 'a') && (flags&1) && (strncmp(value, "active", length) == 0)) {
84 *statePtr = TK_STATE_ACTIVE;
87 if ((c == 'h') && (flags&2) && (strncmp(value, "hidden", length) == 0)) {
88 *statePtr = TK_STATE_HIDDEN;
92 Tcl_AppendResult(interp, "bad ", (flags&4)?"-default" : "state",
93 " value \"", value, "\": must be normal",
96 Tcl_AppendResult(interp, ", active",(char *) NULL);
99 Tcl_AppendResult(interp, ", hidden",(char *) NULL);
102 Tcl_AppendResult(interp, ",",(char *) NULL);
104 Tcl_AppendResult(interp, " or disabled",(char *) NULL);
105 *statePtr = TK_STATE_NORMAL;
110 *--------------------------------------------------------------
112 * TkStatePrintProc --
114 * This procedure is invoked by the Tk configuration code
115 * to produce a printable string for the "-state"
116 * configuration option.
119 * The return value is a string describing the state for
120 * the item referred to by "widgRec". In addition, *freeProcPtr
121 * is filled in with the address of a procedure to call to free
122 * the result string when it's no longer needed (or NULL to
123 * indicate that the string doesn't need to be freed).
128 *--------------------------------------------------------------
132 TkStatePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
133 ClientData clientData; /* Ignored. */
134 Tk_Window tkwin; /* Window containing canvas widget. */
135 char *widgRec; /* Pointer to record for item. */
136 int offset; /* Offset into item. */
137 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
138 * information about how to reclaim
139 * storage for return string. */
141 register Tk_State *statePtr = (Tk_State *) (widgRec + offset);
143 if (*statePtr==TK_STATE_NORMAL) {
145 } else if (*statePtr==TK_STATE_DISABLED) {
147 } else if (*statePtr==TK_STATE_HIDDEN) {
149 } else if (*statePtr==TK_STATE_ACTIVE) {
157 *--------------------------------------------------------------
159 * TkOrientParseProc --
161 * This procedure is invoked during option processing to handle
162 * the "-orient" option.
165 * A standard Tcl return value.
168 * The orientation for a given item gets replaced by the orientation
169 * indicated in the value argument.
171 *--------------------------------------------------------------
175 TkOrientParseProc(clientData, interp, tkwin, value, widgRec, offset)
176 ClientData clientData; /* some flags.*/
177 Tcl_Interp *interp; /* Used for reporting errors. */
178 Tk_Window tkwin; /* Window containing canvas widget. */
179 CONST char *value; /* Value of option. */
180 char *widgRec; /* Pointer to record for item. */
181 int offset; /* Offset into item. */
186 register int *orientPtr = (int *) (widgRec + offset);
188 if(value == NULL || *value == 0) {
194 length = strlen(value);
196 if ((c == 'h') && (strncmp(value, "horizontal", length) == 0)) {
200 if ((c == 'v') && (strncmp(value, "vertical", length) == 0)) {
204 Tcl_AppendResult(interp, "bad orientation \"", value,
205 "\": must be vertical or horizontal",
212 *--------------------------------------------------------------
214 * TkOrientPrintProc --
216 * This procedure is invoked by the Tk configuration code
217 * to produce a printable string for the "-orient"
218 * configuration option.
221 * The return value is a string describing the orientation for
222 * the item referred to by "widgRec". In addition, *freeProcPtr
223 * is filled in with the address of a procedure to call to free
224 * the result string when it's no longer needed (or NULL to
225 * indicate that the string doesn't need to be freed).
230 *--------------------------------------------------------------
234 TkOrientPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
235 ClientData clientData; /* Ignored. */
236 Tk_Window tkwin; /* Window containing canvas widget. */
237 char *widgRec; /* Pointer to record for item. */
238 int offset; /* Offset into item. */
239 Tcl_FreeProc **freeProcPtr; /* Pointer to variable to fill in with
240 * information about how to reclaim
241 * storage for return string. */
243 register int *statePtr = (int *) (widgRec + offset);
253 *----------------------------------------------------------------------
255 * TkOffsetParseProc --
257 * Converts the offset of a stipple or tile into the Tk_TSOffset structure.
259 *----------------------------------------------------------------------
263 TkOffsetParseProc(clientData, interp, tkwin, value, widgRec, offset)
264 ClientData clientData; /* not used */
265 Tcl_Interp *interp; /* Interpreter to send results back to */
266 Tk_Window tkwin; /* Window on same display as tile */
267 CONST char *value; /* Name of image */
268 char *widgRec; /* Widget structure record */
269 int offset; /* Offset of tile in record */
271 Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset);
272 Tk_TSOffset tsoffset;
276 if ((value == NULL) || (*value == 0)) {
277 tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
285 if (((int)clientData) & TK_OFFSET_RELATIVE) {
286 tsoffset.flags = TK_OFFSET_RELATIVE;
293 tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_MIDDLE;
296 if (value[2]!='d' || value[3]!='\0') {goto badTSOffset;}
297 tsoffset.flags = INT_MAX;
301 if (value[1] != '\0') {goto badTSOffset;}
302 tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_MIDDLE;
305 if ((value[1] != '\0') && (value[2] != '\0')) {
309 case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_TOP;
311 case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_TOP;
313 case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_TOP;
318 if ((value[1] != '\0') && (value[2] != '\0')) {
322 case '\0': tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_BOTTOM;
324 case 'w': tsoffset.flags = TK_OFFSET_LEFT|TK_OFFSET_BOTTOM;
326 case 'e': tsoffset.flags = TK_OFFSET_RIGHT|TK_OFFSET_BOTTOM;
331 if (strncmp(value, "center", strlen(value)) != 0) {
334 tsoffset.flags = TK_OFFSET_CENTER|TK_OFFSET_MIDDLE;
337 if ((q = strchr(p,',')) == NULL) {
338 if (((int)clientData) & TK_OFFSET_INDEX) {
339 if (Tcl_GetInt(interp, (char *) p, &tsoffset.flags) != TCL_OK) {
340 Tcl_ResetResult(interp);
343 tsoffset.flags |= TK_OFFSET_INDEX;
349 result = Tk_GetPixels(interp, tkwin, (char *) p, &tsoffset.xoffset);
351 if (result != TCL_OK) {
354 if (Tk_GetPixels(interp, tkwin, (char *) q+1, &tsoffset.yoffset) != TCL_OK) {
360 /* below is a hack to allow the stipple/tile offset to be stored
361 * in the internal tile structure. Most of the times, offsetPtr
362 * is a pointer to an already existing tile structure. However
363 * if this structure is not already created, we must do it
364 * with Tk_GetTile()!!!!;
367 memcpy(offsetPtr,&tsoffset, sizeof(Tk_TSOffset));
371 Tcl_AppendResult(interp, "bad offset \"", value,
372 "\": expected \"x,y\"", (char *) NULL);
373 if (((int) clientData) & TK_OFFSET_RELATIVE) {
374 Tcl_AppendResult(interp, ", \"#x,y\"", (char *) NULL);
376 if (((int) clientData) & TK_OFFSET_INDEX) {
377 Tcl_AppendResult(interp, ", <index>", (char *) NULL);
379 Tcl_AppendResult(interp, ", n, ne, e, se, s, sw, w, nw, or center",
385 *----------------------------------------------------------------------
387 * TkOffsetPrintProc --
389 * Returns the offset of the tile.
392 * The offset of the tile is returned.
394 *----------------------------------------------------------------------
398 TkOffsetPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
399 ClientData clientData; /* not used */
400 Tk_Window tkwin; /* not used */
401 char *widgRec; /* Widget structure record */
402 int offset; /* Offset of tile in record */
403 Tcl_FreeProc **freeProcPtr; /* not used */
405 Tk_TSOffset *offsetPtr = (Tk_TSOffset *)(widgRec + offset);
408 if ((offsetPtr->flags) & TK_OFFSET_INDEX) {
409 if ((offsetPtr->flags) >= INT_MAX) {
412 p = (char *) ckalloc(32);
413 sprintf(p, "%d",(offsetPtr->flags & (~TK_OFFSET_INDEX)));
414 *freeProcPtr = TCL_DYNAMIC;
417 if ((offsetPtr->flags) & TK_OFFSET_TOP) {
418 if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
420 } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
422 } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
425 } else if ((offsetPtr->flags) & TK_OFFSET_MIDDLE) {
426 if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
428 } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
430 } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
433 } else if ((offsetPtr->flags) & TK_OFFSET_BOTTOM) {
434 if ((offsetPtr->flags) & TK_OFFSET_LEFT) {
436 } else if ((offsetPtr->flags) & TK_OFFSET_CENTER) {
438 } else if ((offsetPtr->flags) & TK_OFFSET_RIGHT) {
442 q = p = (char *) ckalloc(32);
443 if ((offsetPtr->flags) & TK_OFFSET_RELATIVE) {
446 sprintf(q, "%d,%d",offsetPtr->xoffset, offsetPtr->yoffset);
447 *freeProcPtr = TCL_DYNAMIC;
453 *----------------------------------------------------------------------
455 * TkPixelParseProc --
457 * Converts the name of an image into a tile.
459 *----------------------------------------------------------------------
463 TkPixelParseProc(clientData, interp, tkwin, value, widgRec, offset)
464 ClientData clientData; /* if non-NULL, negative values are
466 Tcl_Interp *interp; /* Interpreter to send results back to */
467 Tk_Window tkwin; /* Window on same display as tile */
468 CONST char *value; /* Name of image */
469 char *widgRec; /* Widget structure record */
470 int offset; /* Offset of tile in record */
472 double *doublePtr = (double *)(widgRec + offset);
475 result = TkGetDoublePixels(interp, tkwin, value, doublePtr);
477 if ((result == TCL_OK) && (clientData == NULL) && (*doublePtr < 0.0)) {
478 Tcl_AppendResult(interp, "bad screen distance \"", value,
479 "\"", (char *) NULL);
486 *----------------------------------------------------------------------
488 * TkPixelPrintProc --
490 * Returns the name of the tile.
493 * The name of the tile is returned.
495 *----------------------------------------------------------------------
499 TkPixelPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
500 ClientData clientData; /* not used */
501 Tk_Window tkwin; /* not used */
502 char *widgRec; /* Widget structure record */
503 int offset; /* Offset of tile in record */
504 Tcl_FreeProc **freeProcPtr; /* not used */
506 double *doublePtr = (double *)(widgRec + offset);
509 p = (char *) ckalloc(24);
510 Tcl_PrintDouble((Tcl_Interp *) NULL, *doublePtr, p);
511 *freeProcPtr = TCL_DYNAMIC;
516 *----------------------------------------------------------------------
518 * TkDrawInsetFocusHighlight --
520 * This procedure draws a rectangular ring around the outside of
521 * a widget to indicate that it has received the input focus. It
522 * takes an additional padding argument that specifies how much
523 * padding is present outside th widget.
529 * A rectangle "width" pixels wide is drawn in "drawable",
530 * corresponding to the outer area of "tkwin".
532 *----------------------------------------------------------------------
536 TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, padding)
537 Tk_Window tkwin; /* Window whose focus highlight ring is
539 GC gc; /* Graphics context to use for drawing
540 * the highlight ring. */
541 int width; /* Width of the highlight ring, in pixels. */
542 Drawable drawable; /* Where to draw the ring (typically a
543 * pixmap for double buffering). */
544 int padding; /* Width of padding outside of widget. */
548 rects[0].x = padding;
549 rects[0].y = padding;
550 rects[0].width = Tk_Width(tkwin) - (2 * padding);
551 rects[0].height = width;
552 rects[1].x = padding;
553 rects[1].y = Tk_Height(tkwin) - width - padding;
554 rects[1].width = Tk_Width(tkwin) - (2 * padding);
555 rects[1].height = width;
556 rects[2].x = padding;
557 rects[2].y = width + padding;
558 rects[2].width = width;
559 rects[2].height = Tk_Height(tkwin) - 2*width - 2*padding;
560 rects[3].x = Tk_Width(tkwin) - width - padding;
561 rects[3].y = rects[2].y;
562 rects[3].width = width;
563 rects[3].height = rects[2].height;
564 XFillRectangles(Tk_Display(tkwin), drawable, gc, rects, 4);
568 *----------------------------------------------------------------------
570 * Tk_DrawFocusHighlight --
572 * This procedure draws a rectangular ring around the outside of
573 * a widget to indicate that it has received the input focus.
575 * This function is now deprecated. Use TkpDrawHighlightBorder instead,
576 * since this function does not handle drawing the Focus ring properly
577 * on the Macintosh - you need to know the background GC as well
578 * as the foreground since the Mac focus ring separated from the widget
579 * by a 1 pixel border.
585 * A rectangle "width" pixels wide is drawn in "drawable",
586 * corresponding to the outer area of "tkwin".
588 *----------------------------------------------------------------------
592 Tk_DrawFocusHighlight(tkwin, gc, width, drawable)
593 Tk_Window tkwin; /* Window whose focus highlight ring is
595 GC gc; /* Graphics context to use for drawing
596 * the highlight ring. */
597 int width; /* Width of the highlight ring, in pixels. */
598 Drawable drawable; /* Where to draw the ring (typically a
599 * pixmap for double buffering). */
601 TkDrawInsetFocusHighlight(tkwin, gc, width, drawable, 0);
605 *----------------------------------------------------------------------
607 * Tk_GetScrollInfo --
609 * This procedure is invoked to parse "xview" and "yview"
610 * scrolling commands for widgets using the new scrolling
611 * command syntax ("moveto" or "scroll" options).
614 * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
615 * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether
616 * the command was successfully parsed and what form the command
617 * took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the
618 * desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS,
619 * *intPtr is filled in with the number of lines to move (may be
620 * negative); if TK_SCROLL_ERROR, the interp's result contains an
626 *----------------------------------------------------------------------
630 Tk_GetScrollInfo(interp, argc, argv, dblPtr, intPtr)
631 Tcl_Interp *interp; /* Used for error reporting. */
632 int argc; /* # arguments for command. */
633 CONST char **argv; /* Arguments for command. */
634 double *dblPtr; /* Filled in with argument "moveto"
636 int *intPtr; /* Filled in with number of pages
637 * or lines to scroll, if any. */
642 length = strlen(argv[2]);
644 if ((c == 'm') && (strncmp(argv[2], "moveto", length) == 0)) {
646 Tcl_AppendResult(interp, "wrong # args: should be \"",
647 argv[0], " ", argv[1], " moveto fraction\"",
649 return TK_SCROLL_ERROR;
651 if (Tcl_GetDouble(interp, argv[3], dblPtr) != TCL_OK) {
652 return TK_SCROLL_ERROR;
654 return TK_SCROLL_MOVETO;
655 } else if ((c == 's')
656 && (strncmp(argv[2], "scroll", length) == 0)) {
658 Tcl_AppendResult(interp, "wrong # args: should be \"",
659 argv[0], " ", argv[1], " scroll number units|pages\"",
661 return TK_SCROLL_ERROR;
663 if (Tcl_GetInt(interp, argv[3], intPtr) != TCL_OK) {
664 return TK_SCROLL_ERROR;
666 length = strlen(argv[4]);
668 if ((c == 'p') && (strncmp(argv[4], "pages", length) == 0)) {
669 return TK_SCROLL_PAGES;
670 } else if ((c == 'u')
671 && (strncmp(argv[4], "units", length) == 0)) {
672 return TK_SCROLL_UNITS;
674 Tcl_AppendResult(interp, "bad argument \"", argv[4],
675 "\": must be units or pages", (char *) NULL);
676 return TK_SCROLL_ERROR;
679 Tcl_AppendResult(interp, "unknown option \"", argv[2],
680 "\": must be moveto or scroll", (char *) NULL);
681 return TK_SCROLL_ERROR;
685 *----------------------------------------------------------------------
687 * Tk_GetScrollInfoObj --
689 * This procedure is invoked to parse "xview" and "yview"
690 * scrolling commands for widgets using the new scrolling
691 * command syntax ("moveto" or "scroll" options).
694 * The return value is either TK_SCROLL_MOVETO, TK_SCROLL_PAGES,
695 * TK_SCROLL_UNITS, or TK_SCROLL_ERROR. This indicates whether
696 * the command was successfully parsed and what form the command
697 * took. If TK_SCROLL_MOVETO, *dblPtr is filled in with the
698 * desired position; if TK_SCROLL_PAGES or TK_SCROLL_UNITS,
699 * *intPtr is filled in with the number of lines to move (may be
700 * negative); if TK_SCROLL_ERROR, the interp's result contains an
706 *----------------------------------------------------------------------
710 Tk_GetScrollInfoObj(interp, objc, objv, dblPtr, intPtr)
711 Tcl_Interp *interp; /* Used for error reporting. */
712 int objc; /* # arguments for command. */
713 Tcl_Obj *CONST objv[]; /* Arguments for command. */
714 double *dblPtr; /* Filled in with argument "moveto"
716 int *intPtr; /* Filled in with number of pages
717 * or lines to scroll, if any. */
723 arg2 = Tcl_GetString(objv[2]);
724 length = strlen(arg2);
726 if ((c == 'm') && (strncmp(arg2, "moveto", length) == 0)) {
728 Tcl_WrongNumArgs(interp, 2, objv, "moveto fraction");
729 return TK_SCROLL_ERROR;
731 if (Tcl_GetDoubleFromObj(interp, objv[3], dblPtr) != TCL_OK) {
732 return TK_SCROLL_ERROR;
734 return TK_SCROLL_MOVETO;
735 } else if ((c == 's')
736 && (strncmp(arg2, "scroll", length) == 0)) {
738 Tcl_WrongNumArgs(interp, 2, objv, "scroll number units|pages");
739 return TK_SCROLL_ERROR;
741 if (Tcl_GetIntFromObj(interp, objv[3], intPtr) != TCL_OK) {
742 return TK_SCROLL_ERROR;
744 arg4 = Tcl_GetString(objv[4]);
745 length = (strlen(arg4));
747 if ((c == 'p') && (strncmp(arg4, "pages", length) == 0)) {
748 return TK_SCROLL_PAGES;
749 } else if ((c == 'u')
750 && (strncmp(arg4, "units", length) == 0)) {
751 return TK_SCROLL_UNITS;
753 Tcl_AppendResult(interp, "bad argument \"", arg4,
754 "\": must be units or pages", (char *) NULL);
755 return TK_SCROLL_ERROR;
758 Tcl_AppendResult(interp, "unknown option \"", arg2,
759 "\": must be moveto or scroll", (char *) NULL);
760 return TK_SCROLL_ERROR;
764 *---------------------------------------------------------------------------
768 * Determine where to place a rectangle so that it will be properly
769 * anchored with respect to the given window. Used by widgets
770 * to align a box of text inside a window. When anchoring with
771 * respect to one of the sides, the rectangle be placed inside of
772 * the internal border of the window.
775 * *xPtr and *yPtr set to the upper-left corner of the rectangle
776 * anchored in the window.
781 *---------------------------------------------------------------------------
784 TkComputeAnchor(anchor, tkwin, padX, padY, innerWidth, innerHeight, xPtr, yPtr)
785 Tk_Anchor anchor; /* Desired anchor. */
786 Tk_Window tkwin; /* Anchored with respect to this window. */
787 int padX, padY; /* Use this extra padding inside window, in
788 * addition to the internal border. */
789 int innerWidth, innerHeight;/* Size of rectangle to anchor in window. */
790 int *xPtr, *yPtr; /* Returns upper-left corner of anchored
797 *xPtr = Tk_InternalBorderLeft(tkwin) + padX;
801 case TK_ANCHOR_CENTER:
803 *xPtr = (Tk_Width(tkwin) - innerWidth) / 2;
807 *xPtr = Tk_Width(tkwin) - (Tk_InternalBorderRight(tkwin) + padX)
816 *yPtr = Tk_InternalBorderTop(tkwin) + padY;
820 case TK_ANCHOR_CENTER:
822 *yPtr = (Tk_Height(tkwin) - innerHeight) / 2;
826 *yPtr = Tk_Height(tkwin) - Tk_InternalBorderBottom(tkwin) - padY
833 *---------------------------------------------------------------------------
835 * TkFindStateString --
837 * Given a lookup table, map a number to a string in the table.
840 * If numKey was equal to the numeric key of one of the elements
841 * in the table, returns the string key of that element.
842 * Returns NULL if numKey was not equal to any of the numeric keys
848 *---------------------------------------------------------------------------
852 TkFindStateString(mapPtr, numKey)
853 CONST TkStateMap *mapPtr; /* The state table. */
854 int numKey; /* The key to try to find in the table. */
856 for ( ; mapPtr->strKey != NULL; mapPtr++) {
857 if (numKey == mapPtr->numKey) {
858 return mapPtr->strKey;
865 *---------------------------------------------------------------------------
869 * Given a lookup table, map a string to a number in the table.
872 * If strKey was equal to the string keys of one of the elements
873 * in the table, returns the numeric key of that element.
874 * Returns the numKey associated with the last element (the NULL
875 * string one) in the table if strKey was not equal to any of the
876 * string keys in the table. In that case, an error message is
877 * also left in the interp's result (if interp is not NULL).
882 *---------------------------------------------------------------------------
886 TkFindStateNum(interp, option, mapPtr, strKey)
887 Tcl_Interp *interp; /* Interp for error reporting. */
888 CONST char *option; /* String to use when constructing error. */
889 CONST TkStateMap *mapPtr; /* Lookup table. */
890 CONST char *strKey; /* String to try to find in lookup table. */
892 CONST TkStateMap *mPtr;
894 for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
895 if (strcmp(strKey, mPtr->strKey) == 0) {
899 if (interp != NULL) {
901 Tcl_AppendResult(interp, "bad ", option, " value \"", strKey,
902 "\": must be ", mPtr->strKey, (char *) NULL);
903 for (mPtr++; mPtr->strKey != NULL; mPtr++) {
904 Tcl_AppendResult(interp,
905 ((mPtr[1].strKey != NULL) ? ", " : ", or "),
906 mPtr->strKey, (char *) NULL);
913 TkFindStateNumObj(interp, optionPtr, mapPtr, keyPtr)
914 Tcl_Interp *interp; /* Interp for error reporting. */
915 Tcl_Obj *optionPtr; /* String to use when constructing error. */
916 CONST TkStateMap *mapPtr; /* Lookup table. */
917 Tcl_Obj *keyPtr; /* String key to find in lookup table. */
919 CONST TkStateMap *mPtr;
921 CONST Tcl_ObjType *typePtr;
923 if ((keyPtr->typePtr == &tkStateKeyObjType)
924 && (keyPtr->internalRep.twoPtrValue.ptr1 == (VOID *) mapPtr)) {
925 return (int) keyPtr->internalRep.twoPtrValue.ptr2;
928 key = Tcl_GetStringFromObj(keyPtr, NULL);
929 for (mPtr = mapPtr; mPtr->strKey != NULL; mPtr++) {
930 if (strcmp(key, mPtr->strKey) == 0) {
931 typePtr = keyPtr->typePtr;
932 if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) {
933 (*typePtr->freeIntRepProc)(keyPtr);
935 keyPtr->internalRep.twoPtrValue.ptr1 = (VOID *) mapPtr;
936 keyPtr->internalRep.twoPtrValue.ptr2 = (VOID *) mPtr->numKey;
937 keyPtr->typePtr = &tkStateKeyObjType;
941 if (interp != NULL) {
943 Tcl_AppendResult(interp, "bad ",
944 Tcl_GetStringFromObj(optionPtr, NULL), " value \"", key,
945 "\": must be ", mPtr->strKey, (char *) NULL);
946 for (mPtr++; mPtr->strKey != NULL; mPtr++) {
947 Tcl_AppendResult(interp,
948 ((mPtr[1].strKey != NULL) ? ", " : ", or "),
949 mPtr->strKey, (char *) NULL);