diff options
-rw-r--r-- | generic/tkInt.h | 2 | ||||
-rw-r--r-- | generic/tkMenu.c | 32 | ||||
-rw-r--r-- | generic/tkObj.c | 76 |
3 files changed, 90 insertions, 20 deletions
diff --git a/generic/tkInt.h b/generic/tkInt.h index 7ef7862..e797d29 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1331,6 +1331,8 @@ MODULE_SCOPE int TkListCreateFrame(ClientData clientData, MODULE_SCOPE void TkRotatePoint(double originX, double originY, double sine, double cosine, double *xPtr, double *yPtr); +MODULE_SCOPE int TkGetIntForIndex(Tcl_Obj *, TkSizeT, TkSizeT*); + #ifdef _WIN32 #define TkParseColor XParseColor diff --git a/generic/tkMenu.c b/generic/tkMenu.c index faadc81..ed434e9 100644 --- a/generic/tkMenu.c +++ b/generic/tkMenu.c @@ -2126,15 +2126,25 @@ GetMenuIndex( TkSizeT *indexPtr) /* Where to store converted index. */ { int i; - const char *string = Tcl_GetString(objPtr); + const char *string; + + if (TkGetIntForIndex(objPtr, menuPtr->numEntries - ((lastOK) ? 0 : 1), indexPtr) == TCL_OK) { + if (*indexPtr != TCL_INDEX_NONE) { + if (*indexPtr >= menuPtr->numEntries) { + *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1); + } + return TCL_OK; + } + } + + string = Tcl_GetString(objPtr); if ((string[0] == 'a') && (strcmp(string, "active") == 0)) { *indexPtr = menuPtr->active; goto success; } - if (((string[0] == 'l') && (strcmp(string, "last") == 0)) - || ((string[0] == 'e') && (strcmp(string, "end") == 0))) { + if ((string[0] == 'l') && (strcmp(string, "last") == 0)) { *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1); goto success; } @@ -2151,22 +2161,6 @@ GetMenuIndex( } } - if (isdigit(UCHAR(string[0]))) { - if (Tcl_GetIntFromObj(NULL, objPtr, &i) == TCL_OK) { - if (i >= (int)menuPtr->numEntries) { - if (lastOK) { - i = menuPtr->numEntries; - } else { - i = menuPtr->numEntries-1; - } - } else if (i < 0) { - i = -1; - } - *indexPtr = i; - goto success; - } - } - for (i = 0; i < (int)menuPtr->numEntries; i++) { Tcl_Obj *labelPtr = menuPtr->entries[i]->labelPtr; const char *label = (labelPtr == NULL) ? NULL : Tcl_GetString(labelPtr); diff --git a/generic/tkObj.c b/generic/tkObj.c index 1a98db6..bbd331c 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -50,6 +50,7 @@ typedef struct PixelRep { typedef struct { const Tcl_ObjType *doubleTypePtr; const Tcl_ObjType *intTypePtr; + const Tcl_ObjType *endTypePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -97,6 +98,29 @@ static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +#if TCL_MAJOR_VERSION < 9 +#if defined(USE_TCL_STUBS) +/* Little hack to eliminate the need for "tclInt.h" here: + Just copy a small portion of TclIntStubs, just + enough to make it work */ +typedef struct TclIntStubs { + int magic; + void *hooks; + void (*dummy[34]) (void); /* dummy entries 0-33, not used */ + int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */ +} TclIntStubs; +extern const struct TclIntStubs *tclIntStubsPtr; + +# undef Tcl_GetIntForIndex +# define Tcl_GetIntForIndex(interp, obj, max, ptr) ((tclIntStubsPtr->tclGetIntForIndex == NULL)? \ + ((int (*)(Tcl_Interp*, Tcl_Obj *, int, int*))(void *)((&(tclStubsPtr->tcl_PkgProvideEx))[645]))((interp), (obj), (max), (ptr)): \ + tclIntStubsPtr->tclGetIntForIndex((interp), (obj), (max), (ptr))) +#elif TCL_MINOR_VERSION < 7 +extern int TclGetIntForIndex(Tcl_Interp*, Tcl_Obj *, int, int*); +# define Tcl_GetIntForIndex TclGetIntForIndex +#endif +#endif + /* * The following structure defines the implementation of the "pixel" Tcl * object, used for measuring distances. The pixel object remembers its @@ -160,12 +184,17 @@ GetTypeCache(void) /* Smart initialization of doubleTypePtr/intTypePtr without * hash-table lookup or creating complete Tcl_Obj's */ Tcl_Obj obj; + obj.bytes = (char *)"end"; obj.length = 3; + obj.typePtr = NULL; + Tcl_GetIntForIndex(NULL, &obj, TCL_INDEX_NONE, (TkSizeT *)&obj.internalRep.doubleValue); + tsdPtr->endTypePtr = obj.typePtr; obj.bytes = (char *)"0.0"; + obj.length = 3; obj.typePtr = NULL; Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue); tsdPtr->doubleTypePtr = obj.typePtr; - obj.bytes += 2; + obj.bytes = (char *)"0"; obj.length = 1; obj.typePtr = NULL; Tcl_GetLongFromObj(NULL, &obj, &obj.internalRep.longValue); @@ -177,6 +206,51 @@ GetTypeCache(void) /* *---------------------------------------------------------------------- * + * TkGetIntForIndex -- + * + * Almost the same as Tcl_GetIntForIndex, but it return an int, and it is + * more restricted. For example it only accepts "end", not "end-1", and + * only "2", not "1+1" + * + * Results: + * The return value is a standard Tcl object result. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +int +TkGetIntForIndex(Tcl_Obj *indexObj, TkSizeT end, TkSizeT *indexPtr) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (Tcl_GetIntForIndex(NULL, indexObj, end, indexPtr) != TCL_OK) { + return TCL_ERROR; + } + if (indexObj->typePtr == tsdPtr->endTypePtr) { + /* check for "end", but not "end-??" or "end+??" */ + return (*indexPtr == end) ? TCL_OK : TCL_ERROR; + } + if (indexObj->typePtr != tsdPtr->intTypePtr) { + /* Neither do we accept "??-??" or "??+??" */ + return TCL_ERROR; + } +#if TCL_MAJOR_VERSION < 9 + if (*indexPtr < -1) { + *indexPtr = TCL_INDEX_NONE; + } +#endif + if ((*indexPtr != TCL_INDEX_NONE) && (*indexPtr > end)) { + *indexPtr = end + 1; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * GetPixelsFromObjEx -- * * Attempt to return a pixel value from the Tcl object "objPtr". If the |