Tk Source Code

Artifact [2b6b0799]
Login

Artifact 2b6b07990777501fb4c07c73afa74ab776fe81ca:

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;
 
 /*