summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkInt.h2
-rw-r--r--generic/tkMenu.c32
-rw-r--r--generic/tkObj.c76
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