summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkTreeElem.c120
1 files changed, 56 insertions, 64 deletions
diff --git a/generic/tkTreeElem.c b/generic/tkTreeElem.c
index 80b0cf5..5446f86 100644
--- a/generic/tkTreeElem.c
+++ b/generic/tkTreeElem.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 2002-2006 Tim Baker
*
- * RCS: @(#) $Id: tkTreeElem.c,v 1.55 2006/12/04 20:11:18 treectrl Exp $
+ * RCS: @(#) $Id: tkTreeElem.c,v 1.56 2006/12/05 01:42:40 treectrl Exp $
*/
#include "tkTreeCtrl.h"
@@ -2197,10 +2197,14 @@ typedef struct ElementText ElementText;
struct ElementText
{
Element header;
- Tcl_Obj *textObj; /* -text */
- char *text;
- int textLen;
- int stringRepInvalid;
+ char *textCfg; /* -text */
+ char *text; /* This will be the same as textCfg, or it
+ * will be a dynamically allocated string
+ * from any -data or -textvariable. */
+#define STRINGREP_INVALID -1
+ int textLen; /* Number of bytes (not characters) in the
+ * UTF-8 string. If -1, it means the string
+ * representation is invalid. */
struct PerStateGC *gc;
};
#define TEXTVAR
@@ -2330,8 +2334,7 @@ static Tk_OptionSpec textOptionSpecs[] = {
(char *) NULL, -1, Tk_Offset(Element, options),
TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_LAYOUT},
{TK_OPTION_STRING, "-text", (char *) NULL, (char *) NULL,
- (char *) NULL, Tk_Offset(ElementText, textObj),
- Tk_Offset(ElementText, text),
+ (char *) NULL, -1, Tk_Offset(ElementText, textCfg),
TK_OPTION_NULL_OK, (ClientData) NULL, TEXT_CONF_STRINGREP},
#ifdef TEXTVAR
{TK_OPTION_CUSTOM, "-textvariable", (char *) NULL, (char *) NULL,
@@ -2365,12 +2368,12 @@ static int WorldChangedProcText(ElementArgs *args)
int mask = 0;
if ((flagS | flagM) & TEXT_CONF_STRINGREP) {
- elemX->stringRepInvalid = TRUE;
+ elemX->textLen = STRINGREP_INVALID;
}
- if (elemX->stringRepInvalid ||
+ if ((elemX->textLen == STRINGREP_INVALID) ||
((flagS | flagM) & TEXT_CONF_LAYOUT) ||
- /* Not always needed */
+ /* Not needed if this element has its own font. */
(flagT & TREE_CONF_FONT)) {
mask |= CS_DISPLAY | CS_LAYOUT;
}
@@ -2387,7 +2390,8 @@ static void TextUpdateStringRep(ElementArgs *args)
Element *elem = args->elem;
ElementText *elemX = (ElementText *) elem;
ElementText *masterX = (ElementText *) elem->master;
- Tcl_Obj *dataObj, *formatObj, *textObj;
+ Tcl_Obj *dataObj, *formatObj;
+ char *text;
ElementTextData *etd, *etdM = NULL;
#ifdef TEXTVAR
ElementTextVar *etv;
@@ -2395,20 +2399,19 @@ static void TextUpdateStringRep(ElementArgs *args)
#endif
int dataType;
- if ((elemX->textObj == NULL) && (elemX->text != NULL)) {
+ /* Free any string allocated as a result of -data or -textvariable. */
+ if ((elemX->text != NULL) && (elemX->text != elemX->textCfg)) {
ckfree(elemX->text);
- elemX->text = NULL;
- elemX->textLen = 0;
}
- /* If -text is specified, -data, -datatype and -format are ignored */
- textObj = elemX->textObj;
- if ((textObj == NULL) && (masterX != NULL))
- textObj = masterX->textObj;
+ /* Forget any string, and mark the string rep as no-longer invalid. */
+ elemX->text = NULL;
+ elemX->textLen = 0;
- if (textObj != NULL) {
- if (elemX->textObj != NULL)
- (void) Tcl_GetStringFromObj(elemX->textObj, &elemX->textLen);
+ /* If -text is specified, then -data and -textvariable are ignored. */
+ if (elemX->textCfg != NULL) {
+ elemX->text = elemX->textCfg;
+ elemX->textLen = strlen(elemX->textCfg);
return;
}
@@ -2423,10 +2426,12 @@ static void TextUpdateStringRep(ElementArgs *args)
if (valueObj == NULL) {
/* not possible I think */
} else {
- char *string = Tcl_GetStringFromObj(valueObj, &elemX->textLen);
+ /* FIXME: do I need to allocate a copy, or can I just point
+ * to the internal rep of the string object? */
+ text = Tcl_GetStringFromObj(valueObj, &elemX->textLen);
if (elemX->textLen > 0) {
elemX->text = ckalloc(elemX->textLen);
- memcpy(elemX->text, string, elemX->textLen);
+ memcpy(elemX->text, text, elemX->textLen);
}
}
return;
@@ -2556,10 +2561,10 @@ static void TextUpdateStringRep(ElementArgs *args)
}
if (resultObj != NULL) {
- char *string = Tcl_GetStringFromObj(resultObj, &elemX->textLen);
+ text = Tcl_GetStringFromObj(resultObj, &elemX->textLen);
if (elemX->textLen > 0) {
elemX->text = ckalloc(elemX->textLen);
- memcpy(elemX->text, string, elemX->textLen);
+ memcpy(elemX->text, text, elemX->textLen);
}
}
}
@@ -2719,7 +2724,6 @@ static char *VarTraceProc_Text(ClientData clientData, Tcl_Interp *interp,
CONST char *name1, CONST char *name2, int flags)
{
ElementText *elemX = (ElementText *) clientData;
- ElementText *masterX = (ElementText *) elemX->header.master;
ElementTextVar *etv = DynamicOption_FindData(elemX->header.options, 1001);
Tcl_Obj *varNameObj = etv ? etv->varNameObj : NULL;
Tcl_Obj *valueObj;
@@ -2731,14 +2735,9 @@ static char *VarTraceProc_Text(ClientData clientData, Tcl_Interp *interp,
if (flags & TCL_TRACE_UNSETS) {
if ((flags & TCL_TRACE_DESTROYED) && !(flags & TCL_INTERP_DESTROYED)) {
- char *text = elemX->text;
- int textLen = elemX->textLen;
- if ((text == NULL) && (masterX != NULL)) {
- text = masterX->text;
- textLen = masterX->textLen;
- }
- if (text != NULL) {
- valueObj = Tcl_NewStringObj(text, textLen);
+ /* Use the current string if it is valid. */
+ if (elemX->textLen > 0) {
+ valueObj = Tcl_NewStringObj(elemX->text, elemX->textLen);
} else {
valueObj = Tcl_NewStringObj("", 0);
}
@@ -2751,7 +2750,7 @@ static char *VarTraceProc_Text(ClientData clientData, Tcl_Interp *interp,
return (char *) NULL;
}
- elemX->stringRepInvalid = TRUE;
+ elemX->textLen = STRINGREP_INVALID;
Tree_ElementChangedItself(etv->tree, etv->item, etv->column,
(Element *) elemX, TEXT_CONF_TEXTVAR, CS_LAYOUT | CS_DISPLAY);
return (char *) NULL;
@@ -2767,7 +2766,7 @@ static void DeleteProcText(ElementArgs *args)
if (elemX->gc != NULL)
PerStateGC_Free(tree, &elemX->gc);
- if ((elemX->textObj == NULL) && (elemX->text != NULL)) {
+ if ((elemX->textCfg == NULL) && (elemX->text != NULL)) {
ckfree(elemX->text);
elemX->text = NULL;
}
@@ -2789,6 +2788,7 @@ static int ConfigProcText(ElementArgs *args)
Tk_SavedOptions savedOptions;
int error;
Tcl_Obj *errorResult = NULL;
+ char *textCfg = elemX->textCfg;
#ifdef TEXTVAR
ElementTextVar *etv;
Tcl_Obj *varNameObj;
@@ -2822,19 +2822,7 @@ static int ConfigProcText(ElementArgs *args)
valueObj = Tcl_ObjGetVar2(interp, varNameObj,
NULL, TCL_GLOBAL_ONLY);
if (valueObj == NULL) {
- ElementText *masterX = (ElementText *) elem->master;
- char *text = elemX->text;
- int textLen = elemX->textLen;
- if ((text == NULL) && (masterX != NULL)) {
- text = masterX->text;
- textLen = masterX->textLen;
- }
- /* This may not be the current string rep */
- if (text != NULL) {
- valueObj = Tcl_NewStringObj(text, textLen);
- } else {
- valueObj = Tcl_NewStringObj("", 0);
- }
+ valueObj = Tcl_NewStringObj("", 0);
Tcl_IncrRefCount(valueObj);
/* This validates the variable name. We get an error
* if it is the name of an array */
@@ -2858,6 +2846,11 @@ static int ConfigProcText(ElementArgs *args)
}
}
+ /* If -text was specified, then do not try to free the old value in
+ * TextUpdateStringRep. */
+ if (textCfg != elemX->textCfg && elemX->text == textCfg)
+ elemX->text = NULL;
+
#ifdef TEXTVAR
TextTraceSet(interp, elemX);
#endif
@@ -3136,18 +3129,17 @@ static void NeededProcText(ElementArgs *args)
if (masterX != NULL)
etlM = DynamicOption_FindData(args->elem->master->options, 1005);
- if ((masterX != NULL) && masterX->stringRepInvalid) {
+ if ((masterX != NULL) && (masterX->textLen == STRINGREP_INVALID)) {
args->elem = (Element *) masterX;
TextUpdateStringRep(args);
args->elem = elem;
- masterX->stringRepInvalid = FALSE;
}
- if (elemX->stringRepInvalid) {
+ if (elemX->textLen == STRINGREP_INVALID) {
TextUpdateStringRep(args);
- elemX->stringRepInvalid = FALSE;
}
- etl2 = TextUpdateLayout("NeededProcText", args, args->needed.fixedWidth, args->needed.maxWidth);
+ etl2 = TextUpdateLayout("NeededProcText", args, args->needed.fixedWidth,
+ args->needed.maxWidth);
if (etl2 != NULL) {
etl2->layoutWidth = -1;
etl2->neededWidth = -1;
@@ -3246,7 +3238,6 @@ int Element_GetSortData(TreeCtrl *tree, Element *elem, int type, long *lv, doubl
ElementTextData *etd, *etdM = NULL;
Tcl_Obj *dataObj = NULL;
int dataType = TDT_NULL;
- Tcl_Obj *obj;
etd = DynamicOption_FindData(elem->options, 1006);
if (etd != NULL) {
@@ -3269,14 +3260,15 @@ int Element_GetSortData(TreeCtrl *tree, Element *elem, int type, long *lv, doubl
(*sv) = elemX->text;
break;
case SORT_DOUBLE:
- if (dataObj != NULL && dataType == TDT_DOUBLE)
- obj = dataObj;
- else
- obj = elemX->textObj;
- if (obj == NULL)
- return TCL_ERROR;
- if (Tcl_GetDoubleFromObj(tree->interp, obj, dv) != TCL_OK)
+ if (dataObj != NULL && dataType == TDT_DOUBLE) {
+ if (Tcl_GetDoubleFromObj(tree->interp, dataObj, dv) != TCL_OK)
+ return TCL_ERROR;
+ } else if (elemX->textCfg != NULL) {
+ if (Tcl_GetDouble(tree->interp, elemX->textCfg, dv) != TCL_OK)
+ return TCL_ERROR;
+ } else {
return TCL_ERROR;
+ }
break;
case SORT_LONG:
if (dataObj != NULL && dataType != TDT_NULL) {
@@ -3293,8 +3285,8 @@ int Element_GetSortData(TreeCtrl *tree, Element *elem, int type, long *lv, doubl
break;
}
}
- if (elemX->textObj != NULL)
- if (Tcl_GetLongFromObj(tree->interp, elemX->textObj, lv) != TCL_OK)
+ if (elemX->textCfg != NULL)
+ if (TclGetLong(tree->interp, elemX->textCfg, lv) != TCL_OK)
return TCL_ERROR;
break;
}