Attachment "tk-cargo.patch" to
ticket [3023578f]
added by
russty1971
2010-07-01 06:02:30.
diff -rup tk8.5.8_base/generic/tkButton.c tk8.5.8/generic/tkButton.c
--- tk8.5.8_base/generic/tkButton.c 2009-05-14 08:04:40.000000000 -0400
+++ tk8.5.8/generic/tkButton.c 2010-06-29 15:16:15.397570840 -0400
@@ -491,23 +491,24 @@ static Tk_OptionSpec * const optionSpecs
* enumerated type used to dispatch the widget command.
*/
-static const char *commandNames[][8] = {
- {"cget", "configure", NULL},
- {"cget", "configure", "flash", "invoke", NULL},
- {"cget", "configure", "deselect", "flash", "invoke", "select",
+static const char *commandNames[][9] = {
+ {"cget", "configure", "cargo", NULL},
+ {"cget", "configure", "cargo", "flash", "invoke", NULL},
+ {"cget", "configure", "cargo", "deselect", "flash", "invoke", "select",
"toggle", NULL},
- {"cget", "configure", "deselect", "flash", "invoke", "select", NULL}
+ {"cget", "configure", "cargo", "deselect", "flash", "invoke", "select", NULL}
};
enum command {
- COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO, COMMAND_DESELECT, COMMAND_FLASH,
COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE
+
};
-static enum command map[][8] = {
- {COMMAND_CGET, COMMAND_CONFIGURE},
- {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_FLASH, COMMAND_INVOKE},
- {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+static enum command map[][9] = {
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO, COMMAND_FLASH, COMMAND_INVOKE},
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO, COMMAND_DESELECT, COMMAND_FLASH,
COMMAND_INVOKE, COMMAND_SELECT, COMMAND_TOGGLE},
- {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DESELECT, COMMAND_FLASH,
+ {COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO, COMMAND_DESELECT, COMMAND_FLASH,
COMMAND_INVOKE, COMMAND_SELECT}
};
@@ -542,6 +543,12 @@ static int ButtonWidgetObjCmd(ClientDat
static int ConfigureButton(Tcl_Interp *interp, TkButton *butPtr,
int objc, Tcl_Obj *const objv[]);
static void DestroyButton(TkButton *butPtr);
+static int AddCargo(TkButton *butPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(TkButton *butPtr, char *name);
+static int DestroyCargo(TkButton *butPtr);
+static Tcl_Obj * GetCargo(TkButton *butPtr, char *entry);
+static Tcl_Obj * ListCargo(TkButton *butPtr);
+static int SetCargo(TkButton *butPtr, int objc, Tcl_Obj *const objv[]);
/*
*--------------------------------------------------------------
@@ -738,6 +745,7 @@ ButtonCreate(
butPtr->takeFocusPtr = NULL;
butPtr->commandPtr = NULL;
butPtr->flags = 0;
+ butPtr->cargo = NULL;
Tk_CreateEventHandler(butPtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
@@ -915,6 +923,49 @@ ButtonWidgetObjCmd(
goto error;
}
break;
+ case COMMAND_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(butPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(butPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(butPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(butPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(butPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(butPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
Tcl_Release((ClientData) butPtr);
return result;
@@ -923,6 +974,310 @@ ButtonWidgetObjCmd(
Tcl_Release((ClientData) butPtr);
return TCL_ERROR;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(TkButton *butPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = butPtr->cargo;
+ if (butPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(butPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(TkButton *butPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (butPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = butPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ butPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ butPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(TkButton *butPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = butPtr->cargo;
+ while (butPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = butPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != butPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(butPtr->cargo);
+ butPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(TkButton *butPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = butPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(TkButton *butPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (butPtr->cargo != NULL) {
+ depCursor = butPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = butPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(TkButton *butPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (butPtr->cargo == NULL) {
+ butPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ butPtr->cargo->next = NULL;
+ depCursor = butPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = butPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(butPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -998,6 +1353,7 @@ DestroyButton(
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ButtonVarProc, (ClientData) butPtr);
}
+ DestroyCargo(butPtr);
Tk_FreeConfigOptions((char *) butPtr, butPtr->optionTable,
butPtr->tkwin);
butPtr->tkwin = NULL;
diff -rup tk8.5.8_base/generic/tkButton.h tk8.5.8/generic/tkButton.h
--- tk8.5.8_base/generic/tkButton.h 2007-12-13 10:24:13.000000000 -0500
+++ tk8.5.8/generic/tkButton.h 2010-06-29 15:16:15.400580703 -0400
@@ -54,6 +54,17 @@ enum defaultState {
* this file:
*/
+/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
typedef struct {
Tk_Window tkwin; /* Window that embodies the button. NULL means
* that the window has been destroyed. */
@@ -262,6 +273,7 @@ typedef struct {
* invocataions of the button command. */
int flags; /* Various flags; see below for
* definitions. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} TkButton;
/*
diff -rup tk8.5.8_base/generic/tkCanvas.c tk8.5.8/generic/tkCanvas.c
--- tk8.5.8_base/generic/tkCanvas.c 2008-10-11 02:55:03.000000000 -0400
+++ tk8.5.8/generic/tkCanvas.c 2010-06-29 15:16:15.410574375 -0400
@@ -320,6 +320,13 @@ static Tk_Item * TagSearchFirst(TagSearc
static Tk_Item * TagSearchNext(TagSearch *searchPtr);
#endif /* USE_OLD_TAG_SEARCH */
+static int AddCargo(TkCanvas *canvasPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(TkCanvas *canvasPtr, char *name);
+static int DestroyCargo(TkCanvas *canvasPtr);
+static Tcl_Obj * GetCargo(TkCanvas *canvasPtr, char *entry);
+static Tcl_Obj * ListCargo(TkCanvas *canvasPtr);
+static int SetCargo(TkCanvas *canvasPtr, int objc, Tcl_Obj *const objv[]);
+
/*
* The structure below defines canvas class behavior by means of functions
* that can be invoked from generic window code.
@@ -476,6 +483,7 @@ Tk_CanvasObjCmd(
canvasPtr->tsoffset.flags = 0;
canvasPtr->tsoffset.xoffset = 0;
canvasPtr->tsoffset.yoffset = 0;
+ canvasPtr->cargo = NULL;
#ifndef USE_OLD_TAG_SEARCH
canvasPtr->bindTagExprs = NULL;
#endif
@@ -549,7 +557,7 @@ CanvasWidgetCmd(
"index", "insert", "itemcget", "itemconfigure",
"lower", "move", "postscript", "raise",
"scale", "scan", "select", "type",
- "xview", "yview",
+ "xview", "yview", "cargo",
NULL
};
enum options {
@@ -560,7 +568,7 @@ CanvasWidgetCmd(
CANV_INDEX, CANV_INSERT, CANV_ITEMCGET, CANV_ITEMCONFIGURE,
CANV_LOWER, CANV_MOVE, CANV_POSTSCRIPT,CANV_RAISE,
CANV_SCALE, CANV_SCAN, CANV_SELECT, CANV_TYPE,
- CANV_XVIEW, CANV_YVIEW
+ CANV_XVIEW, CANV_YVIEW, CANV_CARGO
};
if (objc < 2) {
@@ -1776,6 +1784,49 @@ CanvasWidgetCmd(
}
break;
}
+ case CANV_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(canvasPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(canvasPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(canvasPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(canvasPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(canvasPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(canvasPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
done:
@@ -1785,6 +1836,310 @@ CanvasWidgetCmd(
Tcl_Release((ClientData) canvasPtr);
return result;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(TkCanvas *canvasPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = canvasPtr->cargo;
+ if (canvasPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(canvasPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(TkCanvas *canvasPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (canvasPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = canvasPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ canvasPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ canvasPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(TkCanvas *canvasPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = canvasPtr->cargo;
+ while (canvasPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = canvasPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != canvasPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(canvasPtr->cargo);
+ canvasPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(TkCanvas *canvasPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = canvasPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(TkCanvas *canvasPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (canvasPtr->cargo != NULL) {
+ depCursor = canvasPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = canvasPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(TkCanvas *canvasPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (canvasPtr->cargo == NULL) {
+ canvasPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ canvasPtr->cargo->next = NULL;
+ depCursor = canvasPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = canvasPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(canvasPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -1853,6 +2208,8 @@ DestroyCanvas(
Tk_FreeOptions(configSpecs, (char *) canvasPtr, canvasPtr->display, 0);
canvasPtr->tkwin = NULL;
ckfree((char *) canvasPtr);
+
+ DestroyCargo(canvasPtr);
}
/*
diff -rup tk8.5.8_base/generic/tkCanvas.h tk8.5.8/generic/tkCanvas.h
--- tk8.5.8_base/generic/tkCanvas.h 2007-12-13 10:24:13.000000000 -0500
+++ tk8.5.8/generic/tkCanvas.h 2010-06-29 15:16:15.412579647 -0400
@@ -38,6 +38,17 @@ struct TagSearchExpr_s {
#endif /* not USE_OLD_TAG_SEARCH */
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* The record below describes a canvas widget. It is made available to the
* item functions so they can access certain shared fields such as the overall
* displacement and scale factor for the canvas.
@@ -232,6 +243,7 @@ typedef struct TkCanvas {
void *reserved2;
void *reserved3;
Tk_TSOffset tsoffset;
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
#ifndef USE_OLD_TAG_SEARCH
TagSearchExpr *bindTagExprs;/* Linked list of tag expressions used in
* bindings. */
diff -rup tk8.5.8_base/generic/tkEntry.c tk8.5.8/generic/tkEntry.c
--- tk8.5.8_base/generic/tkEntry.c 2008-10-09 11:17:44.000000000 -0400
+++ tk8.5.8/generic/tkEntry.c 2010-06-29 15:16:15.420576429 -0400
@@ -321,13 +321,14 @@ static const Tk_OptionSpec sbOptSpec[] =
static CONST char *entryCmdNames[] = {
"bbox", "cget", "configure", "delete", "get", "icursor", "index",
- "insert", "scan", "selection", "validate", "xview", NULL
+ "insert", "scan", "selection", "validate", "xview", "cargo", NULL
};
enum entryCmd {
COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE,
COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT,
- COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW
+ COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW,
+ COMMAND_CARGO
};
static CONST char *selCmdNames[] = {
@@ -348,14 +349,14 @@ enum selCmd {
static CONST char *sbCmdNames[] = {
"bbox", "cget", "configure", "delete", "get", "icursor", "identify",
"index", "insert", "invoke", "scan", "selection", "set",
- "validate", "xview", NULL
+ "validate", "xview", "cargo", NULL
};
enum sbCmd {
SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE,
SB_CMD_GET, SB_CMD_ICURSOR, SB_CMD_IDENTIFY, SB_CMD_INDEX,
SB_CMD_INSERT, SB_CMD_INVOKE, SB_CMD_SCAN, SB_CMD_SELECTION,
- SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW
+ SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW, SB_CMD_CARGO
};
static CONST char *sbSelCmdNames[] = {
@@ -430,6 +431,12 @@ static void EntryWorldChanged(ClientDat
static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,
char *string, int *indexPtr);
static void InsertChars(Entry *entryPtr, int index, char *string);
+static int AddCargo(Entry *entryPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(Entry *entryPtr, char *name);
+static int DestroyCargo(Entry *entryPtr);
+static Tcl_Obj * GetCargo(Entry *entryPtr, char *entry);
+static Tcl_Obj * ListCargo(Entry *entryPtr);
+static int SetCargo(Entry *entryPtr, int objc, Tcl_Obj *const objv[]);
/*
* These forward declarations are the spinbox specific ones:
@@ -537,6 +544,7 @@ Tk_EntryObjCmd(
entryPtr->highlightGC = None;
entryPtr->avgWidth = 1;
entryPtr->validate = VALIDATE_NONE;
+ entryPtr->cargo = NULL;
/*
* Keep a hold of the associated tkwin until we destroy the entry,
@@ -979,6 +987,49 @@ EntryWidgetObjCmd(
EventuallyRedraw(entryPtr);
break;
}
+ case COMMAND_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(entryPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(entryPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(entryPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(entryPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(entryPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(entryPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
done:
@@ -989,6 +1040,310 @@ EntryWidgetObjCmd(
Tcl_Release((ClientData) entryPtr);
return TCL_ERROR;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(Entry *entryPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = entryPtr->cargo;
+ if (entryPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(entryPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(Entry *entryPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (entryPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = entryPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ entryPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ entryPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(Entry *entryPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = entryPtr->cargo;
+ while (entryPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = entryPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != entryPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(entryPtr->cargo);
+ entryPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(Entry *entryPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = entryPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(Entry *entryPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (entryPtr->cargo != NULL) {
+ depCursor = entryPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = entryPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(Entry *entryPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (entryPtr->cargo == NULL) {
+ entryPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ entryPtr->cargo->next = NULL;
+ depCursor = entryPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = entryPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(entryPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -1054,6 +1409,7 @@ DestroyEntry(
entryPtr->tkwin = NULL;
ckfree((char *) entryPtr);
+ DestroyCargo(entryPtr);
}
/*
@@ -4099,6 +4455,49 @@ SpinboxWidgetObjCmd(
EventuallyRedraw(entryPtr);
break;
}
+ case SB_CMD_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(entryPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(entryPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(entryPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(entryPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(entryPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(entryPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
done:
diff -rup tk8.5.8_base/generic/tkEntry.h tk8.5.8/generic/tkEntry.h
--- tk8.5.8_base/generic/tkEntry.h 2005-11-26 21:36:13.000000000 -0500
+++ tk8.5.8/generic/tkEntry.h 2010-06-29 15:16:15.423577911 -0400
@@ -26,6 +26,17 @@ enum EntryType {
};
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each Entry widget
* managed by this file:
*/
@@ -178,6 +189,7 @@ typedef struct {
* commands. Malloc'ed. */
char *invalidCmd; /* Command called when a validation returns 0
* (successfully fails), defaults to {}. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} Entry;
/*
@@ -234,6 +246,7 @@ typedef struct {
Tcl_Obj *listObj; /* Pointer to the list object being used */
int eIndex; /* Holds the current index into elements */
int nElements; /* Holds the current count of elements */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} Spinbox;
/*
diff -rup tk8.5.8_base/generic/tkFrame.c tk8.5.8/generic/tkFrame.c
--- tk8.5.8_base/generic/tkFrame.c 2008-11-14 19:37:30.000000000 -0500
+++ tk8.5.8/generic/tkFrame.c 2010-06-29 15:16:15.428572372 -0400
@@ -26,6 +26,17 @@ enum FrameType {
};
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each
* frame that currently exists for this process:
*/
@@ -96,6 +107,7 @@ typedef struct {
* pixels of extra space to leave above and
* below child area. */
int padY; /* Integer value corresponding to padYPtr. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} Frame;
/*
@@ -323,6 +335,12 @@ static int FrameWidgetObjCmd(ClientData
Tcl_Obj *CONST objv[]);
static void FrameWorldChanged(ClientData instanceData);
static void MapFrame(ClientData clientData);
+static int AddCargo(Frame *framePtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(Frame *framePtr, char *name);
+static int DestroyCargo(Frame *framePtr);
+static Tcl_Obj * GetCargo(Frame *framePtr, char *entry);
+static Tcl_Obj * ListCargo(Frame *framePtr);
+static int SetCargo(Frame *framePtr, int objc, Tcl_Obj *const objv[]);
/*
* The structure below defines frame class behavior by means of functions that
@@ -636,6 +654,7 @@ CreateFrame(
framePtr->colormap = colormap;
framePtr->relief = TK_RELIEF_FLAT;
framePtr->cursor = None;
+ framePtr->cargo = NULL;
if (framePtr->type == TYPE_LABELFRAME) {
Labelframe *labelframePtr = (Labelframe *) framePtr;
@@ -707,10 +726,10 @@ FrameWidgetObjCmd(
Tcl_Obj *CONST objv[]) /* Argument objects. */
{
static CONST char *frameOptions[] = {
- "cget", "configure", NULL
+ "cget", "configure", "cargo", NULL
};
enum options {
- FRAME_CGET, FRAME_CONFIGURE
+ FRAME_CGET, FRAME_CONFIGURE, FRAME_CARGO
};
register Frame *framePtr = (Frame *) clientData;
int result = TCL_OK, index;
@@ -804,12 +823,359 @@ FrameWidgetObjCmd(
result = ConfigureFrame(interp, framePtr, objc-2, objv+2);
}
break;
+ case FRAME_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(framePtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(framePtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(framePtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(framePtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(framePtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(framePtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
done:
Tcl_Release((ClientData) framePtr);
return result;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(Frame *framePtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = framePtr->cargo;
+ if (framePtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(framePtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(Frame *framePtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (framePtr->cargo != NULL) {
+ depCursor1 = depCursor2 = framePtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ framePtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ framePtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(Frame *framePtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = framePtr->cargo;
+ while (framePtr->cargo != NULL) {
+ depCursor1 = depCursor2 = framePtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != framePtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(framePtr->cargo);
+ framePtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(Frame *framePtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = framePtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(Frame *framePtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (framePtr->cargo != NULL) {
+ depCursor = framePtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = framePtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(Frame *framePtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (framePtr->cargo == NULL) {
+ framePtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ framePtr->cargo->next = NULL;
+ depCursor = framePtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = framePtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(framePtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -846,6 +1212,7 @@ DestroyFrame(
Tk_FreeColormap(framePtr->display, framePtr->colormap);
}
ckfree((char *) framePtr);
+ DestroyCargo(framePtr);
}
/*
diff -rup tk8.5.8_base/generic/tkListbox.c tk8.5.8/generic/tkListbox.c
--- tk8.5.8_base/generic/tkListbox.c 2009-03-03 18:54:11.000000000 -0500
+++ tk8.5.8/generic/tkListbox.c 2010-06-29 15:21:44.980569740 -0400
@@ -31,6 +31,17 @@ typedef struct {
} ListboxOptionTables;
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each listbox widget
* managed by this file:
*/
@@ -167,6 +178,7 @@ typedef struct {
Pixmap gray; /* Pixmap for displaying disabled text. */
int flags; /* Various flag bits: see below for
* definitions. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} Listbox;
/*
@@ -343,14 +355,14 @@ static const Tk_OptionSpec itemAttrOptio
static const char *commandNames[] = {
"activate", "bbox", "cget", "configure", "curselection", "delete", "get",
"index", "insert", "itemcget", "itemconfigure", "nearest", "scan",
- "see", "selection", "size", "xview", "yview", NULL
+ "see", "selection", "size", "xview", "yview", "cargo", NULL
};
enum command {
COMMAND_ACTIVATE, COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE,
COMMAND_CURSELECTION, COMMAND_DELETE, COMMAND_GET, COMMAND_INDEX,
COMMAND_INSERT, COMMAND_ITEMCGET, COMMAND_ITEMCONFIGURE,
COMMAND_NEAREST, COMMAND_SCAN, COMMAND_SEE, COMMAND_SELECTION,
- COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW
+ COMMAND_SIZE, COMMAND_XVIEW, COMMAND_YVIEW, COMMAND_CARGO
};
static const char *selCommandNames[] = {
@@ -430,6 +442,12 @@ static char * ListboxListVarProc(Client
const char *name2, int flags);
static void MigrateHashEntries(Tcl_HashTable *table,
int first, int last, int offset);
+static int AddCargo(Listbox *listPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(Listbox *listPtr, char *name);
+static int DestroyCargo(Listbox *listPtr);
+static Tcl_Obj * GetCargo(Listbox *listPtr, char *entry);
+static Tcl_Obj * ListCargo(Listbox *listPtr);
+static int SetCargo(Listbox *listPtr, int objc, Tcl_Obj *const objv[]);
/*
* The structure below defines button class behavior by means of procedures
@@ -542,6 +560,7 @@ Tk_ListboxObjCmd(
listPtr->cursor = None;
listPtr->state = STATE_NORMAL;
listPtr->gray = None;
+ listPtr->cargo = NULL;
/*
* Keep a hold of the associated tkwin until we destroy the listbox,
@@ -1048,10 +1067,357 @@ ListboxWidgetObjCmd(
case COMMAND_YVIEW:
result = ListboxYviewSubCmd(interp, listPtr, objc, objv);
break;
+ case COMMAND_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(listPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(listPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(listPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(listPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(listPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(listPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
Tcl_Release((ClientData)listPtr);
return result;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(Listbox *listPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = listPtr->cargo;
+ if (listPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(listPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(Listbox *listPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (listPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = listPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ listPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ listPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(Listbox *listPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = listPtr->cargo;
+ while (listPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = listPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != listPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(listPtr->cargo);
+ listPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(Listbox *listPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = listPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(Listbox *listPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (listPtr->cargo != NULL) {
+ depCursor = listPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = listPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(Listbox *listPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (listPtr->cargo == NULL) {
+ listPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ listPtr->cargo->next = NULL;
+ depCursor = listPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = listPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(listPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -1483,6 +1849,7 @@ DestroyListbox(
Tk_FreeBitmap(Tk_Display(listPtr->tkwin), listPtr->gray);
}
+ DestroyCargo(listPtr);
Tk_FreeConfigOptions((char *)listPtr, listPtr->optionTable,
listPtr->tkwin);
Tcl_Release((ClientData) listPtr->tkwin);
Only in tk8.5.8/generic: tkListbox.c~
diff -rup tk8.5.8_base/generic/tkMenubutton.c tk8.5.8/generic/tkMenubutton.c
--- tk8.5.8_base/generic/tkMenubutton.c 2009-04-10 12:07:56.000000000 -0400
+++ tk8.5.8/generic/tkMenubutton.c 2010-06-29 15:16:15.438570794 -0400
@@ -154,11 +154,11 @@ static const Tk_OptionSpec optionSpecs[]
*/
static CONST char *commandNames[] = {
- "cget", "configure", NULL
+ "cget", "configure", "cargo", NULL
};
enum command {
- COMMAND_CGET, COMMAND_CONFIGURE
+ COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_CARGO
};
/*
@@ -181,6 +181,12 @@ static int ConfigureMenuButton(Tcl_Inte
TkMenuButton *mbPtr, int objc,
Tcl_Obj *CONST objv[]);
static void DestroyMenuButton(char *memPtr);
+static int AddCargo(TkMenuButton *mbPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(TkMenuButton *mbPtr, char *name);
+static int DestroyCargo(TkMenuButton *mbPtr);
+static Tcl_Obj * GetCargo(TkMenuButton *mbPtr, char *entry);
+static Tcl_Obj * ListCargo(TkMenuButton *mbPtr);
+static int SetCargo(TkMenuButton *mbPtr, int objc, Tcl_Obj *const objv[]);
/*
*--------------------------------------------------------------
@@ -293,6 +299,7 @@ Tk_MenubuttonObjCmd(
mbPtr->cursor = None;
mbPtr->takeFocus = NULL;
mbPtr->flags = 0;
+ mbPtr->cargo = NULL;
Tk_CreateEventHandler(mbPtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
@@ -382,6 +389,49 @@ MenuButtonWidgetObjCmd(
result = ConfigureMenuButton(interp, mbPtr, objc-2, objv+2);
}
break;
+ case COMMAND_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(mbPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(mbPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(mbPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(mbPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(mbPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(mbPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
Tcl_Release((ClientData) mbPtr);
return result;
@@ -390,6 +440,310 @@ MenuButtonWidgetObjCmd(
Tcl_Release((ClientData) mbPtr);
return TCL_ERROR;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(TkMenuButton *mbPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = mbPtr->cargo;
+ if (mbPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(mbPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(TkMenuButton *mbPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (mbPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = mbPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ mbPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ mbPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(TkMenuButton *mbPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = mbPtr->cargo;
+ while (mbPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = mbPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != mbPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(mbPtr->cargo);
+ mbPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(TkMenuButton *mbPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = mbPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(TkMenuButton *mbPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (mbPtr->cargo != NULL) {
+ depCursor = mbPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = mbPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(TkMenuButton *mbPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (mbPtr->cargo == NULL) {
+ mbPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ mbPtr->cargo->next = NULL;
+ depCursor = mbPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = mbPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(mbPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
@@ -455,6 +809,7 @@ DestroyMenuButton(
}
Tk_FreeConfigOptions((char *) mbPtr, mbPtr->optionTable, mbPtr->tkwin);
mbPtr->tkwin = NULL;
+ DestroyCargo(mbPtr);
Tcl_EventuallyFree((ClientData) mbPtr, TCL_DYNAMIC);
}
diff -rup tk8.5.8_base/generic/tkMenubutton.h tk8.5.8/generic/tkMenubutton.h
--- tk8.5.8_base/generic/tkMenubutton.h 2007-12-13 10:24:16.000000000 -0500
+++ tk8.5.8/generic/tkMenubutton.h 2010-06-29 15:16:15.440579977 -0400
@@ -46,6 +46,17 @@ enum state {
};
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each widget managed by
* this file:
*/
@@ -183,6 +194,7 @@ typedef struct {
* scripts. Malloc'ed, but may be NULL. */
int flags; /* Various flags; see below for
* definitions. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} TkMenuButton;
/*
diff -rup tk8.5.8_base/generic/tkScale.c tk8.5.8/generic/tkScale.c
--- tk8.5.8_base/generic/tkScale.c 2007-12-13 10:24:16.000000000 -0500
+++ tk8.5.8/generic/tkScale.c 2010-06-29 15:16:15.445571365 -0400
@@ -143,12 +143,12 @@ static const Tk_OptionSpec optionSpecs[]
*/
static CONST char *commandNames[] = {
- "cget", "configure", "coords", "get", "identify", "set", NULL
+ "cget", "configure", "coords", "get", "identify", "set", "cargo", NULL
};
enum command {
COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_COORDS, COMMAND_GET,
- COMMAND_IDENTIFY, COMMAND_SET
+ COMMAND_IDENTIFY, COMMAND_SET, COMMAND_CARGO
};
/*
@@ -171,6 +171,12 @@ static int ScaleWidgetObjCmd(ClientData
Tcl_Obj *CONST objv[]);
static void ScaleWorldChanged(ClientData instanceData);
static void ScaleSetVariable(TkScale *scalePtr);
+static int AddCargo(TkScale *scalePtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(TkScale *scalePtr, char *name);
+static int DestroyCargo(TkScale *scalePtr);
+static Tcl_Obj * GetCargo(TkScale *scalePtr, char *entry);
+static Tcl_Obj * ListCargo(TkScale *scalePtr);
+static int SetCargo(TkScale *scalePtr, int objc, Tcl_Obj *const objv[]);
/*
* The structure below defines scale class behavior by means of procedures
@@ -290,6 +296,7 @@ Tk_ScaleObjCmd(
scalePtr->cursor = None;
scalePtr->takeFocusPtr = NULL;
scalePtr->flags = NEVER_SET;
+ scalePtr->cargo = NULL;
Tk_SetClassProcs(scalePtr->tkwin, &scaleClass, (ClientData) scalePtr);
Tk_CreateEventHandler(scalePtr->tkwin,
@@ -466,6 +473,49 @@ ScaleWidgetObjCmd(
}
break;
}
+ case COMMAND_CARGO:{
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(scalePtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(scalePtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(scalePtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(scalePtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(scalePtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(scalePtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
Tcl_Release((ClientData) scalePtr);
return result;
@@ -474,6 +524,310 @@ ScaleWidgetObjCmd(
Tcl_Release((ClientData) scalePtr);
return TCL_ERROR;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(TkScale *scalePtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = scalePtr->cargo;
+ if (scalePtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(scalePtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(TkScale *scalePtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (scalePtr->cargo != NULL) {
+ depCursor1 = depCursor2 = scalePtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ scalePtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ scalePtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(TkScale *scalePtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = scalePtr->cargo;
+ while (scalePtr->cargo != NULL) {
+ depCursor1 = depCursor2 = scalePtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != scalePtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(scalePtr->cargo);
+ scalePtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(TkScale *scalePtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = scalePtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(TkScale *scalePtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (scalePtr->cargo != NULL) {
+ depCursor = scalePtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = scalePtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(TkScale *scalePtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (scalePtr->cargo == NULL) {
+ scalePtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ scalePtr->cargo->next = NULL;
+ depCursor = scalePtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = scalePtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(scalePtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*----------------------------------------------------------------------
diff -rup tk8.5.8_base/generic/tkScale.h tk8.5.8/generic/tkScale.h
--- tk8.5.8_base/generic/tkScale.h 2005-11-26 21:36:14.000000000 -0500
+++ tk8.5.8/generic/tkScale.h 2010-06-29 15:16:15.447580268 -0400
@@ -42,6 +42,17 @@ enum state {
};
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each scale widget
* managed by this file:
*/
@@ -164,6 +175,7 @@ typedef struct TkScale {
* scripts. May be NULL. */
int flags; /* Various flags; see below for
* definitions. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} TkScale;
/*
diff -rup tk8.5.8_base/generic/tkScrollbar.c tk8.5.8/generic/tkScrollbar.c
--- tk8.5.8_base/generic/tkScrollbar.c 2008-10-05 07:34:46.000000000 -0400
+++ tk8.5.8/generic/tkScrollbar.c 2010-06-29 15:16:15.449577997 -0400
@@ -500,6 +500,7 @@ ScrollbarWidgetCmd(
Tcl_Release((ClientData) scrollPtr);
return TCL_ERROR;
}
+
/*
*----------------------------------------------------------------------
diff -rup tk8.5.8_base/generic/tkText.c tk8.5.8/generic/tkText.c
--- tk8.5.8_base/generic/tkText.c 2009-10-22 17:41:20.000000000 -0400
+++ tk8.5.8/generic/tkText.c 2010-06-29 15:16:15.460574026 -0400
@@ -399,6 +399,12 @@ static int TextSearchIndexInLine(CONST
static int TextPeerCmd(TkText *textPtr, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[]);
static TkUndoProc TextUndoRedoCallback;
+static int AddCargo(TkText *textPtr, int objc, Tcl_Obj *const objv[]);
+static int DeleteCargo(TkText *textPtr, char *name);
+static int DestroyCargo(TkText *textPtr);
+static Tcl_Obj * GetCargo(TkText *textPtr, char *entry);
+static Tcl_Obj * ListCargo(TkText *textPtr);
+static int SetCargo(TkText *textPtr, int objc, Tcl_Obj *const objv[]);
/*
* Declarations of the three search procs required by the multi-line search
@@ -607,6 +613,7 @@ CreateWidget(
textPtr->selBorderWidth = 0;
textPtr->selBorderWidthPtr = NULL;
textPtr->selFgColorPtr = NULL;
+ textPtr->cargo = NULL;
/*
* Note: it is important that textPtr->selTagPtr is NULL before this
@@ -690,14 +697,14 @@ TextWidgetObjCmd(
"bbox", "cget", "compare", "configure", "count", "debug", "delete",
"dlineinfo", "dump", "edit", "get", "image", "index", "insert",
"mark", "peer", "replace", "scan", "search", "see", "tag", "window",
- "xview", "yview", NULL
+ "xview", "yview", "cargo", NULL
};
enum options {
TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_COUNT,
TEXT_DEBUG, TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT,
TEXT_GET, TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK,
TEXT_PEER, TEXT_REPLACE, TEXT_SCAN, TEXT_SEARCH, TEXT_SEE,
- TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW
+ TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW, TEXT_CARGO
};
if (objc < 2) {
@@ -1496,6 +1503,49 @@ TextWidgetObjCmd(
case TEXT_YVIEW:
result = TkTextYviewCmd(textPtr, interp, objc, objv);
break;
+ case TEXT_CARGO: {
+ Tcl_Obj *objPtr;
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 3, objv, NULL);
+ result = TCL_ERROR;
+ break;
+ }
+
+ if (objc == 3) {
+ if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = ListCargo(textPtr);
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ result = DestroyCargo(textPtr);
+ break;
+ }
+ } else {
+ if (!strcmp(Tcl_GetString(objv[2]), "append")) {
+ result = AddCargo(textPtr, objc, objv);
+ } else if (!strcmp(Tcl_GetString(objv[2]), "get")) {
+ objPtr = GetCargo(textPtr, Tcl_GetString(objv[3]));
+ if (objPtr == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ result = TCL_OK;
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "set")) {
+ result = SetCargo(textPtr, objc, objv);
+ break;
+ } else if (!strcmp(Tcl_GetString(objv[2]), "unset")) {
+ DeleteCargo(textPtr, Tcl_GetString(objv[3]));
+ }
+ }
+ break;
+ }
}
done:
@@ -1505,6 +1555,310 @@ TextWidgetObjCmd(
}
return result;
}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddCargo --
+ * This function is called to add entries to the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * Entries are added to the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+*/
+
+static int
+AddCargo(TkText *textPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ depCursor = textPtr->cargo;
+ if (textPtr->cargo != NULL) {
+ while (depCursor->next != NULL) {
+ depCursor = depCursor->next;
+ }
+ do {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ SetCargo(textPtr, objc, objv);
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteCargo --
+ * This function is called to delete a single entry from the cargo dictionary
+ *
+ * Results:
+ * A Standard Tcl result
+ *
+ * Side effects:
+ * One entry is deleted from the cargo dictionary
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DeleteCargo(TkText *textPtr, char *entry)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ if (textPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = textPtr->cargo;
+ if (strcmp(entry, depCursor1->Entry) == 0) {
+ if (depCursor1->next == NULL) {
+ free(depCursor1);
+ textPtr->cargo = NULL;
+ } else {
+ depCursor1 = depCursor1->next;
+ free(depCursor2);
+ textPtr->cargo = depCursor1;
+ }
+ } else {
+ while ((depCursor2 != NULL) && (strcmp(entry, depCursor2->Entry) != 0)) {
+ depCursor2 = depCursor2->next;
+ }
+ while (depCursor1->next != depCursor2) {
+ depCursor1 = depCursor1->next;
+ }
+ if (depCursor2 != NULL) {
+ depCursor1->next = depCursor2->next;
+ free(depCursor2);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DestroyCargo --
+ * This function is called to destroy the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * The dictionary is deleted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+DestroyCargo(TkText *textPtr)
+{
+ dictionaryEntryPtr depCursor1, depCursor2;
+ depCursor1 = textPtr->cargo;
+ while (textPtr->cargo != NULL) {
+ depCursor1 = depCursor2 = textPtr->cargo;
+ while (depCursor1->next != NULL) {
+ depCursor1 = depCursor1->next;
+ }
+ while ((depCursor2->next != depCursor1) && (depCursor2 != depCursor1)) {
+ depCursor2 = depCursor2->next;
+ }
+ if (depCursor1 != textPtr->cargo) {
+ free(depCursor1);
+ depCursor2->next = NULL;
+ } else {
+ free(textPtr->cargo);
+ textPtr->cargo = NULL;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetCargo --
+ * This function is called to retrieve a single entry in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*GetCargo(TkText *textPtr, char *entry)
+{
+ int stringLen;
+ dictionaryEntryPtr depCursor;
+ depCursor = textPtr->cargo;
+ while ((depCursor != NULL) && (strcmp(depCursor->Entry, entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ if (depCursor->Value != NULL) {
+ stringLen = strlen(depCursor->Value);
+ return Tcl_NewStringObj(depCursor->Value, stringLen);
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+ } else {
+ return Tcl_NewStringObj("", 0);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ListCargo --
+ * This function is called to list all entries and values in the cargo dictionary
+ *
+ * Results:
+ * A string is returned.
+ *
+ * Side effects:
+ * none.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj
+*ListCargo(TkText *textPtr)
+{
+ char *returnString;
+ Tcl_Obj *returnObj;
+ int stringLen = 1;
+ dictionaryEntryPtr depCursor;
+ if (textPtr->cargo != NULL) {
+ depCursor = textPtr->cargo;
+ do {
+ stringLen += strlen(depCursor->Entry) + 3;
+ if (depCursor->Value != NULL) {
+ stringLen += strlen(depCursor->Value);
+ }
+ stringLen++;
+ if (depCursor->next != NULL) {
+ stringLen++;
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ returnString = (char*)malloc(stringLen + 1);
+ depCursor = textPtr->cargo;
+ strcpy(returnString, "\"");
+ do {
+ strcat(returnString, depCursor->Entry);
+ strcat(returnString, "\" \"");
+ if (depCursor->Value != NULL) {
+ strcat(returnString, depCursor->Value);
+ }
+ strcat(returnString, "\"");
+ if (depCursor->next != NULL) {
+ strcat(returnString, " \"");
+ }
+ depCursor = depCursor->next;
+ } while (depCursor != NULL);
+ stringLen = strlen(returnString);
+ returnObj = Tcl_NewStringObj(returnString, stringLen);
+ free(returnString);
+ } else {
+ returnObj = Tcl_NewStringObj("", 0);
+ }
+ return returnObj;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * SetCargo --
+ * This function is called to create the cargo dictionary
+ *
+ * Results:
+ * A standard Tcl result.
+ *
+ * Side effects:
+ * A dictionary is created with at least one entry.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+SetCargo(TkText *textPtr, int objc, Tcl_Obj *const objv[])
+{
+ int x = 3;
+ dictionaryEntryPtr depCursor;
+ Tcl_Obj *obja[5];
+
+ obja[0] = Tcl_DuplicateObj(objv[0]); /* Set the first 3 objects in obja to be the same as objv. */
+ obja[1] = Tcl_DuplicateObj(objv[1]); /* This is because we are going to use this to call CargoAdd */
+ obja[2] = Tcl_DuplicateObj(objv[2]); /* which ignores the first 3 arguments. */
+
+ if (textPtr->cargo == NULL) {
+ textPtr->cargo = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ textPtr->cargo->next = NULL;
+ depCursor = textPtr->cargo;
+ do {
+ depCursor->Entry = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Entry, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ if (x < (objc)) {
+ depCursor->next = (dictionaryEntryPtr)malloc(sizeof(dictionaryEntry));
+ depCursor = depCursor->next;
+ depCursor->next = NULL;
+ }
+ } else {
+ depCursor->Value = NULL;
+ depCursor->next = NULL;
+ }
+ } while (x < objc);
+ } else {
+ depCursor = textPtr->cargo;
+ do {
+ while((depCursor != NULL) && (strcmp(Tcl_GetString(objv[x]), depCursor->Entry))) {
+ depCursor = depCursor->next;
+ }
+ if (depCursor != NULL) {
+ x++;
+ free(depCursor->Value);
+ depCursor->Value = (char*)malloc(strlen(Tcl_GetString(objv[x])) + 1);
+ strcpy(depCursor->Value, Tcl_GetString(objv[x]));
+ x++;
+ } else {
+ obja[3] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ if (x < objc) {
+ obja[4] = Tcl_DuplicateObj(objv[x]);
+ x++;
+ }
+ AddCargo(textPtr, 5, obja);
+ }
+ } while (x < objc);
+ }
+
+ return TCL_OK;
+}
+
/*
*--------------------------------------------------------------
@@ -1967,6 +2321,7 @@ DestroyText(
}
textPtr->tkwin = NULL;
+ DestroyCargo(textPtr);
textPtr->refCount--;
Tcl_DeleteCommandFromToken(textPtr->interp, textPtr->widgetCmd);
if (textPtr->refCount == 0) {
diff -rup tk8.5.8_base/generic/tkText.h tk8.5.8/generic/tkText.h
--- tk8.5.8_base/generic/tkText.h 2009-10-22 17:41:20.000000000 -0400
+++ tk8.5.8/generic/tkText.h 2010-06-29 15:16:15.463578860 -0400
@@ -596,6 +596,17 @@ typedef struct TkSharedText {
} TkSharedText;
/*
+ * Dictionary structure
+ */
+typedef struct dictentry {
+ char *Entry;
+ char *Value;
+ struct dictentry *next;
+} dictionaryentry;
+
+typedef dictionaryentry dictionaryEntry, *dictionaryEntryPtr;
+
+/*
* A data structure of the following type is kept for each text widget that
* currently exists for this process:
*/
@@ -783,6 +794,7 @@ typedef struct TkText {
* statements. */
int autoSeparators; /* Non-zero means the separators will be
* inserted automatically. */
+ dictionaryEntryPtr cargo; /* Used to keep track of the first entry in the dictionary */
} TkText;
/*