Index: generic/tkCanvas.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkCanvas.c,v
retrieving revision 1.20
diff -r1.20 tkCanvas.c
294c294
< static CONST char**	GetStringsFromObjs _ANSI_ARGS_((int argc,
---
> CONST char**	        GetStringsFromObjs _ANSI_ARGS_((int argc,
5489c5489
< static CONST char **
---
> CONST char **
Index: generic/tkInt.h
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkInt.h,v
retrieving revision 1.54
diff -r1.54 tkInt.h
1066,1067c1066,1068
< EXTERN int		Tk_TextCmd _ANSI_ARGS_((ClientData clientData,
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> EXTERN int		Tk_TextObjCmd _ANSI_ARGS_((ClientData clientData,
> 			    Tcl_Interp *interp, int objc,
> 			    Tcl_Obj *CONST objv[]));
Index: generic/tkTest.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTest.c,v
retrieving revision 1.21
diff -r1.21 tkTest.c
2328c2328,2332
<     textPtr = (TkText *) info.clientData;
---
>     if (info.isNativeObjectProc) {
> 	textPtr = (TkText *) info.objClientData;
>     } else {
>         textPtr = (TkText *) info.clientData;
>     }
Index: generic/tkText.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkText.c,v
retrieving revision 1.32
diff -r1.32 tkText.c
33c33,35
<  * Custom options for handling "-state"
---
>  * The 'TkTextState' enum in tkText.h is used to define a type for the
>  * -state option of the Text widget.  These values are used as indices
>  * into the string table below.
36,38c38,39
< static Tk_CustomOption stateOption = {
<     (Tk_OptionParseProc *) TkStateParseProc,
<     TkStatePrintProc, (ClientData) NULL /* only "normal" and "disabled" */
---
> static char *stateStrings[] = {
>     "disabled", "normal", (char *) NULL
42c43,45
<  * Information used to parse text configuration options:
---
>  * The 'TkWrapMode' enum in tkText.h is used to define a type for the
>  * -wrap option of the Text widget.  These values are used as indices
>  * into the string table below.
45,151c48,49
< static Tk_ConfigSpec configSpecs[] = {
<     {TK_CONFIG_BOOLEAN, "-autoseparators", "autoSeparators",
<         "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS,
<         Tk_Offset(TkText, autoSeparators), 0},
<     {TK_CONFIG_BORDER, "-background", "background", "Background",
< 	DEF_TEXT_BG_COLOR, Tk_Offset(TkText, border), TK_CONFIG_COLOR_ONLY},
<     {TK_CONFIG_BORDER, "-background", "background", "Background",
< 	DEF_TEXT_BG_MONO, Tk_Offset(TkText, border), TK_CONFIG_MONO_ONLY},
<     {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
< 	(char *) NULL, 0, 0},
<     {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
< 	(char *) NULL, 0, 0},
<     {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
< 	DEF_TEXT_BORDER_WIDTH, Tk_Offset(TkText, borderWidth), 0},
<     {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
< 	DEF_TEXT_CURSOR, Tk_Offset(TkText, cursor), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection",
< 	"ExportSelection", DEF_TEXT_EXPORT_SELECTION,
< 	Tk_Offset(TkText, exportSelection), 0},
<     {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
< 	(char *) NULL, 0, 0},
<     {TK_CONFIG_FONT, "-font", "font", "Font",
< 	DEF_TEXT_FONT, Tk_Offset(TkText, tkfont), 0},
<     {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
< 	DEF_TEXT_FG, Tk_Offset(TkText, fgColor), 0},
<     {TK_CONFIG_PIXELS, "-height", "height", "Height",
< 	DEF_TEXT_HEIGHT, Tk_Offset(TkText, height), 0},
<     {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
< 	"HighlightBackground", DEF_TEXT_HIGHLIGHT_BG,
< 	Tk_Offset(TkText, highlightBgColorPtr), 0},
<     {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
< 	DEF_TEXT_HIGHLIGHT, Tk_Offset(TkText, highlightColorPtr), 0},
<     {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
< 	"HighlightThickness",
< 	DEF_TEXT_HIGHLIGHT_WIDTH, Tk_Offset(TkText, highlightWidth), 0},
<     {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground",
< 	DEF_TEXT_INSERT_BG, Tk_Offset(TkText, insertBorder), 0},
<     {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
< 	DEF_TEXT_INSERT_BD_COLOR, Tk_Offset(TkText, insertBorderWidth),
< 	TK_CONFIG_COLOR_ONLY},
<     {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth",
< 	DEF_TEXT_INSERT_BD_MONO, Tk_Offset(TkText, insertBorderWidth),
< 	TK_CONFIG_MONO_ONLY},
<     {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime",
< 	DEF_TEXT_INSERT_OFF_TIME, Tk_Offset(TkText, insertOffTime), 0},
<     {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime",
< 	DEF_TEXT_INSERT_ON_TIME, Tk_Offset(TkText, insertOnTime), 0},
<     {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
< 	DEF_TEXT_INSERT_WIDTH, Tk_Offset(TkText, insertWidth), 0},
<     {TK_CONFIG_INT, "-maxundo", "maxUndo", "MaxUndo",
< 	DEF_TEXT_MAX_UNDO, Tk_Offset(TkText, maxUndo), 0},
<     {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
< 	DEF_TEXT_PADX, Tk_Offset(TkText, padX), 0},
<     {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
< 	DEF_TEXT_PADY, Tk_Offset(TkText, padY), 0},
<     {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
< 	DEF_TEXT_RELIEF, Tk_Offset(TkText, relief), 0},
<     {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
< 	DEF_TEXT_SELECT_COLOR, Tk_Offset(TkText, selBorder),
< 	TK_CONFIG_COLOR_ONLY},
<     {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
< 	DEF_TEXT_SELECT_MONO, Tk_Offset(TkText, selBorder),
< 	TK_CONFIG_MONO_ONLY},
<     {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
< 	DEF_TEXT_SELECT_BD_COLOR, Tk_Offset(TkText, selBdString),
< 	TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth",
< 	DEF_TEXT_SELECT_BD_MONO, Tk_Offset(TkText, selBdString),
< 	TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
< 	DEF_TEXT_SELECT_FG_COLOR, Tk_Offset(TkText, selFgColorPtr),
< 	TK_CONFIG_COLOR_ONLY},
<     {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
< 	DEF_TEXT_SELECT_FG_MONO, Tk_Offset(TkText, selFgColorPtr),
< 	TK_CONFIG_MONO_ONLY},
<     {TK_CONFIG_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
< 	DEF_TEXT_SET_GRID, Tk_Offset(TkText, setGrid), 0},
<     {TK_CONFIG_PIXELS, "-spacing1", "spacing1", "Spacing",
< 	DEF_TEXT_SPACING1, Tk_Offset(TkText, spacing1),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_PIXELS, "-spacing2", "spacing2", "Spacing",
< 	DEF_TEXT_SPACING2, Tk_Offset(TkText, spacing2),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_PIXELS, "-spacing3", "spacing3", "Spacing",
< 	DEF_TEXT_SPACING3, Tk_Offset(TkText, spacing3),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_CUSTOM, "-state", "state", "State",
< 	DEF_TEXT_STATE, Tk_Offset(TkText, state), 0, &stateOption},
<     {TK_CONFIG_STRING, "-tabs", "tabs", "Tabs",
< 	DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
< 	DEF_TEXT_TAKE_FOCUS, Tk_Offset(TkText, takeFocus),
< 	TK_CONFIG_NULL_OK},
<     {TK_CONFIG_BOOLEAN, "-undo", "undo", "Undo",
<         DEF_TEXT_UNDO, Tk_Offset(TkText, undo), 0},
<     {TK_CONFIG_INT, "-width", "width", "Width",
< 	DEF_TEXT_WIDTH, Tk_Offset(TkText, width), 0},
<     {TK_CONFIG_CUSTOM, "-wrap", "wrap", "Wrap",
< 	DEF_TEXT_WRAP, Tk_Offset(TkText, wrapMode), 0, &textWrapModeOption},
<     {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
< 	DEF_TEXT_XSCROLL_COMMAND, Tk_Offset(TkText, xScrollCmd),
< 	TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
< 	DEF_TEXT_YSCROLL_COMMAND, Tk_Offset(TkText, yScrollCmd),
< 	TK_CONFIG_NULL_OK},
<     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
< 	(char *) NULL, 0, 0}
---
> static char *wrapStrings[] = {
>     "char", "none", "word", (char *) NULL
155,162c53
<  * Boolean variable indicating whether or not special debugging code
<  * should be executed.
<  */
< 
< int tkTextDebug = 0;
< 
< /*
<  * Custom options for handling "-wrap":
---
>  * Information used to parse text configuration options:
165,175c56,164
< static int		WrapModeParseProc _ANSI_ARGS_((ClientData clientData,
< 			    Tcl_Interp *interp, Tk_Window tkwin,
< 			    CONST char *value, char *widgRec, int offset));
< static char *		WrapModePrintProc _ANSI_ARGS_((ClientData clientData,
< 			    Tk_Window tkwin, char *widgRec, int offset,
< 			    Tcl_FreeProc **freeProcPtr));
< 
< Tk_CustomOption textWrapModeOption = {
<     WrapModeParseProc,
<     WrapModePrintProc,
<     (ClientData) NULL
---
> static Tk_OptionSpec optionSpecs[] = {
>     {TK_OPTION_BOOLEAN, "-autoseparators", "autoSeparators",
>         "AutoSeparators", DEF_TEXT_AUTO_SEPARATORS, -1,
>         Tk_Offset(TkText, autoSeparators), 0, 0, 0},
>     {TK_OPTION_BORDER, "-background", "background", "Background",
> 	DEF_TEXT_BG_COLOR, -1, Tk_Offset(TkText, border),
> 	0, (ClientData) DEF_TEXT_BG_MONO, 0},
>     {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
> 	(char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
>     {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
> 	(char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
>     {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
> 	DEF_TEXT_BORDER_WIDTH, -1, Tk_Offset(TkText, borderWidth), 
> 	0, 0, 0},
>     {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
> 	DEF_TEXT_CURSOR, -1, Tk_Offset(TkText, cursor),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
> 	"ExportSelection", DEF_TEXT_EXPORT_SELECTION, -1, 
> 	Tk_Offset(TkText, exportSelection), 0, 0, 0},
>     {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
> 	(char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
>     {TK_OPTION_FONT, "-font", "font", "Font",
> 	DEF_TEXT_FONT, -1, Tk_Offset(TkText, tkfont), 0, 0, 0},
>     {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
> 	DEF_TEXT_FG, -1, Tk_Offset(TkText, fgColor), 0, 
> 	0, 0},
>     {TK_OPTION_PIXELS, "-height", "height", "Height",
> 	DEF_TEXT_HEIGHT, -1, Tk_Offset(TkText, height), 0, 0, 0},
>     {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
> 	"HighlightBackground", DEF_TEXT_HIGHLIGHT_BG,
> 	-1, Tk_Offset(TkText, highlightBgColorPtr), 
> 	0, 0, 0},
>     {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
> 	DEF_TEXT_HIGHLIGHT, -1, Tk_Offset(TkText, highlightColorPtr),
> 	0, 0, 0},
>     {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
> 	"HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, -1, 
> 	Tk_Offset(TkText, highlightWidth), 0, 0, 0},
>     {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
> 	DEF_TEXT_INSERT_BG,
> 	-1, Tk_Offset(TkText, insertBorder), 
> 	0, 0, 0},
>     {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth", 
> 	"BorderWidth", DEF_TEXT_INSERT_BD_COLOR, -1, 
> 	Tk_Offset(TkText, insertBorderWidth), 0, 
> 	(ClientData) DEF_TEXT_INSERT_BD_MONO, 0},
>     {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
> 	DEF_TEXT_INSERT_OFF_TIME, -1, Tk_Offset(TkText, insertOffTime), 
> 	0, 0, 0},
>     {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
> 	DEF_TEXT_INSERT_ON_TIME, -1, Tk_Offset(TkText, insertOnTime), 
> 	0, 0, 0},
>     {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
> 	DEF_TEXT_INSERT_WIDTH, -1, Tk_Offset(TkText, insertWidth), 
> 	0, 0, 0},
>     {TK_OPTION_INT, "-maxundo", "maxUndo", "MaxUndo",
> 	DEF_TEXT_MAX_UNDO, -1, Tk_Offset(TkText, maxUndo), 0, 0, 0},
>     {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
> 	DEF_TEXT_PADX, -1, Tk_Offset(TkText, padX), 0, 0, 0},
>     {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
> 	DEF_TEXT_PADY, -1, Tk_Offset(TkText, padY), 0, 0, 0},
>     {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
> 	DEF_TEXT_RELIEF, -1, Tk_Offset(TkText, relief), 0, 0, 0},
>     {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
>         DEF_TEXT_SELECT_COLOR, -1, Tk_Offset(TkText, selBorder),
> 	0, (ClientData) DEF_TEXT_SELECT_MONO, 0},
>     {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth", 
> 	"BorderWidth", DEF_TEXT_SELECT_BD_COLOR, 
> 	Tk_Offset(TkText, selBorderWidthPtr), 
> 	Tk_Offset(TkText, selBorderWidth), 
> 	TK_OPTION_NULL_OK, (ClientData) DEF_TEXT_SELECT_BD_MONO, 0},
>     {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
> 	DEF_TEXT_SELECT_FG_COLOR, -1, Tk_Offset(TkText, selFgColorPtr),
> 	0, (ClientData) DEF_TEXT_SELECT_FG_MONO, 0},
>     {TK_OPTION_BOOLEAN, "-setgrid", "setGrid", "SetGrid",
> 	DEF_TEXT_SET_GRID, -1, Tk_Offset(TkText, setGrid), 0, 0, 0},
>     {TK_OPTION_PIXELS, "-spacing1", "spacing1", "Spacing",
> 	DEF_TEXT_SPACING1, -1, Tk_Offset(TkText, spacing1),
> 	TK_OPTION_DONT_SET_DEFAULT, 0 , 0 },
>     {TK_OPTION_PIXELS, "-spacing2", "spacing2", "Spacing",
> 	DEF_TEXT_SPACING2, -1, Tk_Offset(TkText, spacing2),
> 	TK_OPTION_DONT_SET_DEFAULT, 0 , 0 },
>     {TK_OPTION_PIXELS, "-spacing3", "spacing3", "Spacing",
> 	DEF_TEXT_SPACING3, -1, Tk_Offset(TkText, spacing3),
> 	TK_OPTION_DONT_SET_DEFAULT, 0 , 0 },
>     {TK_OPTION_STRING_TABLE, "-state", "state", "State",
>         DEF_TEXT_STATE, -1, Tk_Offset(TkText, state), 
> 	0, (ClientData) stateStrings, 0},
>     {TK_OPTION_STRING, "-tabs", "tabs", "Tabs",
> 	DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionPtr), -1,
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
> 	DEF_TEXT_TAKE_FOCUS, -1, Tk_Offset(TkText, takeFocus), 
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_BOOLEAN, "-undo", "undo", "Undo",
>         DEF_TEXT_UNDO, -1, Tk_Offset(TkText, undo), 0, 0 , 0},
>     {TK_OPTION_INT, "-width", "width", "Width",
>         DEF_TEXT_WIDTH, -1, Tk_Offset(TkText, width), 0, 0, 0},
>     {TK_OPTION_STRING_TABLE, "-wrap", "wrap", "Wrap",
>         DEF_TEXT_WRAP, -1, Tk_Offset(TkText, wrapMode), 
> 	0, (ClientData) wrapStrings, 0},
>     {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
>         DEF_TEXT_XSCROLL_COMMAND, -1, Tk_Offset(TkText, xScrollCmd),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
>         DEF_TEXT_YSCROLL_COMMAND, -1, Tk_Offset(TkText, yScrollCmd),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_END}
179,236c168,196
<  *--------------------------------------------------------------
<  *
<  * WrapModeParseProc --
<  *
<  *	This procedure is invoked during option processing to handle
<  *	"-wrap" options for text widgets.
<  *
<  * Results:
<  *	A standard Tcl return value.
<  *
<  * Side effects:
<  *	The wrap mode for a given item gets replaced by the wrap mode
<  *	indicated in the value argument.
<  *
<  *--------------------------------------------------------------
<  */
< 
< static int
< WrapModeParseProc(clientData, interp, tkwin, value, widgRec, offset)
<     ClientData clientData;		/* some flags.*/
<     Tcl_Interp *interp;			/* Used for reporting errors. */
<     Tk_Window tkwin;			/* Window containing canvas widget. */
<     CONST char *value;			/* Value of option (list of tag
< 					 * names). */
<     char *widgRec;			/* Pointer to record for item. */
<     int offset;				/* Offset into item. */
< {
<     int c;
<     size_t length;
< 
<     register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset);
< 
<     if(value == NULL || *value == 0) {
< 	*wrapPtr = TEXT_WRAPMODE_NULL;
< 	return TCL_OK;
<     }
< 
<     c = value[0];
<     length = strlen(value);
< 
<     if ((c == 'c') && (strncmp(value, "char", length) == 0)) {
< 	*wrapPtr = TEXT_WRAPMODE_CHAR;
< 	return TCL_OK;
<     }
<     if ((c == 'n') && (strncmp(value, "none", length) == 0)) {
< 	*wrapPtr = TEXT_WRAPMODE_NONE;
< 	return TCL_OK;
<     }
<     if ((c == 'w') && (strncmp(value, "word", length) == 0)) {
< 	*wrapPtr = TEXT_WRAPMODE_WORD;
< 	return TCL_OK;
<     }
<     Tcl_AppendResult(interp, "bad wrap mode \"", value,
< 	    "\": must be char, none, or word",
< 	    (char *) NULL);
<     *wrapPtr = TEXT_WRAPMODE_CHAR;
<     return TCL_ERROR;
< }
---
>  * The structure below holds information about a line-based search
>  * in the text widget.  It is private to this file, at present.
>  * However, the first 12 fields in it are very generic and so this
>  * basic structure could be used for a more general line-based
>  * searching mechanism.
>  */
> 
> typedef struct TkLineSearchSpec {
>     int exact;                       /* Whether search is exact or regexp */
>     int noCase;                      /* Case-insenstivive? */
>     int all;                         /* Whether all or the first match should 
>                                       * be reported */
>     int startLine;                   /* First line to examine */
>     int startOffset;                 /* Index in first line to start at */
>     int stopLine;                    /* Last line to examine, or -1 when we
>                                       * search all available text */
>     int stopOffset;                  /* Index to stop at, provided stopLine
>                                       * is not -1 */
>     int numLines;                    /* Total lines which are available */
>     int backwards;                   /* Searching forwards or backwards */
>     Tcl_Obj *varPtr;                 /* If non-NULL, store length(s) of 
>                                       * match(es) in this variable */
>     Tcl_Obj *countPtr;               /* Keeps track of currently found 
>                                       * lengths */
>     Tcl_Obj *resPtr;                 /* Keeps track of currently found 
>                                       * locations */
>     TkText *textPtr;	             /* Information about text widget. */
>     int searchElide;                 /* Search in hidden text as well */
> } TkLineSearchSpec;
239,257c199,200
<  *--------------------------------------------------------------
<  *
<  * WrapModePrintProc --
<  *
<  *	This procedure is invoked by the Tk configuration code
<  *	to produce a printable string for the "-wrap" configuration
<  *	option for canvas items.
<  *
<  * Results:
<  *	The return value is a string describing the state for
<  *	the item referred to by "widgRec".  In addition, *freeProcPtr
<  *	is filled in with the address of a procedure to call to free
<  *	the result string when it's no longer needed (or NULL to
<  *	indicate that the string doesn't need to be freed).
<  *
<  * Side effects:
<  *	None.
<  *
<  *--------------------------------------------------------------
---
>  * Boolean variable indicating whether or not special debugging code
>  * should be executed.
260,281c203
< static char *
< WrapModePrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
<     ClientData clientData;		/* Ignored. */
<     Tk_Window tkwin;			/* Window containing canvas widget. */
<     char *widgRec;			/* Pointer to record for item. */
<     int offset;				/* Ignored. */
<     Tcl_FreeProc **freeProcPtr;		/* Pointer to variable to fill in with
< 					 * information about how to reclaim
< 					 * storage for return string. */
< {
<     register TkWrapMode *wrapPtr = (TkWrapMode *) (widgRec + offset);
< 
<     if (*wrapPtr==TEXT_WRAPMODE_CHAR) {
< 	return "char";
<     } else if (*wrapPtr==TEXT_WRAPMODE_NONE) {
< 	return "none";
<     } else if (*wrapPtr==TEXT_WRAPMODE_WORD) {
< 	return "word";
<     } else {
< 	return "";
<     }
< }
---
> int tkTextDebug = 0;
288,289c210
< 			    TkText *textPtr, int argc, CONST char **argv,
< 			    int flags));
---
> 			    TkText *textPtr, int objc, Tcl_Obj *CONST objv[]));
291,292c212,214
< 			    CONST char *index1String, CONST char *index2String,
< 			    TkTextIndex *indexPtr1, TkTextIndex *indexPtr2));
---
> 			    Tcl_Obj *index1Obj, Tcl_Obj *index2Obj,
> 			    CONST TkTextIndex *indexPtr1, 
> 			    CONST TkTextIndex *indexPtr2));
294,295c216,217
< static void		InsertChars _ANSI_ARGS_((TkText *textPtr,
< 			    TkTextIndex *indexPtr, CONST char *string));
---
> static int		InsertChars _ANSI_ARGS_((TkText *textPtr,
> 			    CONST TkTextIndex *indexPtr, Tcl_Obj *stringPtr));
306c228,229
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, 
> 			    int objc, Tcl_Obj *CONST objv[]));
308,310c231,235
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
< static int		TextWidgetCmd _ANSI_ARGS_((ClientData clientData,
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, 
> 			    int objc, Tcl_Obj *CONST objv[]));
> static int		TextWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
> 			    Tcl_Interp *interp, 
> 			    int objc, Tcl_Obj *CONST objv[]));
314c239,240
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, 
> 			    int objc, Tcl_Obj *CONST objv[]));
321c247
< 			    TkTextIndex *index, int what));
---
> 			    CONST TkTextIndex *index, int what));
324,326c250,274
< static void		TextGetText _ANSI_ARGS_((TkTextIndex * index1,
< 			    TkTextIndex * index2, Tcl_DString *dsPtr));
< static void		updateDirtyFlag _ANSI_ARGS_((TkText *textPtr));
---
> static Tcl_Obj*		TextGetText _ANSI_ARGS_((CONST TkTextIndex * index1,
> 			    CONST TkTextIndex * index2));
> static void		UpdateDirtyFlag _ANSI_ARGS_((TkText *textPtr));
> static void             TextPushUndoAction _ANSI_ARGS_((TkText *textPtr, 
> 			    Tcl_Obj *undoString, int insert, 
> 			    CONST TkTextIndex *index1Ptr,
> 			    CONST TkTextIndex *index2Ptr));
> static int              SearchFoundMatch _ANSI_ARGS_((int lineNum, 
> 			    TkLineSearchSpec *searchSpecPtr, 
> 			    ClientData clientData, Tcl_Obj *theLine, 
> 			    int matchOffset, int matchLength));
> static ClientData       SearchAddNextLine _ANSI_ARGS_((int lineNum,
> 			    TkLineSearchSpec *searchSpecPtr, 
> 		            Tcl_Obj *theLine, int *lenPtr));
> static int              SearchIndexInLine _ANSI_ARGS_((
> 			    CONST TkLineSearchSpec *searchSpecPtr, 
> 			    TkTextLine *linePtr, int byteIndex));
> static int              SearchGetLineIndex _ANSI_ARGS_((Tcl_Interp *interp,
> 			    Tcl_Obj *objPtr, TkLineSearchSpec *searchSpecPtr,
> 			    int forwardWrap, int *linePosPtr, int *offsetPosPtr));
> static int              PerformSearch _ANSI_ARGS_((Tcl_Interp *interp,
> 			    TkLineSearchSpec *searchSpecPtr, Tcl_Obj *patObj));
>     
> 
> 
342c290
<  * Tk_TextCmd --
---
>  * Tk_TextObjCmd --
357c305
< Tk_TextCmd(clientData, interp, argc, argv)
---
> Tk_TextObjCmd(clientData, interp, objc, objv)
361,362c309,310
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings. */
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. */
365a314
>     Tk_OptionTable optionTable;
369,371c318,319
<     if (argc < 2) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " pathName ?options?\"", (char *) NULL);
---
>     if (objc < 2) {
> 	Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
379c327,328
<     new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL);
---
>     new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), 
> 				  (char *) NULL);
395,396c344,345
<     textPtr->widgetCmd = Tcl_CreateCommand(interp,
< 	    Tk_PathName(textPtr->tkwin), TextWidgetCmd,
---
>     textPtr->widgetCmd = Tcl_CreateObjCommand(interp,
> 	    Tk_PathName(textPtr->tkwin), TextWidgetObjCmd,
403c352
<     textPtr->state = TK_STATE_NORMAL;
---
>     textPtr->state = TK_TEXT_STATE_NORMAL;
420c369,372
< 
---
>     textPtr->tabOptionPtr = NULL;
>     textPtr->stateEpoch = 0;
>     textPtr->refCount = 1;
>     
424a377,380
>     textPtr->selBorder = NULL;
>     textPtr->selBorderWidth = 0;
>     textPtr->selBorderWidthPtr = NULL;
>     textPtr->selFgColorPtr = NULL;
432a389,395
>     /*
>      * Create the option table for this widget class.  If it has already
>      * been created, the cached pointer will be returned.
>      */
> 
>     optionTable = Tk_CreateOptionTable(interp, optionSpecs);
> 
434a398,399
>     textPtr->optionTable	= optionTable;
> 
444c409,415
<     if (ConfigureText(interp, textPtr, argc-2, argv+2, 0) != TCL_OK) {
---
>     
>     if (Tk_InitOptions(interp, (char *) textPtr, optionTable, textPtr->tkwin)
> 	    != TCL_OK) {
> 	Tk_DestroyWindow(textPtr->tkwin);
> 	return TCL_ERROR;
>     }
>     if (ConfigureText(interp, textPtr, objc-2, objv+2) != TCL_OK) {
448d418
<     Tcl_SetResult(interp, Tk_PathName(textPtr->tkwin), TCL_STATIC);
449a420,421
>     Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_PathName(textPtr->tkwin),
> 	    -1);
456c428
<  * TextWidgetCmd --
---
>  * TextWidgetObjCmd --
472c444
< TextWidgetCmd(clientData, interp, argc, argv)
---
> TextWidgetObjCmd(clientData, interp, objc, objv)
475,476c447,448
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings. */
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. */
479,481c451,470
<     int c, result = TCL_OK;
<     size_t length;
<     TkTextIndex index1, index2;
---
>     int result = TCL_OK;
>     int index;
>     
>     static CONST char *optionStrings[] = {
> 	"bbox", "cget", "compare", "configure", "debug", "delete", 
> 	"dlineinfo", "dump", "edit", "get", "image", "index", 
> 	"insert", "mark", "scan", "search", "see", "tag", 
> 	"window", "xview", "yview", (char *) NULL 
>     };
>     enum options {
> 	TEXT_BBOX, TEXT_CGET, TEXT_COMPARE, TEXT_CONFIGURE, TEXT_DEBUG,
> 	TEXT_DELETE, TEXT_DLINEINFO, TEXT_DUMP, TEXT_EDIT, TEXT_GET,
> 	TEXT_IMAGE, TEXT_INDEX, TEXT_INSERT, TEXT_MARK, TEXT_SCAN,
> 	TEXT_SEARCH, TEXT_SEE, TEXT_TAG, TEXT_WINDOW, TEXT_XVIEW, TEXT_YVIEW
>     };
>     
>     if (objc < 2) {
> 	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
> 	return TCL_ERROR;
>     }
483,485c472,473
<     if (argc < 2) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " option ?arg arg ...?\"", (char *) NULL);
---
>     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
> 	    &index) != TCL_OK) {
489,505c477,481
<     c = argv[1][0];
<     length = strlen(argv[1]);
<     if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) {
< 	int x, y, width, height;
< 
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " bbox index\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) {
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextCharBbox(textPtr, &index1, &x, &y, &width, &height) == 0) {
< 	    char buf[TCL_INTEGER_SPACE * 4];
---
> 
>     switch ((enum options) index) {
> 	case TEXT_BBOX: {
> 	    int x, y, width, height;
> 	    CONST TkTextIndex *indexPtr;
507,508c483,500
< 	    sprintf(buf, "%d %d %d %d", x, y, width, height);
< 	    Tcl_SetResult(interp, buf, TCL_VOLATILE);
---
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
> 	    if (indexPtr == NULL) {
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    if (TkTextCharBbox(textPtr, indexPtr, &x, &y, 
> 			       &width, &height) == 0) {
> 		char buf[TCL_INTEGER_SPACE * 4];
> 		
> 		sprintf(buf, "%d %d %d %d", x, y, width, height);
> 		Tcl_SetResult(interp, buf, TCL_VOLATILE);
> 	    }
> 	    break;
510,548c502,532
<     } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
< 	    && (length >= 2)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " cget option\"",
< 		    (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	result = Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
< 		(char *) textPtr, argv[2], 0);
<     } else if ((c == 'c') && (strncmp(argv[1], "compare", length) == 0)
< 	    && (length >= 3)) {
< 	int relation, value;
< 	CONST char *p;
< 
< 	if (argc != 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " compare index1 op index2\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if ((TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK)
< 		|| (TkTextGetIndex(interp, textPtr, argv[4], &index2)
< 		!= TCL_OK)) {
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	relation = TkTextIndexCmp(&index1, &index2);
< 	p = argv[3];
< 	if (p[0] == '<') {
< 		value = (relation < 0);
< 	    if ((p[1] == '=') && (p[2] == 0)) {
< 		value = (relation <= 0);
< 	    } else if (p[1] != 0) {
< 		compareError:
< 		Tcl_AppendResult(interp, "bad comparison operator \"",
< 			argv[3], "\": must be <, <=, ==, >=, >, or !=",
< 			(char *) NULL);
---
> 	case TEXT_CGET: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "option");
> 		result = TCL_ERROR;
> 		goto done;
> 	    } else {
> 		Tcl_Obj *objPtr = Tk_GetOptionValue(interp, (char *) textPtr,
> 		  textPtr->optionTable, objv[2], textPtr->tkwin);
> 		if (objPtr == NULL) {
> 		    result = TCL_ERROR;
> 		    goto done;
> 		} else {
> 		    Tcl_SetObjResult(interp, objPtr);
> 		    result = TCL_OK;
> 		}
> 	    }
> 	    break;
> 	}
> 	case TEXT_COMPARE: {
> 	    int relation, value;
> 	    CONST char *p;
> 	    CONST TkTextIndex *index1Ptr, *index2Ptr;
> 	    
> 	    if (objc != 5) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index1 op index2");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
> 	    index2Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[4]);
> 	    if (index1Ptr == NULL || index2Ptr == NULL) {
552,556c536,562
< 	} else if (p[0] == '>') {
< 		value = (relation > 0);
< 	    if ((p[1] == '=') && (p[2] == 0)) {
< 		value = (relation >= 0);
< 	    } else if (p[1] != 0) {
---
> 	    relation = TkTextIndexCmp(index1Ptr, index2Ptr);
> 	    p = Tcl_GetString(objv[3]);
> 	    if (p[0] == '<') {
> 		    value = (relation < 0);
> 		if ((p[1] == '=') && (p[2] == 0)) {
> 		    value = (relation <= 0);
> 		} else if (p[1] != 0) {
> 		    compareError:
> 		    Tcl_AppendResult(interp, "bad comparison operator \"",
> 			Tcl_GetString(objv[3]), 
> 			"\": must be <, <=, ==, >=, >, or !=",
> 			(char *) NULL);
> 		    result = TCL_ERROR;
> 		    goto done;
> 		}
> 	    } else if (p[0] == '>') {
> 		    value = (relation > 0);
> 		if ((p[1] == '=') && (p[2] == 0)) {
> 		    value = (relation >= 0);
> 		} else if (p[1] != 0) {
> 		    goto compareError;
> 		}
> 	    } else if ((p[0] == '=') && (p[1] == '=') && (p[2] == 0)) {
> 		value = (relation == 0);
> 	    } else if ((p[0] == '!') && (p[1] == '=') && (p[2] == 0)) {
> 		value = (relation != 0);
> 	    } else {
559,564c565,566
< 	} else if ((p[0] == '=') && (p[1] == '=') && (p[2] == 0)) {
< 	    value = (relation == 0);
< 	} else if ((p[0] == '!') && (p[1] == '=') && (p[2] == 0)) {
< 	    value = (relation != 0);
< 	} else {
< 	    goto compareError;
---
> 	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));
> 	    break;
566,577c568,583
< 	Tcl_SetResult(interp, ((value) ? "1" : "0"), TCL_STATIC);
<     } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
< 	    && (length >= 3)) {
< 	if (argc == 2) {
< 	    result = Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
< 		    (char *) textPtr, (char *) NULL, 0);
< 	} else if (argc == 3) {
< 	    result = Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
< 		    (char *) textPtr, argv[2], 0);
< 	} else {
< 	    result = ConfigureText(interp, textPtr, argc-2, argv+2,
< 		    TK_CONFIG_ARGV_ONLY);
---
> 	case TEXT_CONFIGURE: {
> 	    if (objc <= 3) {
> 		Tcl_Obj* objPtr = Tk_GetOptionInfo(interp, (char *) textPtr,
> 					  textPtr->optionTable,
> 			(objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
> 					  textPtr->tkwin);
> 		if (objPtr == NULL) {
> 		    result = TCL_ERROR;
> 		    goto done;
> 		} else {
> 		    Tcl_SetObjResult(interp, objPtr);
> 		}
> 	    } else {
> 		result = ConfigureText(interp, textPtr, objc-2, objv+2);
> 	    }
> 	    break;
579,585c585,601
<     } else if ((c == 'd') && (strncmp(argv[1], "debug", length) == 0)
< 	    && (length >= 3)) {
< 	if (argc > 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " debug boolean\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
---
> 	case TEXT_DEBUG: {
> 	    if (objc > 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "boolean");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    if (objc == 2) {
> 		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(tkBTreeDebug));
> 	    } else {
> 		if (Tcl_GetBooleanFromObj(interp, objv[2], 
> 					  &tkBTreeDebug) != TCL_OK) {
> 		    result = TCL_ERROR;
> 		    goto done;
> 		}
> 		tkTextDebug = tkBTreeDebug;
> 	    }
> 	    break;
587,590c603,730
< 	if (argc == 2) {
< 	    Tcl_SetResult(interp, ((tkBTreeDebug) ? "1" : "0"), TCL_STATIC);
< 	} else {
< 	    if (Tcl_GetBoolean(interp, argv[2], &tkBTreeDebug) != TCL_OK) {
---
> 	case TEXT_DELETE: {
> 	    if (objc < 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    if (textPtr->state == TK_TEXT_STATE_NORMAL) {
> 		if (objc < 5) {
> 		    /*
> 		     * Simple case requires no predetermination of indices.
> 		     */
> 		    result = DeleteChars(textPtr, objv[2],
> 			    (objc == 4) ? objv[3] : NULL, NULL, NULL);
> 		} else {
> 		    int i;
> 		    /*
> 		     * Multi-index pair case requires that we prevalidate
> 		     * the indices and sort from last to first so that
> 		     * deletes occur in the exact (unshifted) text.  It
> 		     * also needs to handle partial and fully overlapping
> 		     * ranges.  We have to do this with multiple passes.
> 		     */
> 		    TkTextIndex *indices, *ixStart, *ixEnd;
> 		    TkTextIndex *lastStart, *lastEnd;
> 		    char *useIdx;
> 
> 		    objc -= 2;
> 		    objv += 2;
> 		    indices = (TkTextIndex *)
> 			ckalloc((objc + 1) * sizeof(TkTextIndex));
> 
> 		    /*
> 		     * First pass verifies that all indices are valid.
> 		     */
> 		    for (i = 0; i < objc; i++) {
> 			CONST TkTextIndex *indexPtr = 
> 			  TkTextGetIndexFromObj(interp, textPtr, objv[i]);
> 			
> 			if (indexPtr == NULL) {
> 			    result = TCL_ERROR;
> 			    ckfree((char *) indices);
> 			    goto done;
> 			}
> 			indices[i] = *indexPtr;
> 		    }
> 		    /*
> 		     * Pad out the pairs evenly to make later code easier.
> 		     */
> 		    if (objc & 1) {
> 			indices[i] = indices[i-1];
> 			TkTextIndexForwChars(&indices[i], 1, &indices[i]);
> 			objc++;
> 		    }
> 		    useIdx = (char *) ckalloc((unsigned) objc);
> 		    memset(useIdx, 0, (unsigned) objc);
> 		    /*
> 		     * Do a decreasing order sort so that we delete the end
> 		     * ranges first to maintain index consistency.
> 		     */
> 		    qsort((VOID *) indices, (unsigned) (objc / 2),
> 			    2 * sizeof(TkTextIndex), TextIndexSortProc);
> 		    lastStart = lastEnd = NULL;
> 		    /*
> 		     * Second pass will handle bogus ranges (end < start) and
> 		     * overlapping ranges.
> 		     */
> 		    for (i = 0; i < objc; i += 2) {
> 			ixStart = &indices[i];
> 			ixEnd   = &indices[i+1];
> 			if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
> 			    continue;
> 			}
> 			if (lastStart) {
> 			    if (TkTextIndexCmp(ixStart, lastStart) == 0) {
> 				/*
> 				 * Start indices were equal, and the sort
> 				 * placed the longest range first, so
> 				 * skip this one.
> 				 */
> 				continue;
> 			    } else if (TkTextIndexCmp(lastStart, ixEnd) < 0) {
> 				/*
> 				 * The next pair has a start range before
> 				 * the end point of the last range.
> 				 * Constrain the delete range, but use
> 				 * the pointer values.
> 				 */
> 				*ixEnd = *lastStart;
> 				if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
> 				    continue;
> 				}
> 			    }
> 			}
> 			lastStart = ixStart;
> 			lastEnd   = ixEnd;
> 			useIdx[i]   = 1;
> 		    }
> 		    /*
> 		     * Final pass take the input from the previous and
> 		     * deletes the ranges which are flagged to be
> 		     * deleted.
> 		     */
> 		    for (i = 0; i < objc; i += 2) {
> 			if (useIdx[i]) {
> 			    /*
> 			     * We don't need to check the return value
> 			     * because all indices are preparsed above.
> 			     */
> 			    DeleteChars(textPtr, NULL, NULL,
> 				    &indices[i], &indices[i+1]);
> 			}
> 		    }
> 		    ckfree((char *) indices);
> 		}
> 	    }
> 	    break;
> 	}
> 	case TEXT_DLINEINFO: {
> 	    int x, y, width, height, base;
> 	    CONST TkTextIndex *indexPtr;
> 	    
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
> 	    if (indexPtr == NULL) {
594c734,741
< 	    tkTextDebug = tkBTreeDebug;
---
> 	    if (TkTextDLineInfo(textPtr, indexPtr, &x, &y, &width, 
> 				&height, &base) == 0) {
> 		char buf[TCL_INTEGER_SPACE * 5];
> 		
> 		sprintf(buf, "%d %d %d %d %d", x, y, width, height, base);
> 		Tcl_SetResult(interp, buf, TCL_VOLATILE);
> 	    }
> 	    break;
596,604c743,745
<     } else if ((c == 'd') && (strncmp(argv[1], "delete", length) == 0)
< 	    && (length >= 3)) {
< 	int i;
< 
< 	if (argc < 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " delete index1 ?index2 ...?\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
---
> 	case TEXT_DUMP: {
> 	    result = TextDumpCmd(textPtr, interp, objc, objv);
> 	    break;
606,627c747,753
< 	if (textPtr->state == TK_STATE_NORMAL) {
< 	    if (argc < 5) {
< 		/*
< 		 * Simple case requires no predetermination of indices.
< 		 */
< 		result = DeleteChars(textPtr, argv[2],
< 			(argc == 4) ? argv[3] : NULL, NULL, NULL);
< 	    } else {
< 		/*
< 		 * Multi-index pair case requires that we prevalidate the
< 		 * indices and sort from last to first so that deletes
< 		 * occur in the exact (unshifted) text.  It also needs to
< 		 * handle partial and fully overlapping ranges.  We have to
< 		 * do this with multiple passes.
< 		 */
< 		TkTextIndex *indices, *ixStart, *ixEnd, *lastStart, *lastEnd;
< 		char *useIdx;
< 
< 		argc -= 2;
< 		argv += 2;
< 		indices = (TkTextIndex *)
< 		    ckalloc((argc + 1) * sizeof(TkTextIndex));
---
> 	case TEXT_EDIT: {
> 	    result = TextEditCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_GET: {
> 	    Tcl_Obj *objPtr = NULL;
> 	    int i, found = 0;
629,634c755,781
< 		/*
< 		 * First pass verifies that all indices are valid.
< 		 */
< 		for (i = 0; i < argc; i++) {
< 		    if (TkTextGetIndex(interp, textPtr, argv[i],
< 			    &indices[i]) != TCL_OK) {
---
> 	    if (objc < 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index1 ?index2 ...?");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    for (i = 2; i < objc; i += 2) {
> 		CONST TkTextIndex *index1Ptr, *index2Ptr;
> 		TkTextIndex index2;
> 		
> 		index1Ptr = TkTextGetIndexFromObj(interp, textPtr, objv[i]);
> 		if (index1Ptr == NULL) {
> 		    if (objPtr) {
> 			Tcl_DecrRefCount(objPtr);
> 		    }
> 		    result = TCL_ERROR;
> 		    goto done;
> 		}
> 		if (i+1 == objc) {
> 		    TkTextIndexForwChars(index1Ptr, 1, &index2);
> 		    index2Ptr = &index2;
> 		} else {
> 		    index2Ptr = TkTextGetIndexFromObj(interp, textPtr, 
> 						      objv[i+1]);
> 		    if (index2Ptr == NULL) {
> 			if (objPtr) {
> 			    Tcl_DecrRefCount(objPtr);
> 			}
636d782
< 			ckfree((char *) indices);
640,674c786,798
< 		/*
< 		 * Pad out the pairs evenly to make later code easier.
< 		 */
< 		if (argc & 1) {
< 		    indices[i] = indices[i-1];
< 		    TkTextIndexForwChars(&indices[i], 1, &indices[i]);
< 		    argc++;
< 		}
< 		useIdx = (char *) ckalloc((unsigned) argc);
< 		memset(useIdx, 0, (unsigned) argc);
< 		/*
< 		 * Do a decreasing order sort so that we delete the end
< 		 * ranges first to maintain index consistency.
< 		 */
< 		qsort((VOID *) indices, (unsigned) (argc / 2),
< 			2 * sizeof(TkTextIndex), TextIndexSortProc);
< 		lastStart = lastEnd = NULL;
< 		/*
< 		 * Second pass will handle bogus ranges (end < start) and
< 		 * overlapping ranges.
< 		 */
< 		for (i = 0; i < argc; i += 2) {
< 		    ixStart = &indices[i];
< 		    ixEnd   = &indices[i+1];
< 		    if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
< 			continue;
< 		    }
< 		    if (lastStart) {
< 			if (TkTextIndexCmp(ixStart, lastStart) == 0) {
< 			    /*
< 			     * Start indices were equal, and the sort placed
< 			     * the longest range first, so skip this one.
< 			     */
< 			    continue;
< 			} else if (TkTextIndexCmp(lastStart, ixEnd) < 0) {
---
> 		if (TkTextIndexCmp(index1Ptr, index2Ptr) < 0) {
> 		    /* 
> 		     * We want to move the text we get from the window
> 		     * into the result, but since this could in principle
> 		     * be a megabyte or more, we want to do it
> 		     * efficiently!
> 		     */
> 		    Tcl_Obj *get = TextGetText(index1Ptr, index2Ptr);
> 		    found++;
> 		    if (found == 1) {
> 			Tcl_SetObjResult(interp, get);
> 		    } else {
> 			if (found == 2) {
676,678c800,801
< 			     * The next pair has a start range before the end
< 			     * point of the last range.  Constrain the delete
< 			     * range, but use the pointer values.
---
> 			     * Move the first item we put into the result into
> 			     * the first element of the list object.
680,683c803,805
< 			    *ixEnd = *lastStart;
< 			    if (TkTextIndexCmp(ixEnd, ixStart) <= 0) {
< 				continue;
< 			    }
---
> 			    objPtr = Tcl_NewObj();
> 			    Tcl_ListObjAppendElement(NULL, objPtr,
> 						     Tcl_GetObjResult(interp));
685,701c807
< 		    }
< 		    lastStart = ixStart;
< 		    lastEnd   = ixEnd;
< 		    useIdx[i]   = 1;
< 		}
< 		/*
< 		 * Final pass take the input from the previous and deletes
< 		 * the ranges which are flagged to be deleted.
< 		 */
< 		for (i = 0; i < argc; i += 2) {
< 		    if (useIdx[i]) {
< 			/*
< 			 * We don't need to check the return value because all
< 			 * indices are preparsed above.
< 			 */
< 			DeleteChars(textPtr, NULL, NULL,
< 				&indices[i], &indices[i+1]);
---
> 			Tcl_ListObjAppendElement(NULL, objPtr, get);
704d809
< 		ckfree((char *) indices);
705a811,814
> 	    if (found > 1) {
> 		Tcl_SetObjResult(interp, objPtr);
> 	    }
> 	    break;
707,726c816,818
<     } else if ((c == 'd') && (strncmp(argv[1], "dlineinfo", length) == 0)
< 	    && (length >= 2)) {
< 	int x, y, width, height, base;
< 
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " dlineinfo index\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) {
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextDLineInfo(textPtr, &index1, &x, &y, &width, &height, &base)
< 		== 0) {
< 	    char buf[TCL_INTEGER_SPACE * 5];
< 	    
< 	    sprintf(buf, "%d %d %d %d %d", x, y, width, height, base);
< 	    Tcl_SetResult(interp, buf, TCL_VOLATILE);
---
> 	case TEXT_IMAGE: {
> 	    result = TkTextImageCmd(textPtr, interp, objc, objv);
> 	    break;
728,739c820,835
<     } else if ((c == 'e') && (strncmp(argv[1], "edit", length) == 0)) {
<         result = TextEditCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
< 	Tcl_Obj *objPtr = NULL;
< 	Tcl_DString ds;
< 	int i, found = 0;
< 
< 	if (argc < 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " get index1 ?index2 ...?\"", (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
---
> 	case TEXT_INDEX: {
> 	    CONST TkTextIndex *indexPtr;
> 
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 2, objv, "index");
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    
> 	    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
> 	    if (indexPtr == NULL) {
> 		result = TCL_ERROR;
> 		goto done;
> 	    }
> 	    Tcl_SetObjResult(interp, TkTextNewIndexObj(textPtr, indexPtr));
> 	    break;
741,742c837,846
< 	for (i = 2; i < argc; i += 2) {
< 	    if (TkTextGetIndex(interp, textPtr, argv[i], &index1) != TCL_OK) {
---
> 	case TEXT_INSERT: {
> 	    int i, j, numTags;
> 	    Tcl_Obj **tagNamePtrs;
> 	    TkTextTag **oldTagArrayPtr;
> 	    CONST TkTextIndex *indexPtr;
> 	    TkTextIndex index1, index2;
> 
> 	    if (objc < 4) {
> 		Tcl_WrongNumArgs(interp, 2, objv, 
> 				 "index chars ?tagList chars tagList ...?");
746,753c850,851
< 	    if (i+1 == argc) {
< 		index2 = index1;
< 		TkTextIndexForwChars(&index2, 1, &index2);
< 	    } else if (TkTextGetIndex(interp, textPtr, argv[i+1], &index2)
< 		    != TCL_OK) {
< 		if (objPtr) {
< 		    Tcl_DecrRefCount(objPtr);
< 		}
---
> 	    indexPtr = TkTextGetIndexFromObj(interp, textPtr, objv[2]);
> 	    if (indexPtr == NULL) {
757,829c855,874
< 	    if (TkTextIndexCmp(&index1, &index2) < 0) {
< 		/* 
< 		 * Place the text in a DString and move it to the result.
< 		 * Since this could in principle be a megabyte or more, we
< 		 * want to do it efficiently!
< 		 */
< 		TextGetText(&index1, &index2, &ds);
< 		found++;
< 		if (found == 1) {
< 		    Tcl_DStringResult(interp, &ds);
< 		} else {
< 		    if (found == 2) {
< 			/*
< 			 * Move the first item we put into the result into
< 			 * the first element of the list object.
< 			 */
< 			objPtr = Tcl_NewObj();
< 			Tcl_ListObjAppendElement(NULL, objPtr,
< 				Tcl_GetObjResult(interp));
< 		    }
< 		    Tcl_ListObjAppendElement(NULL, objPtr,
< 			    Tcl_NewStringObj(Tcl_DStringValue(&ds),
< 				    Tcl_DStringLength(&ds)));
< 		}
< 		Tcl_DStringFree(&ds);
< 	    }
< 	}
< 	if (found > 1) {
< 	    Tcl_SetObjResult(interp, objPtr);
< 	}
<     } else if ((c == 'i') && (strncmp(argv[1], "index", length) == 0)
< 	    && (length >= 3)) {
< 	char buf[200];
< 
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " index index\"",
< 		    (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) {
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	TkTextPrintIndex(&index1, buf);
< 	Tcl_SetResult(interp, buf, TCL_VOLATILE);
<     } else if ((c == 'i') && (strncmp(argv[1], "insert", length) == 0)
< 	    && (length >= 3)) {
< 	int i, j, numTags;
< 	CONST char **tagNames;
< 	TkTextTag **oldTagArrayPtr;
< 
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0],
< 		    " insert index chars ?tagList chars tagList ...?\"",
< 		    (char *) NULL);
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) {
< 	    result = TCL_ERROR;
< 	    goto done;
< 	}
< 	if (textPtr->state == TK_STATE_NORMAL) {
< 	    for (j = 3;  j < argc; j += 2) {
< 		InsertChars(textPtr, &index1, argv[j]);
< 		if (argc > (j+1)) {
< 		    TkTextIndexForwBytes(&index1, (int) strlen(argv[j]),
< 			    &index2);
< 		    oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags);
< 		    if (oldTagArrayPtr != NULL) {
---
> 	    if (textPtr->state == TK_TEXT_STATE_NORMAL) {
> 		index1 = *indexPtr;
> 		for (j = 3;  j < objc; j += 2) {
> 		    int length = InsertChars(textPtr, &index1, objv[j]);
> 		    if (objc > (j+1)) {
> 			TkTextIndexForwBytes(&index1, length, &index2);
> 			oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags);
> 			if (oldTagArrayPtr != NULL) {
> 			    for (i = 0; i < numTags; i++) {
> 				TkBTreeTag(&index1, &index2, 
> 					   oldTagArrayPtr[i], 0);
> 			    }
> 			    ckfree((char *) oldTagArrayPtr);
> 			}
> 			if (Tcl_ListObjGetElements(interp, objv[j+1], 
> 						   &numTags, &tagNamePtrs)
> 				!= TCL_OK) {
> 			    result = TCL_ERROR;
> 			    goto done;
> 			}
831c876,878
< 			    TkBTreeTag(&index1, &index2, oldTagArrayPtr[i], 0);
---
> 			    TkBTreeTag(&index1, &index2,
> 			      TkTextCreateTag(textPtr, 
> 			      Tcl_GetString(tagNamePtrs[i])), 1);
833,842c880
< 			ckfree((char *) oldTagArrayPtr);
< 		    }
< 		    if (Tcl_SplitList(interp, argv[j+1], &numTags, &tagNames)
< 			    != TCL_OK) {
< 			result = TCL_ERROR;
< 			goto done;
< 		    }
< 		    for (i = 0; i < numTags; i++) {
< 			TkBTreeTag(&index1, &index2,
< 				TkTextCreateTag(textPtr, tagNames[i]), 1);
---
> 			index1 = index2;
844,845d881
< 		    ckfree((char *) tagNames);
< 		    index1 = index2;
847a884,916
> 	    break;
> 	}
> 	case TEXT_MARK: {
> 	    result = TkTextMarkCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_SCAN: {
> 	    result = TkTextScanCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_SEARCH: {
> 	    result = TextSearchCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_SEE: {
> 	    result = TkTextSeeCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_TAG: {
> 	    result = TkTextTagCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_WINDOW: {
> 	    result = TkTextWindowCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_XVIEW: {
> 	    result = TkTextXviewCmd(textPtr, interp, objc, objv);
> 	    break;
> 	}
> 	case TEXT_YVIEW: {
> 	    result = TkTextYviewCmd(textPtr, interp, objc, objv);
> 	    break;
849,877d917
<     } else if ((c == 'd') && (strncmp(argv[1], "dump", length) == 0)) {
< 	result = TextDumpCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'i') && (strncmp(argv[1], "image", length) == 0)) {
< 	result = TkTextImageCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'm') && (strncmp(argv[1], "mark", length) == 0)) {
< 	result = TkTextMarkCmd(textPtr, interp, argc, argv);
<     } else if ((c == 's') && (strcmp(argv[1], "scan") == 0) && (length >= 2)) {
< 	result = TkTextScanCmd(textPtr, interp, argc, argv);
<     } else if ((c == 's') && (strcmp(argv[1], "search") == 0)
< 	    && (length >= 3)) {
< 	result = TextSearchCmd(textPtr, interp, argc, argv);
<     } else if ((c == 's') && (strcmp(argv[1], "see") == 0) && (length >= 3)) {
< 	result = TkTextSeeCmd(textPtr, interp, argc, argv);
<     } else if ((c == 't') && (strcmp(argv[1], "tag") == 0)) {
< 	result = TkTextTagCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'w') && (strncmp(argv[1], "window", length) == 0)) {
< 	result = TkTextWindowCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'x') && (strncmp(argv[1], "xview", length) == 0)) {
< 	result = TkTextXviewCmd(textPtr, interp, argc, argv);
<     } else if ((c == 'y') && (strncmp(argv[1], "yview", length) == 0)
< 	    && (length >= 2)) {
< 	result = TkTextYviewCmd(textPtr, interp, argc, argv);
<     } else {
< 	Tcl_AppendResult(interp, "bad option \"", argv[1],
< 		"\": must be bbox, cget, compare, configure, debug, delete, ",
<                 "dlineinfo, dump, edit, get, image, index, insert, mark, ",
<                 "scan, search, see, tag, window, xview, or yview",
< 		(char *) NULL);
< 	result = TCL_ERROR;
879c919
< 
---
>     
956,960c996,1001
<      * Free up all the stuff that requires special handling, then
<      * let Tk_FreeOptions handle all the standard option-related
<      * stuff.  Special note:  free up display-related information
<      * before deleting the B-tree, since display-related stuff
<      * may refer to stuff in the B-tree.
---
>      * Free up all the stuff that requires special handling.  We have
>      * already called let Tk_FreeConfigOptions to handle all the standard
>      * option-related stuff (and so none of that exists when we are
>      * called).  Special note: free up display-related information before
>      * deleting the B-tree, since display-related stuff may refer to
>      * stuff in the B-tree.
987,997c1028,1031
<     /*
<      * NOTE: do NOT free up selBorder, selBdString, or selFgColorPtr:
<      * they are duplicates of information in the "sel" tag, which was
<      * freed up as part of deleting the tags above.
<      */
< 
<     textPtr->selBorder = NULL;
<     textPtr->selBdString = NULL;
<     textPtr->selFgColorPtr = NULL;
<     Tk_FreeOptions(configSpecs, (char *) textPtr, textPtr->display, 0);
<     ckfree((char *) textPtr);
---
>     textPtr->refCount--;
>     if (textPtr->refCount == 0) {
>         ckfree((char *) textPtr);
>     }
1005c1039
<  *	This procedure is called to process an argv/argc list, plus
---
>  *	This procedure is called to process an objv/objc list, plus
1022c1056
< ConfigureText(interp, textPtr, argc, argv, flags)
---
> ConfigureText(interp, textPtr, objc, objv)
1026,1028c1060,1061
<     int argc;			/* Number of valid entries in argv. */
<     CONST char **argv;		/* Arguments. */
<     int flags;			/* Flags to pass to Tk_ConfigureWidget. */
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. */
1029a1063
>     Tk_SavedOptions savedOptions;
1032,1033c1066,1067
<     if (Tk_ConfigureWidget(interp, textPtr->tkwin, configSpecs,
< 	    argc, argv, (char *) textPtr, flags) != TCL_OK) {
---
>     if (Tk_SetOptions(interp, (char*)textPtr, textPtr->optionTable,
> 	    objc, objv, textPtr->tkwin, &savedOptions, NULL) != TCL_OK) {
1068c1102
<     if (textPtr->tabOptionString != NULL) {
---
>     if (textPtr->tabOptionPtr != NULL) {
1070c1104
< 		textPtr->tabOptionString);
---
> 		textPtr->tabOptionPtr);
1072a1107
> 	    Tk_RestoreSavedOptions(&savedOptions);
1086,1096c1121,1123
<     if (textPtr->selTagPtr->bdString != textPtr->selBdString) {
< 	textPtr->selTagPtr->bdString = textPtr->selBdString;
< 	if (textPtr->selBdString != NULL) {
< 	    if (Tk_GetPixels(interp, textPtr->tkwin, textPtr->selBdString,
< 		    &textPtr->selTagPtr->borderWidth) != TCL_OK) {
< 		return TCL_ERROR;
< 	    }
< 	    if (textPtr->selTagPtr->borderWidth < 0) {
< 		textPtr->selTagPtr->borderWidth = 0;
< 	    }
< 	}
---
>     if (textPtr->selTagPtr->borderWidthPtr != textPtr->selBorderWidthPtr) {
> 	textPtr->selTagPtr->borderWidthPtr = textPtr->selBorderWidthPtr;
> 	textPtr->selTagPtr->borderWidth = textPtr->selBorderWidth;
1101c1128
< 	    || (textPtr->selTagPtr->bdString != NULL)
---
> 	    || (textPtr->selTagPtr->borderWidth != 0)
1116c1143
< 	    || (textPtr->selTagPtr->tabString != NULL)
---
> 	    || (textPtr->selTagPtr->tabStringPtr != NULL)
1166a1194
>     Tk_FreeSavedOptions(&savedOptions);
1184c1212
<  *	Configures all tags in the Text with a empty argc/argv, for
---
>  *	Configures all tags in the Text with a empty objc/objv, for
1262a1291,1302
> 	    /*
> 	     * NOTE: we must zero out selBorder, selBorderWidthPtr and
> 	     * selFgColorPtr: they are duplicates of information in the
> 	     * "sel" tag, which will be freed up when we delete all tags.
> 	     * Hence we don't want the automatic config options freeing
> 	     * process to delete them as well.
> 	     */
> 
> 	    textPtr->selBorder = NULL;
> 	    textPtr->selBorderWidthPtr = NULL;
> 	    textPtr->selBorderWidth = 0;
> 	    textPtr->selFgColorPtr = NULL;
1265a1306,1307
> 	    Tk_FreeConfigOptions((char *) textPtr, textPtr->optionTable,
> 				 textPtr->tkwin);
1349c1391
<  *	None.
---
>  *	The length of the inserted string.
1352c1394
<  *	The characters in "string" get added to the text just before
---
>  *	The characters in "stringPtr" get added to the text just before
1358,1359c1400,1401
< static void
< InsertChars(textPtr, indexPtr, string)
---
> static int
> InsertChars(textPtr, cIndexPtr, stringPtr)
1361c1403
<     TkTextIndex *indexPtr;	/* Where to insert new characters.  May be
---
>     CONST TkTextIndex *cIndexPtr;/* Where to insert new characters.  May be
1363c1405
<     CONST char *string;		/* Null-terminated string containing new
---
>     Tcl_Obj *stringPtr;		/* Null-terminated string containing new
1367,1369c1409,1414
<     TkTextIndex newTop;
<     char indexBuffer[TK_POS_CHARS];
< 
---
>     TkTextIndex tempIndex;
>     TkTextIndex *indexPtr;
>     int length;
>     
>     CONST char *string = Tcl_GetStringFromObj(stringPtr, &length);
>     
1374c1419
<     lineIndex = TkBTreeLineIndex(indexPtr->linePtr);
---
>     lineIndex = TkBTreeLineIndex(cIndexPtr->linePtr);
1377c1422,1424
< 	TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, indexPtr);
---
> 	TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &tempIndex);
>     } else {
> 	tempIndex = *cIndexPtr;
1379c1426,1427
< 
---
>     indexPtr = &tempIndex;
>     
1392c1440
< 	    offset += strlen(string);
---
> 	    offset += length;
1395a1444
>     textPtr->stateEpoch ++;
1402,1407c1451,1453
<     if ( textPtr->undo ) {
<         TkTextIndex     toIndex;
< 
<         Tcl_DString actionCommand;
<         Tcl_DString revertCommand;
<         
---
>     if (textPtr->undo) {
>         TkTextIndex toIndex;
> 	
1414,1454d1459
<         
<         Tcl_DStringInit(&actionCommand);
<         Tcl_DStringInit(&revertCommand);
<         
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," insert ",-1);
<         TkTextPrintIndex(indexPtr,indexBuffer);
<         Tcl_DStringAppend(&actionCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&actionCommand," ",-1);
<         Tcl_DStringAppendElement(&actionCommand,string);
<         Tcl_DStringAppend(&actionCommand,";",-1);
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," mark set insert ",-1);
<         TkTextIndexForwBytes(indexPtr, (int) strlen(string),
< 			&toIndex);
<         TkTextPrintIndex(&toIndex, indexBuffer);
<         Tcl_DStringAppend(&actionCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&actionCommand,"; ",-1);
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," see insert",-1);
<         
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," delete ",-1);
<         TkTextPrintIndex(indexPtr,indexBuffer);
<         Tcl_DStringAppend(&revertCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&revertCommand," ",-1);
<         TkTextPrintIndex(&toIndex, indexBuffer);
<         Tcl_DStringAppend(&revertCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&revertCommand," ;",-1);
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," mark set insert ",-1);
<         TkTextPrintIndex(indexPtr,indexBuffer);
<         Tcl_DStringAppend(&revertCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&revertCommand,"; ",-1);
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," see insert",-1);
<         
<         TkUndoPushAction(textPtr->undoStack,&actionCommand, &revertCommand);
< 
<      	Tcl_DStringFree(&actionCommand);
<      	Tcl_DStringFree(&revertCommand);
1455a1461,1462
> 	TkTextIndexForwBytes(indexPtr, length, &toIndex);
> 	TextPushUndoAction(textPtr, stringPtr, 1, indexPtr, &toIndex);
1457c1464,1465
<     updateDirtyFlag(textPtr);
---
>     
>     UpdateDirtyFlag(textPtr);
1459a1468
> 	TkTextIndex newTop;
1469a1479,1585
>     
>     /* For convenience, return the length of the string */
>     return length;
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * TextPushUndoAction --
>  *
>  *	Shared by insert and delete actions.  Stores the appropriate
>  *	scripts into our undo stack.  We will add a single refCount to
>  *	the 'undoString' object, so, if it previously had a refCount of
>  *	zero, the caller should not free it.
>  *
>  * Results:
>  *	None.
>  *
>  * Side effects:
>  *	Items pushed onto stack.
>  *
>  *----------------------------------------------------------------------
>  */
> 
> static void
> TextPushUndoAction (textPtr, undoString, insert, index1Ptr, index2Ptr)
>     TkText *textPtr;		 /* Overall information about text widget. */
>     Tcl_Obj *undoString;	 /* New text */
>     int insert;                  /* 1 if insert, else delete */
>     CONST TkTextIndex *index1Ptr;/* Index describing first location */
>     CONST TkTextIndex *index2Ptr;/* Index describing second location */
> {
>     /* Create the helpers */
>     Tcl_Obj *cmdNameObj = Tcl_NewObj();
>     Tcl_Obj *seeInsertObj = Tcl_NewObj();
>     Tcl_Obj *markSet1InsertObj = Tcl_NewObj();
>     Tcl_Obj *markSet2InsertObj = Tcl_NewObj();
>     Tcl_Obj *insertCmdObj = Tcl_NewObj();
>     Tcl_Obj *deleteCmdObj = Tcl_NewObj();
>     
>     Tcl_Obj *insertCmd = Tcl_NewObj();
>     Tcl_Obj *deleteCmd = Tcl_NewObj();
>     
>     /* Get the index positions */
>     Tcl_Obj *index1Obj = TkTextNewIndexObj(textPtr, index1Ptr);
>     Tcl_Obj *index2Obj = TkTextNewIndexObj(textPtr, index2Ptr);
> 
>     /* Get the fully qualified name */
>     Tcl_GetCommandFullName(textPtr->interp, textPtr->widgetCmd, cmdNameObj);
> 
>     /* These need refCounts, because they are used more than once below */
>     Tcl_IncrRefCount(cmdNameObj);
>     Tcl_IncrRefCount(seeInsertObj);
>     Tcl_IncrRefCount(index1Obj);
>     Tcl_IncrRefCount(index2Obj);
> 
>     Tcl_ListObjAppendElement(NULL, seeInsertObj, cmdNameObj);
>     Tcl_ListObjAppendElement(NULL, seeInsertObj, Tcl_NewStringObj("see",3));
>     Tcl_ListObjAppendElement(NULL, seeInsertObj, Tcl_NewStringObj("insert",6));
> 
>     Tcl_ListObjAppendElement(NULL, markSet1InsertObj, cmdNameObj);
>     Tcl_ListObjAppendElement(NULL, markSet1InsertObj, 
> 			     Tcl_NewStringObj("mark",4));
>     Tcl_ListObjAppendElement(NULL, markSet1InsertObj, 
> 			     Tcl_NewStringObj("set",3));
>     Tcl_ListObjAppendElement(NULL, markSet1InsertObj, 
> 			     Tcl_NewStringObj("insert",6));
>     markSet2InsertObj = Tcl_DuplicateObj(markSet1InsertObj);
>     Tcl_ListObjAppendElement(NULL, markSet1InsertObj, index1Obj);
>     Tcl_ListObjAppendElement(NULL, markSet2InsertObj, index2Obj);
> 
>     Tcl_ListObjAppendElement(NULL, insertCmdObj, cmdNameObj);
>     Tcl_ListObjAppendElement(NULL, insertCmdObj, Tcl_NewStringObj("insert",6));
>     Tcl_ListObjAppendElement(NULL, insertCmdObj, index1Obj);
>     /* Only use of 'undoString' */
>     Tcl_ListObjAppendElement(NULL, insertCmdObj, undoString);
> 
>     Tcl_ListObjAppendElement(NULL, deleteCmdObj, cmdNameObj);
>     Tcl_ListObjAppendElement(NULL, deleteCmdObj, Tcl_NewStringObj("delete",6));
>     Tcl_ListObjAppendElement(NULL, deleteCmdObj, index1Obj);
>     Tcl_ListObjAppendElement(NULL, deleteCmdObj, index2Obj);
> 
>     Tcl_ListObjAppendElement(NULL, insertCmd, insertCmdObj);
>     Tcl_ListObjAppendElement(NULL, insertCmd, markSet2InsertObj);
>     Tcl_ListObjAppendElement(NULL, insertCmd, seeInsertObj);
>     Tcl_ListObjAppendElement(NULL, deleteCmd, deleteCmdObj);
>     Tcl_ListObjAppendElement(NULL, deleteCmd, markSet1InsertObj);
>     Tcl_ListObjAppendElement(NULL, deleteCmd, seeInsertObj);
>     
>     Tcl_DecrRefCount(cmdNameObj);
>     Tcl_DecrRefCount(seeInsertObj);
>     Tcl_DecrRefCount(index1Obj);
>     Tcl_DecrRefCount(index2Obj);
> 
>     /* 
>      * Depending whether the action is to insert or delete, we provide
>      * the appropriate second and third arguments to TkUndoPushAction.
>      * (The first is the 'actionCommand', and the second the
>      * 'revertCommand').  The final '1' says we are providing a list
>      * of scripts to execute rather than a single script.
>      */
>     if (insert) {
> 	TkUndoPushAction(textPtr->undoStack, insertCmd, deleteCmd, 1);
>     } else {
> 	TkUndoPushAction(textPtr->undoStack, deleteCmd, insertCmd, 1);
>     }
>     
1491,1504c1607,1620
< DeleteChars(textPtr, index1String, index2String, indexPtr1, indexPtr2)
<     TkText *textPtr;		/* Overall information about text widget. */
<     CONST char *index1String;	/* String describing location of first
< 				 * character to delete. */
<     CONST char *index2String;	/* String describing location of last
< 				 * character to delete.  NULL means just
< 				 * delete the one character given by
< 				 * index1String. */
<     TkTextIndex *indexPtr1;	/* index describing location of first
< 				 * character to delete. */
<     TkTextIndex *indexPtr2;	/* index describing location of last
< 				 * character to delete.  NULL means just
< 				 * delete the one character given by
< 				 * indexPtr1. */
---
> DeleteChars(textPtr, index1Obj, index2Obj, indexPtr1, indexPtr2)
>     TkText *textPtr;		 /* Overall information about text widget. */
>     Tcl_Obj *index1Obj;	         /* Object describing location of first
> 				  * character to delete. */
>     Tcl_Obj *index2Obj;	         /* Object describing location of last
> 				  * character to delete.  NULL means just
> 				  * delete the one character given by
> 				  * index1Obj. */
>     CONST TkTextIndex *indexPtr1;/* Index describing location of first
> 				  * character to delete. */
>     CONST TkTextIndex *indexPtr2;/* Index describing location of last
> 				  * character to delete.  NULL means just
> 				  * delete the one character given by
> 				  * indexPtr1. */
1508d1623
<     char indexBuffer[TK_POS_CHARS];
1514,1516c1629,1631
<     if (index1String != NULL) {
< 	if (TkTextGetIndex(textPtr->interp, textPtr, index1String, &index1)
< 		!= TCL_OK) {
---
>     if (index1Obj != NULL) {
> 	indexPtr1 = TkTextGetIndexFromObj(textPtr->interp, textPtr, index1Obj);
> 	if (indexPtr1 == NULL) {
1519,1521c1634,1638
< 	if (index2String != NULL) {
< 	    if (TkTextGetIndex(textPtr->interp, textPtr, index2String, &index2)
< 		    != TCL_OK) {
---
> 	index1 = *indexPtr1;
> 	if (index2Obj != NULL) {
> 	    indexPtr2 = TkTextGetIndexFromObj(textPtr->interp, textPtr, 
> 					      index2Obj);
> 	    if (indexPtr2 == NULL) {
1523a1641
> 	    index2 = *indexPtr2;
1636,1639c1754,1755
< 	Tcl_DString ds;
<         Tcl_DString actionCommand;
<         Tcl_DString revertCommand;
<     
---
> 	Tcl_Obj *get;
> 	
1647,1688c1763,1764
<         Tcl_DStringInit(&actionCommand);
<         Tcl_DStringInit(&revertCommand);
< 
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," delete ",-1);
<         TkTextPrintIndex(&index1,indexBuffer);
<         Tcl_DStringAppend(&actionCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&actionCommand," ",-1);
<         TkTextPrintIndex(&index2, indexBuffer);
<         Tcl_DStringAppend(&actionCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&actionCommand,"; ",-1);
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," mark set insert ",-1);
<         TkTextPrintIndex(&index1,indexBuffer);
<         Tcl_DStringAppend(&actionCommand,indexBuffer,-1);
< 
<         Tcl_DStringAppend(&actionCommand,"; ",-1);
<         Tcl_DStringAppend(&actionCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&actionCommand," see insert",-1);
< 
< 	TextGetText(&index1, &index2, &ds);
< 
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," insert ",-1);
<         TkTextPrintIndex(&index1,indexBuffer);
<         Tcl_DStringAppend(&revertCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&revertCommand," ",-1);
<         Tcl_DStringAppendElement(&revertCommand,Tcl_DStringValue(&ds));
<         Tcl_DStringAppend(&revertCommand,"; ",-1);
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," mark set insert ",-1);
<         TkTextPrintIndex(&index2, indexBuffer);
<         Tcl_DStringAppend(&revertCommand,indexBuffer,-1);
<         Tcl_DStringAppend(&revertCommand,"; ",-1);
<         Tcl_DStringAppend(&revertCommand,Tcl_GetCommandName(textPtr->interp,textPtr->widgetCmd),-1);
<         Tcl_DStringAppend(&revertCommand," see insert",-1);
< 
<         TkUndoPushAction(textPtr->undoStack,&actionCommand, &revertCommand);
< 
<         Tcl_DStringFree(&actionCommand);
<         Tcl_DStringFree(&revertCommand);
< 
---
> 	get = TextGetText(&index1, &index2);
> 	TextPushUndoAction(textPtr, get, 0, &index1, &index2);
1690c1766
<     updateDirtyFlag(textPtr);
---
>     UpdateDirtyFlag(textPtr);
1691a1768
>     textPtr->stateEpoch ++;
1800c1877
< 		goto done;
---
> 		goto fetchDone;
1841c1918
<     done:
---
>     fetchDone:
1934c2011
<     if ((textPtr->state == TK_STATE_DISABLED) ||
---
>     if ((textPtr->state == TK_TEXT_STATE_DISABLED) ||
1973c2050
< TextSearchCmd(textPtr, interp, argc, argv)
---
> TextSearchCmd(textPtr, interp, objc, objv)
1976,1977c2053,2054
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings. */
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. */
1979,1994c2056,2058
<     int backwards, exact, searchElide, c, i, argsLeft, noCase, leftToScan;
<     size_t length;
<     int numLines, startingLine, startingByte, lineNum, firstByte, lastByte;
<     int code, matchLength, matchByte, passes, stopLine, searchWholeText;
<     int patLength;
<     CONST char *arg, *pattern, *varName, *p, *startOfLine;
<     char buffer[20];
<     TkTextIndex index, stopIndex;
<     Tcl_DString line, patDString;
<     TkTextSegment *segPtr;
<     TkTextLine *linePtr;
<     TkTextIndex curIndex;
<     Tcl_Obj *patObj = NULL;
<     Tcl_RegExp regexp = NULL;		/* Initialization needed only to
< 					 * prevent compiler warning. */
< 
---
>     int i, argsLeft, code;
>     TkLineSearchSpec searchSpec;
>     
1999,2006c2063,2079
<     exact = 1;
<     searchElide = 0;
<     curIndex.tree = textPtr->tree;
<     backwards = 0;
<     noCase = 0;
<     varName = NULL;
<     for (i = 2; i < argc; i++) {
< 	arg = argv[i];
---
>     searchSpec.exact = 1;
>     searchSpec.noCase = 0;
>     searchSpec.all = 0;
>     searchSpec.backwards = 0;
>     searchSpec.textPtr = textPtr;
>     searchSpec.varPtr = NULL;
>     searchSpec.countPtr = NULL;
>     searchSpec.resPtr = NULL;
>     searchSpec.searchElide = 0;
>     searchSpec.numLines = TkBTreeNumLines(textPtr->tree);
> 
>     for (i = 2; i < objc; i++) {
> 	size_t length;
> 	char c;
> 	
> 	CONST char *arg = Tcl_GetStringFromObj(objv[i],&length);
> 	
2010d2082
< 	length = strlen(arg);
2014c2086
< 		    "\": must be --, -backward, -count, -elide, -exact, ",
---
> 		    "\": must be --, -all, -backward, -count, -elide, -exact, ",
2019,2022c2091,2096
< 	if ((c == 'b') && (strncmp(argv[i], "-backwards", length) == 0)) {
< 	    backwards = 1;
< 	} else if ((c == 'c') && (strncmp(argv[i], "-count", length) == 0)) {
< 	    if (i >= (argc-1)) {
---
> 	if ((c == 'a') && (strncmp(arg, "-all", length) == 0)) {
> 	    searchSpec.all = 1;
> 	} else if ((c == 'b') && (strncmp(arg, "-backwards", length) == 0)) {
> 	    searchSpec.backwards = 1;
> 	} else if ((c == 'c') && (strncmp(arg, "-count", length) == 0)) {
> 	    if (i >= (objc-1)) {
2028c2102,2106
< 	    varName = argv[i];
---
> 	    /* 
> 	     * Assumption objv[i] isn't going to disappear on us during
> 	     * this procedure, which is fair.
> 	     */
> 	    searchSpec.varPtr = objv[i];
2030,2031c2108,2109
< 		&& (strncmp(argv[i], "-exact", length) == 0)) {
< 	    exact = 1;
---
> 		&& (strncmp(arg, "-exact", length) == 0)) {
> 	    searchSpec.exact = 1;
2033,2035c2111,2113
< 		&& (strncmp(argv[i], "-elide", length) == 0)) {
< 	    searchElide = 1;
< 	} else if ((c == 'h') && (strncmp(argv[i], "-hidden", length) == 0)) {
---
> 		&& (strncmp(arg, "-elide", length) == 0)) {
> 	    searchSpec.searchElide = 1;
> 	} else if ((c == 'h') && (strncmp(arg, "-hidden", length) == 0)) {
2040,2047c2118,2125
< 	    searchElide = 1;
< 	} else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) {
< 	    backwards = 0;
< 	} else if ((c == 'n') && (strncmp(argv[i], "-nocase", length) == 0)) {
< 	    noCase = 1;
< 	} else if ((c == 'r') && (strncmp(argv[i], "-regexp", length) == 0)) {
< 	    exact = 0;
< 	} else if ((c == '-') && (strncmp(argv[i], "--", length) == 0)) {
---
> 	    searchSpec.searchElide = 1;
> 	} else if ((c == 'f') && (strncmp(arg, "-forwards", length) == 0)) {
> 	    searchSpec.backwards = 0;
> 	} else if ((c == 'n') && (strncmp(arg, "-nocase", length) == 0)) {
> 	    searchSpec.noCase = 1;
> 	} else if ((c == 'r') && (strncmp(arg, "-regexp", length) == 0)) {
> 	    searchSpec.exact = 0;
> 	} else if ((c == '-') && (strncmp(arg, "--", length) == 0)) {
2054c2132
<     argsLeft = argc - (i+2);
---
>     argsLeft = objc - (i+2);
2056,2058c2134,2135
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " search ?switches? pattern index ?stopIndex?\"",
< 		(char *) NULL);
---
> 	Tcl_WrongNumArgs(interp, 2, objv, 
> 			 "?switches? pattern index ?stopIndex?");
2061d2137
<     pattern = argv[i];
2063,2064c2139,2141
<     /*
<      * Convert the pattern to lower-case if we're supposed to ignore case.
---
>     /* 
>      * Find the starting line and starting offset (measured in Unicode
>      * chars for regexp search, utf-8 bytes for exact search)
2066,2075c2143,2144
< 
<     if (noCase && exact) {
< 	Tcl_DStringInit(&patDString);
< 	Tcl_DStringAppend(&patDString, pattern, -1);
< 	Tcl_UtfToLower(Tcl_DStringValue(&patDString));
< 	pattern = Tcl_DStringValue(&patDString);
<     }
< 
<     Tcl_DStringInit(&line);
<     if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) {
---
>     if (SearchGetLineIndex(interp, objv[i+1], &searchSpec, 1, 
> 		&searchSpec.startLine, &searchSpec.startOffset) != TCL_OK) {
2077,2090c2146
< 	goto done;
<     }
<     numLines = TkBTreeNumLines(textPtr->tree);
<     startingLine = TkBTreeLineIndex(index.linePtr);
<     startingByte = index.byteIndex;
<     if (startingLine >= numLines) {
< 	if (backwards) {
< 	    startingLine = TkBTreeNumLines(textPtr->tree) - 1;
< 	    startingByte = TkBTreeBytesInLine(TkBTreeFindLine(textPtr->tree,
< 		    startingLine));
< 	} else {
< 	    startingLine = 0;
< 	    startingByte = 0;
< 	}
---
> 	goto cleanup;
2091a2148,2151
> 
>     /* 
>      * Find the optional end location, similarly.
>      */
2093c2153,2154
< 	if (TkTextGetIndex(interp, textPtr, argv[i+2], &stopIndex) != TCL_OK) {
---
> 	if (SearchGetLineIndex(interp, objv[i+2], &searchSpec, 0, 
> 		  &searchSpec.stopLine, &searchSpec.stopOffset) != TCL_OK) {
2095,2099c2156
< 	    goto done;
< 	}
< 	stopLine = TkBTreeLineIndex(stopIndex.linePtr);
< 	if (!backwards && (stopLine == numLines)) {
< 	    stopLine = numLines-1;
---
> 	    goto cleanup;
2101d2157
< 	searchWholeText = 0;
2103,2104c2159
< 	stopLine = 0;
< 	searchWholeText = 1;
---
> 	searchSpec.stopLine = -1;
2106c2161
< 
---
>     
2112,2121c2167,2173
<     matchLength = patLength = 0;	/* Only needed to prevent compiler
< 					 * warnings. */
<     if (exact) {
< 	patLength = strlen(pattern);
<     } else {
< 	patObj = Tcl_NewStringObj(pattern, -1);
< 	Tcl_IncrRefCount(patObj);
< 	regexp = Tcl_GetRegExpFromObj(interp, patObj,
< 		(noCase ? TCL_REG_NOCASE : 0) | TCL_REG_ADVANCED);
< 	if (regexp == NULL) {
---
>     code = PerformSearch(interp, &searchSpec, objv[i]);
> 
>     /* Set the '-count' variable, if given */
>     if (searchSpec.varPtr != NULL && searchSpec.countPtr != NULL) {
> 	Tcl_IncrRefCount(searchSpec.countPtr);
> 	if (Tcl_ObjSetVar2(interp, searchSpec.varPtr, NULL, 
> 			   searchSpec.countPtr, TCL_LEAVE_ERR_MSG) == NULL) {
2123c2175
< 	    goto done;
---
> 	    goto cleanup;
2126,2134c2178,2253
<     lineNum = startingLine;
<     code = TCL_OK;
<     for (passes = 0; passes < 2; ) {
< 	if (lineNum >= numLines) {
< 	    /*
< 	     * Don't search the dummy last line of the text.
< 	     */
< 
< 	    goto nextLine;
---
>     
>     /* Set the result */
>     if (searchSpec.resPtr != NULL) {
> 	Tcl_SetObjResult(interp, searchSpec.resPtr);
> 	searchSpec.resPtr = NULL;
>     }
>         
>     cleanup:
>     if (searchSpec.countPtr != NULL) {
> 	Tcl_DecrRefCount(searchSpec.countPtr);
>     }
>     if (searchSpec.resPtr != NULL) {
> 	Tcl_DecrRefCount(searchSpec.resPtr);
>     }
>     return code;
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * SearchGetLineIndex --
>  *
>  *	Extract a row, text offset index position from an objPtr
>  *	
>  *	This means we ignore any embedded windows/images and
>  *	elidden text (unless we are searching that).
>  *
>  * Results:
>  *      Standard Tcl error code (with a message in the interpreter
>  *      on error conditions).
>  *      
>  *	The returned offset is a utf-8 char* byte index for exact
>  *	searches, and a Unicode character index for regexp searches.
>  *
>  * Side effects:
>  *	None.
>  *
>  *----------------------------------------------------------------------
>  */
> static int
> SearchGetLineIndex(interp, objPtr, searchSpecPtr, forwardWrap, 
> 		   linePosPtr, offsetPosPtr)
>     Tcl_Interp *interp;                /* For error messages */
>     Tcl_Obj *objPtr;                   /* Contains a textual index 
>                                         * like "1.2" */
>     TkLineSearchSpec *searchSpecPtr;   /* Contains other search 
>                                         * parameters */
>     int forwardWrap;                   /* If the given position is at or 
>                                         * beyond the end of the text, if 1 
>                                         * then wrap to the beginning (0,0), 
>                                         * else find the very last textual 
>                                         * position.  This logic is reversed
>                                         * if the search is backwards */
>     int *linePosPtr;                   /* For returning the line number */
>     int *offsetPosPtr;                 /* For returning the text offset in 
>                                         * the line */
> {
>     CONST TkTextIndex *indexPtr;
>     int line;
>     
>     indexPtr = TkTextGetIndexFromObj(interp, searchSpecPtr->textPtr, objPtr);
>     if (indexPtr == NULL) {
> 	return TCL_ERROR;
>     }
>     
>     line = TkBTreeLineIndex(indexPtr->linePtr);
>     if (line >= searchSpecPtr->numLines) {
> 	if (searchSpecPtr->backwards ^ forwardWrap) {
> 	    line = 0;
> 	    *offsetPosPtr = 0;
> 	} else {
> 	    TkTextLine *linePtr;
> 	    line = searchSpecPtr->numLines-1;
> 	    linePtr = TkBTreeFindLine(searchSpecPtr->textPtr->tree, line);
> 	    *offsetPosPtr = SearchIndexInLine(searchSpecPtr, linePtr, 
> 					      TkBTreeBytesInLine(linePtr));
2135a2255,2260
>     } else {
> 	*offsetPosPtr = SearchIndexInLine(searchSpecPtr, 
> 			  indexPtr->linePtr, indexPtr->byteIndex);
>     }
>     
>     *linePosPtr = line;
2137,2141c2262,2284
< 	/*
< 	 * Extract the text from the line.  If we're doing regular
< 	 * expression matching, drop the newline from the line, so
< 	 * that "$" can be used to match the end of the line.
< 	 */
---
>     return TCL_OK;
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * SearchIndexInLine --
>  *
>  *	Find textual index of 'byteIndex' in the searchable
>  *	characters of 'linePtr'.
>  *	
>  *	This means we ignore any embedded windows/images and
>  *	elidden text (unless we are searching that).
>  *
>  * Results:
>  *	The returned index is a utf-8 char* byte index for exact
>  *	searches, and a Unicode character index for regexp searches.
>  *
>  * Side effects:
>  *	None.
>  *
>  *----------------------------------------------------------------------
>  */
2143,2149c2286,2316
< 	linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
< 	curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
< 	for (segPtr = linePtr->segPtr; segPtr != NULL;
< 		curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
< 	    if ((segPtr->typePtr != &tkTextCharType)
< 		    || (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
< 		continue;
---
> static int
> SearchIndexInLine(searchSpecPtr, linePtr, byteIndex)
>     CONST TkLineSearchSpec *searchSpecPtr;
>     TkTextLine *linePtr;
>     int byteIndex;
> {
>     TkTextSegment *segPtr;
>     TkTextIndex curIndex;
>     int index, leftToScan;
> 
>     index = 0;
>     curIndex.tree = searchSpecPtr->textPtr->tree;
>     curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
>     for (segPtr = linePtr->segPtr, leftToScan = byteIndex;
> 	 leftToScan > 0; 
> 	 curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
> 	if ((segPtr->typePtr == &tkTextCharType)
> 	    && (searchSpecPtr->searchElide || 
> 		!TkTextIsElided(searchSpecPtr->textPtr, &curIndex))) {
> 	    if (leftToScan < segPtr->size) {
> 		if (searchSpecPtr->exact) {
> 		    index += leftToScan;
> 		} else {
> 		    index += Tcl_NumUtfChars(segPtr->body.chars, leftToScan);
> 		}
> 	    } else {
> 		if (searchSpecPtr->exact) {
> 		    index += segPtr->size;
> 		} else {
> 		    index += Tcl_NumUtfChars(segPtr->body.chars, -1);
> 		}
2151d2317
< 	    Tcl_DStringAppend(&line, segPtr->body.chars, segPtr->size);
2153,2156c2319,2343
< 	if (!exact) {
< 	    Tcl_DStringSetLength(&line, Tcl_DStringLength(&line)-1);
< 	}
< 	startOfLine = Tcl_DStringValue(&line);
---
> 	leftToScan -= segPtr->size;
>     }
>     return index;
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * SearchAddNextLine --
>  *
>  *	Adds a line from the text widget to the object 'theLine'.
>  *
>  * Results:
>  *	A pointer to the TkTextLine corresponding to the given line.
>  *	Also 'lenPtr' (if non-NULL) is filled in with the total length of
>  *	'theLine' (not just what we added to it, but the length including
>  *	what was already in there).  This is in bytes for an exact search
>  *	and in chars for a regexp search.
>  *
>  * Side effects:
>  *	Memory may be allocated or re-allocated for theLine's string
>  *	representation.
>  *
>  *----------------------------------------------------------------------
>  */
2158,2160c2345,2357
< 	/*
< 	 * If we're ignoring case, convert the line to lower case.
< 	 */
---
> static ClientData 
> SearchAddNextLine(lineNum, searchSpecPtr, theLine, lenPtr)
>     int lineNum;
>     TkLineSearchSpec *searchSpecPtr;
>     Tcl_Obj *theLine;
>     int *lenPtr;
> {
>     TkTextLine *linePtr;
>     TkTextIndex curIndex;
>     TkTextSegment *segPtr;
>     /*
>      * Extract the text from the line. 
>      */
2162,2164c2359,2370
< 	if (noCase) {
< 	    Tcl_DStringSetLength(&line,
< 		    Tcl_UtfToLower(Tcl_DStringValue(&line)));
---
>     linePtr = TkBTreeFindLine(searchSpecPtr->textPtr->tree, lineNum);
>     if (linePtr == NULL) {
> 	return NULL;
>     }
>     curIndex.tree = searchSpecPtr->textPtr->tree;
>     curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
>     for (segPtr = linePtr->segPtr; segPtr != NULL;
> 	    curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
> 	if ((segPtr->typePtr != &tkTextCharType)
> 	  || (!searchSpecPtr->searchElide 
> 	      && TkTextIsElided(searchSpecPtr->textPtr, &curIndex))) {
> 	    continue;
2165a2372,2382
> #if 1
> 	/* Workaround Tcl bug 635200. Remove this line as soon as
> 	 * that bug is fixed! */
> 	Tcl_GetString(theLine);
> #endif
> 	Tcl_AppendToObj(theLine, segPtr->body.chars, segPtr->size);
>     }
>     
>     /*
>      * If we're ignoring case, convert the line to lower case.
>      */
2167,2203c2384,2416
< 	/*
< 	 * Check for matches within the current line.  If so, and if we're
< 	 * searching backwards, repeat the search to find the last match
< 	 * in the line.  (Note: The lastByte should include the NULL char
< 	 * so we can handle searching for end of line easier.)
< 	 */
< 
< 	matchByte = -1;
< 	firstByte = 0;
< 	lastByte = Tcl_DStringLength(&line) + 1;
< 	if (lineNum == startingLine) {
< 	    int indexInDString;
< 
< 	    /*
< 	     * The starting line is tricky: the first time we see it
< 	     * we check one part of the line, and the second pass through
< 	     * we check the other part of the line.  We have to be very
< 	     * careful here because there could be embedded windows or
< 	     * other things that are not in the extracted line.  Rescan
< 	     * the original line to compute the index in it of the first
< 	     * character.
< 	     */
< 
< 	    indexInDString = startingByte;
< 	    for (segPtr = linePtr->segPtr, leftToScan = startingByte;
< 		    leftToScan > 0; segPtr = segPtr->nextPtr) {
< 		if (segPtr->typePtr != &tkTextCharType) {
< 		    indexInDString -= segPtr->size;
< 		}
< 		leftToScan -= segPtr->size;
< 	    }
< 
< 	    passes++;
< 	    if ((passes == 1) ^ backwards) {
< 		/*
< 		 * Only use the last part of the line.
< 		 */
---
>     if (searchSpecPtr->noCase) {
> 	Tcl_SetObjLength(theLine, Tcl_UtfToLower(Tcl_GetString(theLine)));
>     }
>     if (lenPtr != NULL) {
>         if (searchSpecPtr->exact) {
> 	    Tcl_GetStringFromObj(theLine, lenPtr);
> 	} else {
> 	    *lenPtr = Tcl_GetCharLength(theLine);
> 	}
>     }
>     return (ClientData)linePtr;
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * SearchFoundMatch --
>  *
>  *	Stores information from a successful search.
>  *
>  * Results:
>  *	1 if the information was stored, 0 if it actually goes beyond
>  *	the allowable search region (and therefore the search is actually
>  *	complete).
>  *
>  * Side effects:
>  *	Memory may be allocated in the 'countPtr' and 'resPtr' fields
>  *	of 'searchSpecPtr'.  Each of those objects will have refCount
>  *	zero and must eventually be freed or stored elsewhere as 
>  *	appropriate.
>  *
>  *----------------------------------------------------------------------
>  */
2205,2213c2418,2435
< 		firstByte = indexInDString;
< 		if ((firstByte >= Tcl_DStringLength(&line))
< 			&& !((Tcl_DStringLength(&line) == 0) && !exact)) {
< 		    goto nextLine;
< 		}
< 	    } else {
< 		/*
< 		 * Use only the first part of the line.
< 		 */
---
> static int 
> SearchFoundMatch(lineNum, searchSpecPtr, clientData, theLine, 
> 		 matchOffset, matchLength)
>     int lineNum;                    /* Line on which match was found */
>     TkLineSearchSpec *searchSpecPtr;/* Search parameters */
>     ClientData clientData;          /* Token returned by SearchAddNextLine */
>     Tcl_Obj *theLine;               /* Text from current line */
>     int matchOffset;                /* Offset of found item in utf-8 bytes
>                                      * for exact search, Unicode chars 
>                                      * for regexp */
>     int matchLength;                /* Length also in bytes/chars as per
>                                      * search type. */
> {
>     int numChars;
>     int leftToScan;
>     TkTextIndex curIndex, foundIndex;
>     TkTextSegment *segPtr;
>     TkTextLine *linePtr;
2215,2216c2437,2445
< 		lastByte = indexInDString;
< 	    }
---
>     if (lineNum == searchSpecPtr->stopLine) {
> 	/* 
> 	 * If the current index is on the wrong side of the stopIndex,
> 	 * then the item we just found is actually outside the acceptable
> 	 * range, and the search is over.
> 	 */
> 	if (searchSpecPtr->backwards ^ 
> 	  (matchOffset >= searchSpecPtr->stopOffset)) {
> 	    return 0;
2218,2220c2447,2452
< 	do {
< 	    int thisLength;
< 	    Tcl_UniChar ch;
---
>     }
>     
>     /*
>      * Calculate the character count, which may need augmenting
>      * if there are embedded windows or elidden text.
>      */
2222,2229c2454,2485
< 	    if (exact) {
< 		p = strstr(startOfLine + firstByte,	/* INTL: Native. */
< 			pattern); 
< 		if (p == NULL) {
< 		    break;
< 		}
< 		i = p - startOfLine;
< 		thisLength = patLength;
---
>     if (searchSpecPtr->exact) {
> 	CONST char *startOfLine = Tcl_GetString(theLine);
> 	numChars = Tcl_NumUtfChars(startOfLine + matchOffset, matchLength);
>     } else {
> 	numChars = matchLength;
>     }
>     
>     /*
>      * The index information returned by the regular expression
>      * parser only considers textual information:  it doesn't
>      * account for embedded windows, elided text (when we are not
>      * searching elided text) or any other non-textual info.
>      * Scan through the line's segments again to adjust both
>      * matchChar and matchCount.
>      *
>      * We will walk through the segments of this line until we
>      * have either reached the end of the match or we have
>      * reached the end of the line.
>      */
> 
>     linePtr = (TkTextLine *)clientData;
>     curIndex.tree = searchSpecPtr->textPtr->tree;
>     curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
>     /* Find the starting point */
>     for (segPtr = linePtr->segPtr, leftToScan = matchOffset;
> 	    leftToScan >= 0 && segPtr; segPtr = segPtr->nextPtr) {
> 	if (segPtr->typePtr != &tkTextCharType) {
> 	    matchOffset += segPtr->size;
> 	} else if (!searchSpecPtr->searchElide 
> 		   && TkTextIsElided(searchSpecPtr->textPtr, &curIndex)) {
> 	    if (searchSpecPtr->exact) {
> 		matchOffset += segPtr->size;
2231,2248c2487
< 		CONST char *start, *end;
< 		int match;
< 
< 		match = Tcl_RegExpExec(interp, regexp,
< 			startOfLine + firstByte, startOfLine);
< 		if (match < 0) {
< 		    code = TCL_ERROR;
< 		    goto done;
< 		}
< 		if (!match) {
< 		    break;
< 		}
< 		Tcl_RegExpRange(regexp, 0, &start, &end);
< 		i = start - startOfLine;
< 		thisLength = end - start;
< 	    }
< 	    if (i >= lastByte) {
< 		break;
---
> 		matchOffset += Tcl_NumUtfChars(segPtr->body.chars, -1);
2250,2281c2489,2524
< 	    matchByte = i;
< 	    matchLength = thisLength;
< 	    firstByte = i + Tcl_UtfToUniChar(startOfLine + matchByte, &ch);
< 	} while (backwards);
< 
< 	/*
< 	 * If we found a match then we're done.  Make sure that
< 	 * the match occurred before the stopping index, if one was
< 	 * specified.
< 	 */
< 
< 	if (matchByte >= 0) {
< 	    int numChars;
< 
< 	    /*
< 	     * Convert the byte length to a character count.
< 	     */
< 
< 	    numChars = Tcl_NumUtfChars(startOfLine + matchByte,
< 		    matchLength);
< 
< 	    /*
< 	     * The index information returned by the regular expression
< 	     * parser only considers textual information:  it doesn't
< 	     * account for embedded windows, elided text (when we are not
< 	     * searching elided text) or any other non-textual info.
< 	     * Scan through the line's segments again to adjust both
< 	     * matchChar and matchCount.
< 	     *
< 	     * We will walk through the segments of this line until we have
< 	     * either reached the end of the match or we have reached the end
< 	     * of the line.
---
> 	} else {
> 	    leftToScan -= segPtr->size;
> 	}
> 	curIndex.byteIndex += segPtr->size;
>     }
>     /* Calculate and store the found index in the result */
>     if (searchSpecPtr->exact) {
> 	TkTextMakeByteIndex(searchSpecPtr->textPtr->tree, lineNum, 
> 			    matchOffset, &foundIndex);
>     } else {
> 	TkTextMakeCharIndex(searchSpecPtr->textPtr->tree, lineNum, 
> 			    matchOffset, &foundIndex);
>     }
>     if (searchSpecPtr->all) {
> 	if (searchSpecPtr->resPtr == NULL) {
> 	    searchSpecPtr->resPtr = Tcl_NewObj();
> 	}
> 	Tcl_ListObjAppendElement(NULL, searchSpecPtr->resPtr, 
> 		TkTextNewIndexObj(searchSpecPtr->textPtr, &foundIndex));
>     } else {
> 	searchSpecPtr->resPtr = 
> 	        TkTextNewIndexObj(searchSpecPtr->textPtr, &foundIndex);
>     }
>     /* 
>      * Find the end point.  Here 'leftToScan' could be negative already
>      * as a result of the above loop if the segment we reached spanned
>      * the start of the string.  When we add matchLength it will become
>      * non-negative.
>      */
>     for (leftToScan += matchLength; leftToScan > 0;
> 	 curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
> 	if (segPtr == NULL) {
> 	    /* 
> 	     * We are on the next line -- this of course should only
> 	     * ever happen with searches which have matched across
> 	     * multiple lines 
2283c2526,2527
< 
---
> 	    linePtr = TkBTreeNextLine(linePtr);
> 	    segPtr = linePtr->segPtr;
2285,2322d2528
< 	    for (segPtr = linePtr->segPtr, leftToScan = matchByte;
< 		    leftToScan >= 0 && segPtr; segPtr = segPtr->nextPtr) {
< 		if (segPtr->typePtr != &tkTextCharType || \
< 			(!searchElide && TkTextIsElided(textPtr, &curIndex))) {
< 		    matchByte += segPtr->size;
< 		} else {
< 		    leftToScan -= segPtr->size;
< 		}
< 		curIndex.byteIndex += segPtr->size;
< 	    }
< 	    for (leftToScan += matchLength; leftToScan > 0;
< 		    segPtr = segPtr->nextPtr) {
< 		if (segPtr->typePtr != &tkTextCharType) {
< 		    numChars += segPtr->size;
< 		    continue;
< 		}
< 		leftToScan -= segPtr->size;
< 	    }
< 	    TkTextMakeByteIndex(textPtr->tree, lineNum, matchByte, &index);
< 	    if (!searchWholeText) {
< 		if (!backwards && (TkTextIndexCmp(&index, &stopIndex) >= 0)) {
< 		    goto done;
< 		}
< 		if (backwards && (TkTextIndexCmp(&index, &stopIndex) < 0)) {
< 		    goto done;
< 		}
< 	    }
< 	    if (varName != NULL) {
< 		sprintf(buffer, "%d", numChars);
< 		if (Tcl_SetVar(interp, varName, buffer, TCL_LEAVE_ERR_MSG)
< 			== NULL) {
< 		    code = TCL_ERROR;
< 		    goto done;
< 		}
< 	    }
< 	    TkTextPrintIndex(&index, buffer);
< 	    Tcl_SetResult(interp, buffer, TCL_VOLATILE);
< 	    goto done;
2324,2338c2530,2540
< 
< 	/*
< 	 * Go to the next (or previous) line;
< 	 */
< 
< 	nextLine:
< 	if (backwards) {
< 	    lineNum--;
< 	    if (!searchWholeText) {
< 		if (lineNum < stopLine) {
< 		    break;
< 		}
< 	    } else if (lineNum < 0) {
< 		lineNum = numLines-1;
< 	    }
---
> 	if (segPtr->typePtr != &tkTextCharType) {
> 	    /* Anything we didn't count in the search needs adding */
> 	    numChars += segPtr->size;
> 	    continue;
> 	} else if (!searchSpecPtr->searchElide 
> 		 && TkTextIsElided(searchSpecPtr->textPtr, &curIndex)) {
> 	    numChars += Tcl_NumUtfChars(segPtr->body.chars, -1);
> 	    continue;
> 	}
> 	if (searchSpecPtr->exact) {
> 	    leftToScan -= segPtr->size;
2340,2347c2542
< 	    lineNum++;
< 	    if (!searchWholeText) {
< 		if (lineNum > stopLine) {
< 		    break;
< 		}
< 	    } else if (lineNum >= numLines) {
< 		lineNum = 0;
< 	    }
---
> 	    leftToScan -= Tcl_NumUtfChars(segPtr->body.chars, -1);
2349,2354d2543
< 	Tcl_DStringSetLength(&line, 0);
<     }
<     done:
<     Tcl_DStringFree(&line);
<     if (noCase && exact) {
< 	Tcl_DStringFree(&patDString);
2356,2357c2545,2557
<     if (patObj != NULL) {
< 	Tcl_DecrRefCount(patObj);
---
>     /* 
>      * Now store the count result, if it is wanted
>      */
>     if (searchSpecPtr->varPtr != NULL) {
> 	Tcl_Obj *tmpPtr = Tcl_NewIntObj(numChars);
> 	if (searchSpecPtr->all) {
> 	    if (searchSpecPtr->countPtr == NULL) {
> 		searchSpecPtr->countPtr = Tcl_NewObj();
> 	    }
> 	    Tcl_ListObjAppendElement(NULL, searchSpecPtr->countPtr, tmpPtr);
> 	} else {
> 	    searchSpecPtr->countPtr = tmpPtr;
> 	}
2359c2559
<     return code;
---
>     return 1;
2384c2584
< TkTextGetTabs(interp, tkwin, string)
---
> TkTextGetTabs(interp, tkwin, stringPtr)
2388,2389c2588,2590
<     char *string;			/* Description of the tab stops.  See
< 					 * the text manual entry for details. */
---
>     Tcl_Obj *stringPtr;			/* Description of the tab stops.  
>                        			 * See the text manual entry for 
>                        			 * details. */
2391,2392c2592,2593
<     int argc, i, count, c;
<     CONST char **argv;
---
>     int objc, i, count;
>     Tcl_Obj **objv;
2397c2598,2604
<     if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
---
>     /* Map these strings to TkTextTabAlign values */
>     
>     static CONST char *tabOptionStrings[] = {
> 	"left", "right", "center", "numeric", (char *) NULL 
>     };
>     
>     if (Tcl_ListObjGetElements(interp, stringPtr, &objc, &objv) != TCL_OK) {
2407,2408c2614,2615
<     for (i = 0; i < argc; i++) {
< 	c = argv[i][0];
---
>     for (i = 0; i < objc; i++) {
> 	char c = Tcl_GetString(objv[i])[0];
2422,2423c2629,2632
<     for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i  < argc; i++, tabPtr++) {
< 	if (Tk_GetPixels(interp, tkwin, argv[i], &tabPtr->location)
---
>     for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i  < objc; i++, tabPtr++) {
> 	int index;
> 	
> 	if (Tk_GetPixelsFromObj(interp, tkwin, objv[i], &tabPtr->location)
2435c2644
< 	if ((i+1) == argc) {
---
> 	if ((i+1) == objc) {
2438c2647,2648
< 	Tcl_UtfToUniChar(argv[i+1], &ch);
---
> 	/* There may be a more efficient way of getting this */
> 	Tcl_UtfToUniChar(Tcl_GetString(objv[i+1]), &ch);
2443,2459c2653,2655
< 	c = argv[i][0];
< 	if ((c == 'l') && (strncmp(argv[i], "left",
< 		strlen(argv[i])) == 0)) {
< 	    tabPtr->alignment = LEFT;
< 	} else if ((c == 'r') && (strncmp(argv[i], "right",
< 		strlen(argv[i])) == 0)) {
< 	    tabPtr->alignment = RIGHT;
< 	} else if ((c == 'c') && (strncmp(argv[i], "center",
< 		strlen(argv[i])) == 0)) {
< 	    tabPtr->alignment = CENTER;
< 	} else if ((c == 'n') && (strncmp(argv[i],
< 		"numeric", strlen(argv[i])) == 0)) {
< 	    tabPtr->alignment = NUMERIC;
< 	} else {
< 	    Tcl_AppendResult(interp, "bad tab alignment \"",
< 		    argv[i], "\": must be left, right, center, or numeric",
< 		    (char *) NULL);
---
> 	
> 	if (Tcl_GetIndexFromObj(interp, objv[i], tabOptionStrings, 
> 				"tab alignment", 0, &index) != TCL_OK) {
2461a2658
> 	tabPtr->alignment = ((TkTextTabAlign)index);
2463d2659
<     ckfree((char *) argv);
2468d2663
<     ckfree((char *) argv);
2492c2687
< TextDumpCmd(textPtr, interp, argc, argv)
---
> TextDumpCmd(textPtr, interp, objc, objv)
2495,2496c2690,2691
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
2498c2693
< 				 * argv[1] is "dump". */
---
> 				 * objv[1] is "dump". */
2515c2710
<     for (arg=2 ; argv[arg] != (char *) NULL ; arg++) {
---
>     for (arg=2 ; objv[arg] != NULL ; arg++) {
2517c2712,2713
< 	if (argv[arg][0] != '-') {
---
> 	char *str = Tcl_GetStringFromObj(objv[arg],&len);
> 	if (str[0] != '-') {
2520,2521c2716
< 	len = strlen(argv[arg]);
< 	if (strncmp("-all", argv[arg], len) == 0) {
---
> 	if (strncmp("-all", str, len) == 0) {
2523c2718
< 	} else if (strncmp("-text", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-text", str, len) == 0) {
2525c2720
< 	} else if (strncmp("-tag", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-tag", str, len) == 0) {
2527c2722
< 	} else if (strncmp("-mark", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-mark", str, len) == 0) {
2529c2724
< 	} else if (strncmp("-image", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-image", str, len) == 0) {
2531c2726
< 	} else if (strncmp("-window", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-window", str, len) == 0) {
2533c2728
< 	} else if (strncmp("-command", argv[arg], len) == 0) {
---
> 	} else if (strncmp("-command", str, len) == 0) {
2535,2536c2730,2732
< 	    if (arg >= argc) {
< 		Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
---
> 	    if (arg >= objc) {
> 		Tcl_AppendResult(interp, "Usage: ", Tcl_GetString(objv[0]), 
> 		" dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
2539c2735
< 	    command = argv[arg];
---
> 	    command = Tcl_GetString(objv[arg]);
2541c2737,2738
< 	    Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
---
> 	    Tcl_AppendResult(interp, "Usage: ", Tcl_GetString(objv[0]), 
> 			     " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
2545,2546c2742,2744
<     if (arg >= argc) {
< 	Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
---
>     if (arg >= objc) {
> 	Tcl_AppendResult(interp, "Usage: ", Tcl_GetString(objv[0]), 
> 			 " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL);
2552c2750
<     if (TkTextGetIndex(interp, textPtr, argv[arg], &index1) != TCL_OK) {
---
>     if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index1) != TCL_OK) {
2558c2756
<     if (argc == arg) {
---
>     if (objc == arg) {
2561c2759
< 	if (TkTextGetIndex(interp, textPtr, argv[arg], &index2) != TCL_OK) {
---
> 	if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) {
2564c2762,2763
< 	if (strncmp(argv[arg], "end", strlen(argv[arg])) == 0) {
---
> 	if (strncmp(Tcl_GetString(objv[arg]), "end", 
> 		  strlen(Tcl_GetString(objv[arg]))) == 0) {
2600a2800,2801
>  *----------------------------------------------------------------------
>  *
2601a2803
>  * 
2609a2812,2813
>  *	
>  *----------------------------------------------------------------------
2697a2902,2903
>  *----------------------------------------------------------------------
>  *
2698a2905
>  * 
2706a2914,2915
>  *	
>  *----------------------------------------------------------------------
2714c2923
<     TkTextIndex *index;         /* index with line/byte position info */
---
>     CONST TkTextIndex *index;   /* index with line/byte position info */
2717c2926
<     char buffer[TCL_INTEGER_SPACE*2];
---
>     char buffer[TK_POS_CHARS];
2739a2949,2950
>  *----------------------------------------------------------------------
>  *
2740a2952
>  * 
2747a2960,2961
>  *    
>  *----------------------------------------------------------------------
2752c2966
<     TkText     * textPtr;          /* Overall information about text widget. */
---
>     TkText     *textPtr;    /* Overall information about text widget. */
2778a2993,2994
>  *----------------------------------------------------------------------
>  *
2779a2996
>  * 
2786a3004,3005
>  *    
>  *----------------------------------------------------------------------
2791c3010
<     TkText     * textPtr;       /* Overall information about text widget. */
---
>     TkText     *textPtr;     /* Overall information about text widget. */
2811a3031,3032
>  *----------------------------------------------------------------------
>  *
2821a3043,3044
>  *    
>  *----------------------------------------------------------------------
2825c3048
< TextEditCmd(textPtr, interp, argc, argv)
---
> TextEditCmd(textPtr, interp, objc, objv)
2828,2829c3051,3052
<     int argc;                 /* Number of arguments. */
<     CONST char **argv;        /* Argument strings. */
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. */
2831,2836c3054,3069
<     int      c, setModified;
<     size_t   length;
< 
<     if (argc < 3) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " edit option ?arg arg ...?\"", (char *) NULL);
---
>     int index;
>     
>     static CONST char *editOptionStrings[] = {
> 	"modified", "redo", "reset", "separator", "undo", (char *) NULL 
>     };
>     enum editOptions {
> 	EDIT_MODIFIED, EDIT_REDO, EDIT_RESET, EDIT_SEPARATOR, EDIT_UNDO
>     };
>     
>     if (objc < 3) {
> 	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
> 	return TCL_ERROR;
>     }
>     
>     if (Tcl_GetIndexFromObj(interp, objv[2], editOptionStrings, 
> 			    "edit option", 0, &index) != TCL_OK) {
2839,2855d3071
<     c = argv[2][0];
<     length = strlen(argv[2]);
<     if ((c == 'm') && (strncmp(argv[2], "modified", length) == 0)) {
< 	if (argc == 3) {
< 	    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(textPtr->isDirty));
< 	} else if (argc != 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " edit modified ?boolean?\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	} else {
< 	    XEvent event;
< 	    if (Tcl_GetBoolean(interp, argv[3], &setModified) != TCL_OK) {
< 		return TCL_ERROR;
<             }
< 	    /*
< 	     * Set or reset the dirty info and trigger a Modified event.
< 	     */
2857,2859c3073,3079
< 	    if (setModified) {
< 		textPtr->isDirty     = 1;
< 		textPtr->modifiedSet = 1;
---
>     switch ((enum editOptions)index) {
> 	case EDIT_MODIFIED: {
> 	    if (objc == 3) {
> 		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(textPtr->isDirty));
> 	    } else if (objc != 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "?boolean?");
> 		return TCL_ERROR;
2861,2863c3081,3089
< 		textPtr->isDirty     = 0;
< 		textPtr->modifiedSet = 0;
< 	    }
---
> 		int setModified;
> 		XEvent event;
> 		if (Tcl_GetBooleanFromObj(interp, objv[3], &setModified) 
> 		  != TCL_OK) {
> 		    return TCL_ERROR;
> 		}
> 		/*
> 		 * Set or reset the dirty info and trigger a Modified event.
> 		 */
2865,2868c3091,3097
< 	    /*
< 	     * Send an event that the text was modified.  This is equivalent to
< 	     * "event generate $textWidget <<Modified>>"
< 	     */
---
> 		if (setModified) {
> 		    textPtr->isDirty     = 1;
> 		    textPtr->modifiedSet = 1;
> 		} else {
> 		    textPtr->isDirty     = 0;
> 		    textPtr->modifiedSet = 0;
> 		}
2870,2884c3099,3113
< 	    memset((VOID *) &event, 0, sizeof(event));
< 	    event.xany.type = VirtualEvent;
< 	    event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
< 	    event.xany.send_event = False;
< 	    event.xany.window = Tk_WindowId(textPtr->tkwin);
< 	    event.xany.display = Tk_Display(textPtr->tkwin);
< 	    ((XVirtualEvent *) &event)->name = Tk_GetUid("Modified");
< 	    Tk_HandleEvent(&event);
<         }
<     } else if ((c == 'r') && (strncmp(argv[2], "redo", length) == 0)
< 	    && (length >= 3)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " edit redo\"", (char *) NULL);
< 	    return TCL_ERROR;
---
> 		/*
> 		 * Send an event that the text was modified.  This is
> 		 * equivalent to "event generate $textWidget <<Modified>>"
> 		 */
> 
> 		memset((VOID *) &event, 0, sizeof(event));
> 		event.xany.type = VirtualEvent;
> 		event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
> 		event.xany.send_event = False;
> 		event.xany.window = Tk_WindowId(textPtr->tkwin);
> 		event.xany.display = Tk_Display(textPtr->tkwin);
> 		((XVirtualEvent *) &event)->name = Tk_GetUid("Modified");
> 		Tk_HandleEvent(&event);
> 	    }
> 	    break;
2886,2895c3115,3124
<         if ( TextEditRedo(textPtr) ) {
<             Tcl_AppendResult(interp, "nothing to redo", (char *) NULL);
< 	    return TCL_ERROR;
<         }
<     } else if ((c == 'r') && (strncmp(argv[2], "reset", length) == 0)
< 	    && (length >= 3)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " edit reset\"", (char *) NULL);
< 	    return TCL_ERROR;
---
> 	case EDIT_REDO: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
> 	    }
> 	    if (TextEditRedo(textPtr)) {
> 		Tcl_AppendResult(interp, "nothing to redo", (char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    break;
2897,2902c3126,3132
<         TkUndoClearStacks(textPtr->undoStack);
<     } else if ((c == 's') && (strncmp(argv[2], "separator", length) == 0)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " edit separator\"", (char *) NULL);
< 	    return TCL_ERROR;
---
> 	case EDIT_RESET: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
> 	    }
> 	    TkUndoClearStacks(textPtr->undoStack);
> 	    break;
2904,2909c3134,3140
<         TkUndoInsertUndoSeparator(textPtr->undoStack);
<     } else if ((c == 'u') && (strncmp(argv[2], "undo", length) == 0)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " edit undo\"", (char *) NULL);
< 	    return TCL_ERROR;
---
> 	case EDIT_SEPARATOR: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
> 	    }
> 	    TkUndoInsertUndoSeparator(textPtr->undoStack);
> 	    break;
2911,2920c3142,3153
<         if ( TextEditUndo(textPtr) ) {
<             Tcl_AppendResult(interp, "nothing to undo",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
<         }
<     } else {
< 	Tcl_AppendResult(interp, "bad edit option \"", argv[2],
< 		"\": must be modified, redo, reset, separator or undo",
< 		(char *) NULL);
< 	return TCL_ERROR;
---
> 	case EDIT_UNDO: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
> 	    }
> 	    if (TextEditUndo(textPtr)) {
> 		Tcl_AppendResult(interp, "nothing to undo",
> 			(char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    break;
> 	}	
2922d3154
<     
2926a3159,3160
>  *----------------------------------------------------------------------
>  *
2927a3162
>  * 
2929c3164,3171
<  *    in the Tcl_DString given.  That DString should be free or uninitialized.
---
>  *    in a string object which is returned with a refCount of zero.
>  *    
>  *    Since the amount of text may potentially be several megabytes (e.g.
>  *    in text editors built on the text widget), efficiency is very
>  *    important.  We may want to investigate the efficiency of the
>  *    Tcl_AppendToObj more carefully (e.g. if we know we are going to be
>  *    appending several thousand lines, we could attempt to pre-allocate
>  *    a larger space).
2932c3174
<  *    None.
---
>  *    Tcl_Obj of string type containing the specified text.
2935c3177,3180
<  *    Memory will be allocated for the DString.  Remember to free it.
---
>  *    Memory will be allocated for the new object.  Remember to free it if
>  *    it isn't going to be stored appropriately.
>  *    
>  *----------------------------------------------------------------------
2938,2942c3183,3186
< static void 
< TextGetText(indexPtr1,indexPtr2, dsPtr)
<     TkTextIndex *indexPtr1;
<     TkTextIndex *indexPtr2;
<     Tcl_DString *dsPtr;
---
> static Tcl_Obj* 
> TextGetText(indexPtr1,indexPtr2)
>     CONST TkTextIndex *indexPtr1;
>     CONST TkTextIndex *indexPtr2;
2945c3189
<     Tcl_DStringInit(dsPtr);
---
>     Tcl_Obj *resultPtr = Tcl_NewObj();
2958,2959c3202,3206
< 		int last2;
< 
---
> 		/* 
> 		 * The last line that was requested must be handled
> 		 * carefully, because we may need to break out of this
> 		 * loop in the middle of the line
> 		 */
2962,2965c3209,3214
< 		}
< 		last2 = indexPtr2->byteIndex - tmpIndex.byteIndex + offset;
< 		if (last2 < last) {
< 		    last = last2;
---
> 		} else {
> 		    int last2;
> 		    last2 = indexPtr2->byteIndex - tmpIndex.byteIndex + offset;
> 		    if (last2 < last) {
> 			last = last2;
> 		    }
2969,2970c3218,3219
< 		Tcl_DStringAppend(dsPtr, segPtr->body.chars + offset,
< 			last - offset);
---
> 		Tcl_AppendToObj(resultPtr, segPtr->body.chars + offset,
> 				last - offset);
2974a3224
>     return resultPtr;
2978,2979c3228,3232
<  * updateDirtyFlag --
<  *    increases the dirtyness of the text widget
---
>  *----------------------------------------------------------------------
>  *
>  * UpdateDirtyFlag --
>  * 
>  *    Increases the dirtyness of the text widget
2985a3239,3240
>  *    
>  *----------------------------------------------------------------------
2988c3243,3244
< static void updateDirtyFlag (textPtr)
---
> static void 
> UpdateDirtyFlag (textPtr)
3013a3270,3705
> }
> 
> /*
>  *----------------------------------------------------------------------
>  *
>  * PerformSearch --
>  *
>  *	The core of the search procedure.  This procedure is actually
>  *	completely indepent of Tk, and could in the future be split
>  *	off, along with one or two other procedures above.
>  *
>  * Results:
>  *	Standard Tcl result code.
>  *
>  * Side effects:
>  *	Only those of 'SearchFoundMatch' which is called whenever a
>  *	match is found.
>  *	
>  *	Note that the way matching across multiple lines is implemented,
>  *	we start afresh with each line we have available, even though we
>  *	may already have examined the contents of that line (and further
>  *	ones) if we were attempting a multi-line match using the previous
>  *	line.  This means there may be ways to speed this up a lot by not
>  *	throwing away all the multi-line information one has accumulated.
>  *	Profiling should be done to see where the bottlenecks lie before
>  *	attempting this, however.
>  *
>  *----------------------------------------------------------------------
>  */
> 
> static int
> PerformSearch(interp, searchSpecPtr, patObj)
>     Tcl_Interp *interp;             /* For error messages */
>     TkLineSearchSpec *searchSpecPtr;/* Search parameters */
>     Tcl_Obj *patObj;                /* Contains an exact string or a
>                                      * regexp pattern.  Must have a 
>                                      * refCount > 0 */
> {
>     int passes;
>     /* 
>      * For exact searches these are utf-8 char* offsets, for regexp
>      * searches they are Unicode char offsets
>      */
>     int firstOffset, lastOffset, matchOffset, matchLength;
>     int lineNum = searchSpecPtr->startLine;
>     int code = TCL_OK;
>     Tcl_Obj *theLine;
>     
>     /* For regexp searches only */
>     Tcl_RegExp regexp = NULL;
>     /* For exact searches only */
>     CONST char *pattern = NULL;
>     int patLength = 0;
>     int firstNewLine;
>     
>     if (searchSpecPtr->exact) {
> 	/*
> 	 * Convert the pattern to lower-case if we're supposed to ignore
> 	 * case.
> 	 */
> 	if (searchSpecPtr->noCase) {
> 	    patObj = Tcl_DuplicateObj(patObj);
> 	    /* 
> 	     * This can change the length of the string behind the
> 	     * object's back, so ensure it is correctly synchronised.
> 	     */
> 	    Tcl_SetObjLength(patObj, Tcl_UtfToLower(Tcl_GetString(patObj)));
> 	}
>     } else {
> 	/* 
> 	 * Compile the regular expression.  We want '^$' to match after and
> 	 * before \n respectively, so use the TCL_REG_NLANCH flag.
> 	 */
> 	regexp = Tcl_GetRegExpFromObj(interp, patObj,
> 		(searchSpecPtr->noCase ? TCL_REG_NOCASE : 0) 
> 	        | TCL_REG_ADVANCED | TCL_REG_CANMATCH
> 		| TCL_REG_NLSTOP| TCL_REG_NLANCH);
> 	if (regexp == NULL) {
> 	    return TCL_ERROR;
> 	}
>     }
> 
>     /* 
>      * For exact strings, we want to know where the first newline is,
>      * and we will also use this as a flag to test whether it is even
>      * possible to match the pattern on a single line.  If not we
>      * will have to search across multiple lines.
>      */
>     if (searchSpecPtr->exact) {
> 	char *nl;
> 	
> 	pattern = Tcl_GetStringFromObj(patObj, &patLength);
> 	nl = strchr(pattern, '\n');
> 	/* 
> 	 * If there is no newline, or it is the very end of the string,
> 	 * then we don't need any special treatment, since single-line
> 	 * matching will work fine.
> 	 */
> 	if (nl == NULL || nl[1] == '\0') {
> 	    firstNewLine = -1;
> 	} else {
> 	    firstNewLine = (nl - pattern);
> 	}
>     } else {
> 	firstNewLine = -1;
>     }
>     
>     /* 
>      * Keep a reference here, so that we can be sure the object
>      * doesn't disappear behind our backs and invalidate its
>      * contents which we are using.
>      */
>     Tcl_IncrRefCount(patObj);
> 
>     /* For building up the current line being checked */
>     theLine = Tcl_NewObj();
>     Tcl_IncrRefCount(theLine);
> 
>     matchLength = 0;   /* Only needed to prevent compiler warnings. */
> 
>     for (passes = 0; passes < 2; ) {
> 	ClientData lineInfo;
> 	int linesSearched = 1;
> 	
> 	if (lineNum >= searchSpecPtr->numLines) {
> 	    /* Don't search the dummy last line of the text. */
> 	    goto nextLine;
> 	}
> 
> 	/*
> 	 * Extract the text from the line, storing its length in
> 	 * 'lastOffset' (in bytes if exact, chars if regexp).
> 	 */
> 
> 	lineInfo = SearchAddNextLine(lineNum, searchSpecPtr, theLine, 
> 				     &lastOffset);
> 
> 	firstOffset = 0;
> 	if (lineNum == searchSpecPtr->startLine) {
> 	    /*
> 	     * The starting line is tricky: the first time we see it
> 	     * we check one part of the line, and the second pass through
> 	     * we check the other part of the line.
> 	     */
> 	    passes++;
> 	    if ((passes == 1) ^ searchSpecPtr->backwards) {
> 		/*
> 		 * Only use the last part of the line.
> 		 */
> 
> 		if ((searchSpecPtr->startOffset >= lastOffset) 
> 		  && ((lastOffset != 0) || searchSpecPtr->exact)) {
> 		    goto nextLine;
> 		}
> 
> 		firstOffset = searchSpecPtr->startOffset;
> 	    } else {
> 		/*
> 		 * Use only the first part of the line.
> 		 */
> 
> 		lastOffset = searchSpecPtr->startOffset -1;
> 	    }
> 	}
> 	
> 	/*
> 	 * Check for matches within the current line.  If so, and if
> 	 * we're searching backwards, repeat the search to find the last
> 	 * match in the line.  (Note: The lastOffset should include the
> 	 * NULL char so we can handle searching for end of line easier.)
> 	 */
> 
> 	matchOffset = -1;
> 	
> 	if (searchSpecPtr->exact) {
> 	    int maxExtraLines = 0;
> 	    CONST char *startOfLine = Tcl_GetString(theLine);
> 	    /* 
> 	     * Only need to set this once for exact searches; it will be
> 	     * ignored if we don't actually find anything
> 	     */
> 	    matchLength = patLength;
> 
> 	    do {
> 		Tcl_UniChar ch;
> 		CONST char *p;
> 		
> 		p = strstr(startOfLine + firstOffset, pattern); 
> 		if (p == NULL) {
> 		    if (firstNewLine == -1) break;
> 		    if (firstNewLine >= (lastOffset - firstOffset)) break;
> 		    p = startOfLine + lastOffset - firstNewLine - 1;
> 		    if (strncmp(p, pattern, firstNewLine + 1)) {
> 			break;
> 		    } else {
> 			int extraLines = 1;
> 			int skipFirst = lastOffset - firstNewLine -1;
> 			/* We may be able to match if given more text */
> 			while (1) {
> 			    int len;
> 			    ClientData clientData;
> 
> 			    if (lineNum + extraLines 
> 			      >= searchSpecPtr->numLines) {
> 				p = NULL;
> 				break;
> 			    }
> 			    
> 			    /* 
> 			     * Only add the line if we haven't already
> 			     * done so already.
> 			     */
> 			    if (extraLines > maxExtraLines) {
> 			        clientData = SearchAddNextLine(
> 				           lineNum + extraLines, 
> 					   searchSpecPtr, theLine, &len);
> 				maxExtraLines = extraLines;
> 				if (clientData == NULL) {
> 				    p = NULL;
> 				    break;
> 				}
> 			    }
> 			    
> 			    startOfLine = Tcl_GetString(theLine);
> 			    p = startOfLine + skipFirst;
> 			    if ((len - skipFirst) >= patLength) {
> 			        /* We now have enough text to match */
> 				if (strncmp(p, pattern, patLength)) {
> 				    p = NULL;
> 				}
> 				break;
> 			    } else {
> 				/* Not enough text yet, but check the prefix */
> 				if (strncmp(p, pattern, (len - skipFirst))) {
> 				    p = NULL;
> 				    break;
> 				}
> 				/* The prefix matches, so keep looking */
> 			    }
> 			    extraLines++;
> 			}
> 			/* 
> 			 * If we reach here, with p != NULL, we've found a 
> 			 * multi-line match, else we started a multi-match
> 			 * but didn't finish it off, so we go to the next line.
> 			 */
> 			if (p == NULL) break;
> 		    }
> 		}
> 		firstOffset = p - startOfLine;
> 		if (firstOffset > lastOffset) {
> 		    break;
> 		}
> 		
> 		/* Remember the match */
> 		matchOffset = firstOffset;
> 		
> 		/* 
> 		 * Move the starting point one character on from the
> 		 * previous match, in case we are doing repeated or
> 		 * backwards searches (for the latter, we actually do
> 		 * repeated forward searches).
> 		 */
> 		firstOffset += Tcl_UtfToUniChar(startOfLine + matchOffset, &ch);
> 		if (searchSpecPtr->all) {
> 		    if (!SearchFoundMatch(lineNum, searchSpecPtr, lineInfo, 
> 					  theLine, matchOffset, matchLength)) {
> 			/* We reached the end of the search */
> 			goto searchDone;
> 		    }
> 		}
> 	    } while (searchSpecPtr->backwards || searchSpecPtr->all);
> 	    
> 	} else {
> 
> 	    int maxExtraLines = 0;
> 
> 	    do {
> 		Tcl_RegExpInfo info;
> 		int match;
> 
> 		match = Tcl_RegExpExecObj(interp, regexp, theLine, 
> 			  firstOffset, 1, 
> 			  ((firstOffset > 0) ? TCL_REG_NOTBOL : 0));
> 		if (match < 0) {
> 		    code = TCL_ERROR;
> 		    goto searchDone;
> 		}
> 		Tcl_RegExpGetInfo(regexp, &info);
> 
> 		if (!match) {
> 		    int extraLines = 1;
> 		    int found = 0;
> 		    int curLen = 0;
> 		    
> 		    if (info.extendStart < 0) { break; }
> 		    
> 		    /* We might be able to match if we had more text */
> 		    
> 		    while (1) {
> 			ClientData clientData;
> 			
> 			/* Move firstOffset to first possible start */
> 			firstOffset += info.extendStart;
> 			if (firstOffset >= lastOffset) {
> 			    /* 
> 			     * We're being told that the only possible
> 			     * new match is starting after the end of
> 			     * the line. But, that is the next line which
> 			     * we will handle when we look at that line.
> 			     */
> 			    if (!searchSpecPtr->backwards 
> 			      && (firstOffset == curLen)) {
> 				linesSearched = extraLines + 1;
> 			    }
> 			    break;
> 			}
> 
> 			if (lineNum + extraLines >= searchSpecPtr->numLines) {
> 			    break;
> 			}
> 			/* Add next line, provided we haven't already done so */
> 			if (extraLines > maxExtraLines) {
> 			    clientData = SearchAddNextLine(lineNum + extraLines, 
> 					    searchSpecPtr, theLine, NULL);
> 			    maxExtraLines = extraLines;
> 			    if (clientData == NULL) {
> 				break;
> 			    }
> 			}
> 			
> 			match = Tcl_RegExpExecObj(interp, regexp, theLine, 
> 				  firstOffset, 1, 
> 				  ((firstOffset > 0) ? TCL_REG_NOTBOL : 0));
> 			if (match < 0) {
> 			    code = TCL_ERROR;
> 			    goto searchDone;
> 			}
> 			Tcl_RegExpGetInfo(regexp, &info);
> 			if (match) {
> 			    /* We found a match! */
> 			    found = 1;
> 			    break;
> 			}
> 			if (info.extendStart < 0) { break; }
> 			/* The prefix matches, so keep looking */
> 			extraLines++;
> 		    }
> 		    /* 
> 		     * If we reach here, with found == 1, we've found a 
> 		     * multi-line match, else we started a multi-match
> 		     * but didn't finish it off, so we go to the next line.
> 		     */
> 		    if (!found) break;
> 		}
> 		
> 		firstOffset += info.matches[0].start;
> 		if (firstOffset >= lastOffset) {
> 		    break;
> 		}
> 		
> 		/* Remember the match */
> 		matchOffset = firstOffset;
> 		matchLength = info.matches[0].end - info.matches[0].start;
> 		
> 		/* 
> 		 * Move the starting point one character on, in case
> 		 * we are doing repeated or backwards searches (for the
> 		 * latter, we actually do repeated forward searches).
> 		 */
> 		firstOffset++;
> 		if (searchSpecPtr->all) {
> 		    if (!SearchFoundMatch(lineNum, searchSpecPtr, lineInfo, 
> 					  theLine, matchOffset, matchLength)) {
> 			/* We reached the end of the search */
> 			goto searchDone;
> 		    }
> 		}
> 	    } while (searchSpecPtr->backwards || searchSpecPtr->all);
> 	    
> 	}
> 	
> 	/*
> 	 * If the 'all' flag is set, we will already have stored all
> 	 * matches, so we just proceed to the next line.
> 	 * 
> 	 * If not, and there is a match we need to store that information
> 	 * and we are done.
> 	 */
> 
> 	if ((matchOffset >= 0) && !searchSpecPtr->all) {
> 	    SearchFoundMatch(lineNum, searchSpecPtr, lineInfo, theLine, 
> 			     matchOffset, matchLength);
> 	    goto searchDone;
> 	}
> 
> 	/*
> 	 * Go to the next (or previous) line;
> 	 */
> 
> 	nextLine:
> 
> 	for (;linesSearched > 0;linesSearched--) {
> 	    /* If we have just completed the stopLine, we are done */
> 	    if (lineNum == searchSpecPtr->stopLine) {
> 		goto searchDone;
> 	    }
> 	    
> 	    if (searchSpecPtr->backwards) {
> 		lineNum--;
> 		if ((searchSpecPtr->stopLine == -1) && (lineNum < 0)) {
> 		    lineNum = searchSpecPtr->numLines-1;
> 		}
> 	    } else {
> 		lineNum++;
> 		if ((searchSpecPtr->stopLine == -1) 
> 		    && (lineNum >= searchSpecPtr->numLines)) {
> 		    lineNum = 0;
> 		}
> 	    }
> 	}
> 	
> #ifndef FIXED_STRINGS
> 	Tcl_DecrRefCount(theLine);
> 	theLine = Tcl_NewObj();
> #else
> 	Tcl_SetObjLength(theLine,0);
> #endif
>     }
>     searchDone:
>     
>     /* Free up the cached line and pattern */
>     Tcl_DecrRefCount(theLine);
>     Tcl_DecrRefCount(patObj);
>     
>     return code;
Index: generic/tkText.h
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkText.h,v
retrieving revision 1.12
diff -r1.12 tkText.h
34c34
<  * file:
---
>  * file.
119a120,121
>     Tk_OptionTable optionTable;	        /* Token representing the 
>                                	         * configuration specifications. */
189a192
>     struct TkText *textPtr;
281,282c284,285
< typedef enum {	TEXT_WRAPMODE_NULL, TEXT_WRAPMODE_NONE,
< 		TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_WORD
---
> typedef enum {	TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE,  
> 		TEXT_WRAPMODE_WORD, TEXT_WRAPMODE_NULL
285,286d287
< EXTERN Tk_CustomOption textWrapModeOption;
< 
314,315d314
<     char *bdString;		/* -borderwidth option string (malloc-ed).
< 				 * NULL means option not specified. */
316a316
>     Tcl_Obj* borderWidthPtr;	/* Width of 3-D border for background. */
374c374
<     char *tabString;		/* -tabs option string (malloc-ed).
---
>     Tcl_Obj *tabStringPtr;	/* -tabs option string.
395a396,397
>     Tk_OptionTable optionTable;	/* Token representing the configuration
> 				 * specifications. */
438c440,442
<  * The following data structure describes a single tab stop.
---
>  * The following data structure describes a single tab stop.  It must be
>  * kept in sync with the 'tabOptionStrings' array in the function
>  * 'TkTextGetTabs'
466a471,479
>  * The following enum is used to define a type for the -state option
>  * of the Text widget.
>  */
> 
> typedef enum {
>     TK_TEXT_STATE_DISABLED, TK_TEXT_STATE_NORMAL
> } TkTextState;
> 
> /*
534c547
<     char *tabOptionString;	/* Value of -tabs option string (malloc'ed). */
---
>     Tcl_Obj *tabOptionPtr; 	/* Value of -tabs option string */
567,568c580,581
<     char *selBdString;		/* Value of -selectborderwidth option, or NULL
< 				 * if not specified (malloc'ed). */
---
>     int selBorderWidth;		/* Width of border around selection. */
>     Tcl_Obj* selBorderWidthPtr;	/* Width of border around selection. */
640a654,662
>     Tk_OptionTable optionTable;	/* Token representing the configuration
> 				 * specifications. */
>     
>     int stateEpoch;	        /* This is incremented each time the widget's
>                    	         * contents change, and means that any cached
>                    	         * TkTextIndex objects are no longer valid. */
>     int refCount;               /* Number of cached TkTextIndex objects 
>                                  * refering to us */
>     
645c667
<     TkUndoRedoStack * undoStack; /* The undo/redo stack */
---
>     TkUndoRedoStack *undoStack; /* The undo/redo stack */
647c669
<     int undo;			/* non zero means the undo/redo behaviour is 
---
>     int undo;			/* Non-zero means the undo/redo behaviour is 
650,651c672,674
<     int maxUndo;		/* The maximum depth of the undo stack expressed
<              * as the maximum number of compound statements */
---
>     int maxUndo;		/* The maximum depth of the undo stack 
>                 		 * expressed as the maximum number of 
>                 		 * compound statements */
653c676
<     int autoSeparators;		/* non zero means the separatorss will be 
---
>     int autoSeparators;		/* Non-zero means the separators will be 
666,667c689
< 				 * incremented every edit action
< 				 */
---
> 				 * incremented every edit action */
669c691
<     TkTextEditMode lastEditMode;	/* Keeps track of what the last edit mode was
---
>     TkTextEditMode lastEditMode;/* Keeps track of what the last edit mode was
784c806
< EXTERN int		TkBTreeCharTagged _ANSI_ARGS_((TkTextIndex *indexPtr,
---
> EXTERN int		TkBTreeCharTagged _ANSI_ARGS_((CONST TkTextIndex *indexPtr,
795c817
< EXTERN TkTextTag **	TkBTreeGetTags _ANSI_ARGS_((TkTextIndex *indexPtr,
---
> EXTERN TkTextTag **	TkBTreeGetTags _ANSI_ARGS_((CONST TkTextIndex *indexPtr,
823c845
< 			    TkTextIndex *indexPtr, int *xPtr, int *yPtr,
---
> 			    CONST TkTextIndex *indexPtr, int *xPtr, int *yPtr,
831c853
< 			    TkTextIndex *indexPtr, int *xPtr, int *yPtr,
---
> 			    CONST TkTextIndex *indexPtr, int *xPtr, int *yPtr,
840a863,867
> EXTERN int		TkTextGetObjIndex _ANSI_ARGS_((Tcl_Interp *interp,
> 			    TkText *textPtr, Tcl_Obj *idxPtr,
> 			    TkTextIndex *indexPtr));
> EXTERN CONST TkTextIndex* TkTextGetIndexFromObj _ANSI_ARGS_((Tcl_Interp *interp,
> 			    TkText *textPtr, Tcl_Obj *objPtr));
842c869
< 			    Tk_Window tkwin, char *string));
---
> 			    Tk_Window tkwin, Tcl_Obj *stringPtr));
870c897
< 			    TkTextIndex *indexPtr));
---
> 			    CONST TkTextIndex *indexPtr));
875c902
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
885c912
< EXTERN void		TkTextPrintIndex _ANSI_ARGS_((
---
> EXTERN int		TkTextPrintIndex _ANSI_ARGS_((
886a914,915
> EXTERN Tcl_Obj*		TkTextNewIndexObj _ANSI_ARGS_((TkText *textPtr,
> 			    CONST TkTextIndex *indexPtr));
894c923
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
896c925
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
905c934
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
907c936
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
911c940
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
915c944
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
917c946,949
< 			    Tcl_Interp *interp, int argc, CONST char **argv));
---
> 			    Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
> /* Use a helper from tkCanvas.c */
> EXTERN CONST char**	GetStringsFromObjs _ANSI_ARGS_((int argc,
> 			    Tcl_Obj *CONST *objv));
Index: generic/tkTextBTree.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextBTree.c,v
retrieving revision 1.6
diff -r1.6 tkTextBTree.c
2226c2226
<     TkTextIndex *indexPtr;		/* Indicates a character position at
---
>     CONST TkTextIndex *indexPtr;	/* Indicates a character position at
2338c2338
<     TkTextIndex *indexPtr;	/* Indicates a particular position in
---
>     CONST TkTextIndex *indexPtr;/* Indicates a particular position in
2455c2455
<     TkTextIndex *indexPtr;	/* The character in the text for which
---
>     CONST TkTextIndex *indexPtr;/* The character in the text for which
Index: generic/tkTextDisp.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextDisp.c,v
retrieving revision 1.13
diff -r1.13 tkTextDisp.c
353c353
< 			    TkTextIndex *indexPtr));
---
> 			    CONST TkTextIndex *indexPtr));
563c563,564
< 	if ((tagPtr->bdString != NULL)
---
> 	if ((tagPtr->borderWidthPtr != NULL) 
> 	        && (Tcl_GetString(tagPtr->borderWidthPtr)[0] != '\0')
639c640
< 	if ((tagPtr->tabString != NULL)
---
> 	if ((tagPtr->tabStringPtr != NULL)
1709c1710
<     if (textPtr->state == TK_STATE_NORMAL) {
---
>     if (textPtr->state == TK_TEXT_STATE_NORMAL) {
3298c3299
< TkTextSeeCmd(textPtr, interp, argc, argv)
---
> TkTextSeeCmd(textPtr, interp, objc, objv)
3301,3302c3302,3303
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
3304c3305
< 				 * argv[1] is "see". */
---
> 				 * objv[1] is "see". */
3312c3313
<     if (argc != 3) {
---
>     if (objc != 3) {
3314c3315
< 		argv[0], " see index\"", (char *) NULL);
---
> 		Tcl_GetString(objv[0]), " see index\"", (char *) NULL);
3317c3318
<     if (TkTextGetIndex(interp, textPtr, argv[2], &index) != TCL_OK) {
---
>     if (TkTextGetObjIndex(interp, textPtr, objv[2], &index) != TCL_OK) {
3366,3367c3367,3369
<     if (chunkPtr!=NULL) {       /* chunkPtr==NULL iff trying to see in elided region */
<     (*chunkPtr->bboxProc)(chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove,
---
>     if (chunkPtr != NULL) {       
> 	/* chunkPtr==NULL iff trying to see in elided region */
> 	(*chunkPtr->bboxProc)(chunkPtr, byteCount, dlPtr->y + dlPtr->spaceAbove,
3371,3383c3373,3376
<     delta = x - dInfoPtr->curPixelOffset;
<     oneThird = lineWidth/3;
<     if (delta < 0) {
< 	if (delta < -oneThird) {
< 	    dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth;
< 	} else {
< 	    dInfoPtr->newByteOffset -= ((-delta) + textPtr->charWidth - 1)
< 		/ textPtr->charWidth;
< 	}
<     } else {
< 	delta -= (lineWidth - width);
< 	if (delta > 0) {
< 	    if (delta > oneThird) {
---
> 	delta = x - dInfoPtr->curPixelOffset;
> 	oneThird = lineWidth/3;
> 	if (delta < 0) {
> 	    if (delta < -oneThird) {
3386c3379
< 		dInfoPtr->newByteOffset += (delta + textPtr->charWidth - 1)
---
> 		dInfoPtr->newByteOffset -= ((-delta) + textPtr->charWidth - 1)
3390c3383,3393
< 	    return TCL_OK;
---
> 	    delta -= (lineWidth - width);
> 	    if (delta > 0) {
> 		if (delta > oneThird) {
> 		    dInfoPtr->newByteOffset = (x - lineWidth/2)/textPtr->charWidth;
> 		} else {
> 		    dInfoPtr->newByteOffset += (delta + textPtr->charWidth - 1)
> 			/ textPtr->charWidth;
> 		}
> 	    } else {
> 		return TCL_OK;
> 	    }
3392c3395
<     }}
---
>     }
3420c3423
< TkTextXviewCmd(textPtr, interp, argc, argv)
---
> TkTextXviewCmd(textPtr, interp, objc, objv)
3423,3424c3426,3427
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
3426c3429
< 				 * argv[1] is "xview". */
---
> 				 * objv[1] is "xview". */
3436c3439
<     if (argc == 2) {
---
>     if (objc == 2) {
3442c3445
<     type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
---
>     type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);
3608c3611
< TkTextYviewCmd(textPtr, interp, argc, argv)
---
> TkTextYviewCmd(textPtr, interp, objc, objv)
3611,3612c3614,3615
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
3614c3617
< 				 * argv[1] is "yview". */
---
> 				 * objv[1] is "yview". */
3630c3633
<     if (argc == 2) {
---
>     if (objc == 2) {
3640,3641c3643,3644
<     if (argv[2][0] == '-') {
< 	switchLength = strlen(argv[2]);
---
>     if (Tcl_GetString(objv[2])[0] == '-') {
> 	switchLength = strlen(Tcl_GetString(objv[2]));
3643c3646
< 		&& (strncmp(argv[2], "-pickplace", switchLength) == 0)) {
---
> 		&& (strncmp(Tcl_GetString(objv[2]), "-pickplace", switchLength) == 0)) {
3645c3648
< 	    if (argc != 4) {
---
> 	    if (objc != 4) {
3647c3650,3651
< 			argv[0], " yview -pickplace lineNum|index\"",
---
> 				 Tcl_GetString(objv[0]), 
> 				 " yview -pickplace lineNum|index\"",
3653,3654c3657,3658
<     if ((argc == 3) || pickPlace) {
< 	if (Tcl_GetInt(interp, argv[2+pickPlace], &lineNum) == TCL_OK) {
---
>     if ((objc == 3) || pickPlace) {
> 	if (Tcl_GetIntFromObj(interp, objv[2+pickPlace], &lineNum) == TCL_OK) {
3665c3669
< 	if (TkTextGetIndex(interp, textPtr, argv[2+pickPlace],
---
> 	if (TkTextGetObjIndex(interp, textPtr, objv[2+pickPlace],
3674c3678
<      * New syntax: dispatch based on argv[2].
---
>      * New syntax: dispatch based on objv[2].
3677c3681
<     type = Tk_GetScrollInfo(interp, argc, argv, &fraction, &count);
---
>     type = Tk_GetScrollInfoObj(interp, objc, objv, &fraction, &count);
3774c3778
< TkTextScanCmd(textPtr, interp, argc, argv)
---
> TkTextScanCmd(textPtr, interp, objc, objv)
3777,3778c3781,3782
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
3780c3784
< 				 * argv[1] is "scan". */
---
> 				 * objv[1] is "scan". */
3788c3792
<     if ((argc != 5) && (argc != 6)) {
---
>     if ((objc != 5) && (objc != 6)) {
3790,3791c3794,3795
< 		argv[0], " scan mark x y\" or \"",
< 		argv[0], " scan dragto x y ?gain?\"", (char *) NULL);
---
> 			 Tcl_GetString(objv[0]), " scan mark x y\" or \"",
> 			 Tcl_GetString(objv[0]), " scan dragto x y ?gain?\"", (char *) NULL);
3794c3798
<     if (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) {
---
>     if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
3797c3801
<     if (Tcl_GetInt(interp, argv[4], &y) != TCL_OK) {
---
>     if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
3800c3804
<     if ((argc == 6) && (Tcl_GetInt(interp, argv[5], &gain) != TCL_OK))
---
>     if ((objc == 6) && (Tcl_GetIntFromObj(interp, objv[5], &gain) != TCL_OK))
3802,3804c3806,3808
<     c = argv[2][0];
<     length = strlen(argv[2]);
<     if ((c == 'd') && (strncmp(argv[2], "dragto", length) == 0)) {
---
>     c = Tcl_GetString(objv[2])[0];
>     length = strlen(Tcl_GetString(objv[2]));
>     if ((c == 'd') && (strncmp(Tcl_GetString(objv[2]), "dragto", length) == 0)) {
3844c3848
<     } else if ((c == 'm') && (strncmp(argv[2], "mark", length) == 0)) {
---
>     } else if ((c == 'm') && (strncmp(Tcl_GetString(objv[2]), "mark", length) == 0)) {
3850c3854
< 	Tcl_AppendResult(interp, "bad scan option \"", argv[2],
---
> 	Tcl_AppendResult(interp, "bad scan option \"", Tcl_GetString(objv[2]),
4043c4047
<     TkTextIndex *indexPtr;	/* Index of desired character. */
---
>     CONST TkTextIndex *indexPtr;/* Index of desired character. */
4221c4225
<     TkTextIndex *indexPtr;	/* Index of character whose bounding
---
>     CONST TkTextIndex *indexPtr;/* Index of character whose bounding
4330c4334
<     TkTextIndex *indexPtr;	/* Index of character whose bounding
---
>     CONST TkTextIndex *indexPtr;/* Index of character whose bounding
Index: generic/tkTextImage.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextImage.c,v
retrieving revision 1.5
diff -r1.5 tkTextImage.c
55c55
< 			    TkTextSegment *eiPtr, int argc, CONST char **argv));
---
> 			    TkTextSegment *eiPtr, int objc, Tcl_Obj *CONST objv[]));
131c131
< TkTextImageCmd(textPtr, interp, argc, argv)
---
> TkTextImageCmd(textPtr, interp, objc, objv)
134,135c134,135
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
137c137
< 				 * argv[1] is "image". */
---
> 				 * objv[1] is "image". */
141,144c141,144
< 
<     if (argc < 3) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " image option ?arg arg ...?\"", (char *) NULL);
---
>     CONST char *str;
>     
>     if (objc < 3) {
> 	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
147,148c147,148
<     length = strlen(argv[2]);
<     if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
---
>     str = Tcl_GetStringFromObj(objv[2],&length);
>     if ((strncmp(str, "cget", length) == 0) && (length >= 2)) {
152,155c152,153
< 	if (argc != 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " image cget index option\"",
< 		    (char *) NULL);
---
> 	if (objc != 5) {
> 	    Tcl_WrongNumArgs(interp, 3, objv, "index option");
158c156
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
---
> 	if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
164c162
< 		    argv[3], "\"", (char *) NULL);
---
> 			     Tcl_GetString(objv[3]), "\"", (char *) NULL);
168,169c166,167
< 		(char *) &eiPtr->body.ei, argv[4], 0);
<     } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
---
> 		(char *) &eiPtr->body.ei, Tcl_GetString(objv[4]), 0);
>     } else if ((strncmp(str, "configure", length) == 0) && (length >= 2)) {
173,176c171,172
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " image configure index ?option value ...?\"",
< 		    (char *) NULL);
---
> 	if (objc < 4) {
> 	    Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
179c175
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
---
> 	if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
185c181
< 		    argv[3], "\"", (char *) NULL);
---
> 			     Tcl_GetString(objv[3]), "\"", (char *) NULL);
188c184
< 	if (argc == 4) {
---
> 	if (objc == 4) {
191c187
< 	} else if (argc == 5) {
---
> 	} else if (objc == 5) {
193c189
< 		    (char *) &eiPtr->body.ei, argv[4], 0);
---
> 		    (char *) &eiPtr->body.ei, Tcl_GetString(objv[4]), 0);
196c192
< 	    return EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4);
---
> 	    return EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4);
198c194
<     } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
---
>     } else if ((strncmp(str, "create", length) == 0) && (length >= 2)) {
207,210c203,204
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " image create index ?option value ...?\"",
< 		    (char *) NULL);
---
> 	if (objc < 4) {
> 	    Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
213c207
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
---
> 	if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
251c245
< 	if (EmbImageConfigure(textPtr, eiPtr, argc-4, argv+4) != TCL_OK) {
---
> 	if (EmbImageConfigure(textPtr, eiPtr, objc-4, objv+4) != TCL_OK) {
258c252
<     } else if (strncmp(argv[2], "names", length) == 0) {
---
>     } else if (strncmp(str, "names", length) == 0) {
262,264c256,257
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " image names\"", (char *) NULL);
---
> 	if (objc != 3) {
> 	    Tcl_WrongNumArgs(interp, 3, objv, NULL);
273c266
< 	Tcl_AppendResult(interp, "bad image option \"", argv[2],
---
> 	Tcl_AppendResult(interp, "bad image option \"", str,
287c280
<  *	for an embedded image, using an argc/argv list.
---
>  *	for an embedded image, using an objc/objv list.
301c294
< EmbImageConfigure(textPtr, eiPtr, argc, argv)
---
> EmbImageConfigure(textPtr, eiPtr, objc, objv)
305,306c298,299
<     int argc;			/* Number of strings in argv. */
<     CONST char **argv;		/* Array of strings describing configuration
---
>     int objc;			/* Number of strings in objv. */
>     Tcl_Obj *CONST objv[];	/* Array of strings describing configuration
318c311,313
< 
---
>     CONST char **argv;
>    
>     argv = GetStringsFromObjs(objc, objv);
320c315
< 	    argc, argv, (char *) &eiPtr->body.ei,TK_CONFIG_ARGV_ONLY)
---
> 	    objc, argv, (char *) &eiPtr->body.ei,TK_CONFIG_ARGV_ONLY)
321a317
> 	if (argv) ckfree((char *) argv);
323a320
>     if (argv) ckfree((char *) argv);
Index: generic/tkTextIndex.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextIndex.c,v
retrieving revision 1.6
diff -r1.6 tkTextIndex.c
34a35,272
> static int		GetIndex _ANSI_ARGS_((Tcl_Interp *interp,
> 			    TkText *textPtr, CONST char *string,
> 			    TkTextIndex *indexPtr, int *canCachePtr));
> 
> 
> static void		DupTextIndexInternalRep _ANSI_ARGS_((Tcl_Obj *srcPtr,
> 			    Tcl_Obj *copyPtr));
> static void		FreeTextIndexInternalRep _ANSI_ARGS_((Tcl_Obj *listPtr));
> static int		SetTextIndexFromAny _ANSI_ARGS_((Tcl_Interp *interp,
> 			    Tcl_Obj *objPtr));
> static void		UpdateStringOfTextIndex _ANSI_ARGS_((Tcl_Obj *objPtr));
> 
> #define GET_TEXTINDEX(objPtr) \
> 		((TkTextIndex *) (objPtr)->internalRep.twoPtrValue.ptr1)
> #define GET_INDEXEPOCH(objPtr) \
> 		((int) (objPtr)->internalRep.twoPtrValue.ptr2)
> #define SET_TEXTINDEX(objPtr, indexPtr) \
> 		(objPtr)->internalRep.twoPtrValue.ptr1 = (VOID*) (indexPtr)
> #define SET_INDEXEPOCH(objPtr, epoch) \
> 		(objPtr)->internalRep.twoPtrValue.ptr2 = (VOID*) (epoch)
> /*
>  * Define the 'textindex' object type, which Tk uses to represent
>  * indices in text widgets internally.
>  */
> Tcl_ObjType tclTextIndexType = {
>     "textindex",			/* name */
>     FreeTextIndexInternalRep,		/* freeIntRepProc */
>     DupTextIndexInternalRep,	        /* dupIntRepProc */
>     NULL,                               /* updateStringProc */
>     SetTextIndexFromAny		        /* setFromAnyProc */
> };
> 
> static void
> FreeTextIndexInternalRep(indexObjPtr)
>     Tcl_Obj *indexObjPtr;   /* TextIndex object with internal rep to free. */
> {
>     TkTextIndex *indexPtr = GET_TEXTINDEX(indexObjPtr);
>     if (indexPtr->textPtr != NULL) {
>         if (--indexPtr->textPtr->refCount == 0) {
> 	    /* The text widget has been deleted and we need to free it now */
> 	    ckfree((char *) (indexPtr->textPtr));
> 	}
>     }
>     ckfree((char*)indexPtr);
> }
> 
> static void
> DupTextIndexInternalRep(srcPtr, copyPtr)
>     Tcl_Obj *srcPtr;		/* TextIndex obj with internal rep to copy. */
>     Tcl_Obj *copyPtr;		/* TextIndex obj with internal rep to set. */
> {
>     int epoch;
>     TkTextIndex *dupIndexPtr, *indexPtr;
>     dupIndexPtr = (TkTextIndex*) ckalloc(sizeof(TkTextIndex));
>     indexPtr = GET_TEXTINDEX(srcPtr);
>     epoch = GET_INDEXEPOCH(srcPtr);
>     
>     dupIndexPtr->tree = indexPtr->tree;
>     dupIndexPtr->linePtr = indexPtr->linePtr;
>     dupIndexPtr->byteIndex = indexPtr->byteIndex;
>     
>     SET_TEXTINDEX(copyPtr, dupIndexPtr);
>     SET_INDEXEPOCH(copyPtr, epoch);
> }
> 
> /* 
>  * This will not be called except by TkTextNewIndexObj below.
>  * This is because if a TkTextIndex is no longer valid, it is
>  * not possible to regenerate the string representation.
>  */
> static void
> UpdateStringOfTextIndex(objPtr)
>     Tcl_Obj *objPtr;
> {
>     char buffer[TK_POS_CHARS];
>     register int len;
> 
>     CONST TkTextIndex *indexPtr = GET_TEXTINDEX(objPtr);
> 
>     len = TkTextPrintIndex(indexPtr, buffer);
> 
>     objPtr->bytes = ckalloc((unsigned) len + 1);
>     strcpy(objPtr->bytes, buffer);
>     objPtr->length = len;
> }
>     
> static int
> SetTextIndexFromAny(interp, objPtr)
>     Tcl_Interp *interp;		/* Used for error reporting if not NULL. */
>     Tcl_Obj *objPtr;		/* The object to convert. */
> {
>     Tcl_AppendToObj(Tcl_GetObjResult(interp),
> 	"can't convert value to textindex except via TkTextGetIndexFromObj API",
> 	-1);
>     return TCL_ERROR;
> }
> 
> /*
>  *---------------------------------------------------------------------------
>  *
>  * MakeObjIndex --
>  *	
>  *	This procedure generates a Tcl_Obj description of an index,
>  *	suitable for reading in again later.  If the 'textPtr' is NULL
>  *	then we still generate an index object, but it's internal
>  *	description is deemed non-cacheable, and therefore effectively
>  *	useless (apart from as a temporary memory storage).  This is used
>  *	for indices whose meaning is very temporary (like @0,0 or the
>  *	name of a mark or tag).  The mapping from such strings/objects to
>  *	actual TkTextIndex pointers is not stable to minor text widget
>  *	changes which we do not track (we track insertions/deletions).
>  *
>  * Results:
>  *	A pointer to an allocated TkTextIndex which will be freed 
>  *	automatically when the Tcl_Obj is used for other purposes.
>  *
>  * Side effects:
>  *	A small amount of memory is allocated.
>  *
>  *---------------------------------------------------------------------------
>  */
> static TkTextIndex*
> MakeObjIndex(textPtr, objPtr, origPtr) 
>     TkText *textPtr;		/* Information about text widget. */
>     Tcl_Obj *objPtr;		/* Object containing description of position. */
>     CONST TkTextIndex *origPtr; /* Pointer to index. */
> {
>     TkTextIndex *indexPtr = (TkTextIndex*) ckalloc(sizeof(TkTextIndex));
> 
>     indexPtr->tree = origPtr->tree;
>     indexPtr->linePtr = origPtr->linePtr;
>     indexPtr->byteIndex = origPtr->byteIndex;
>     SET_TEXTINDEX(objPtr, indexPtr);
>     objPtr->typePtr = &tclTextIndexType;
>     indexPtr->textPtr = textPtr;
> 
>     if (textPtr != NULL) {
> 	textPtr->refCount++;
> 	SET_INDEXEPOCH(objPtr, textPtr->stateEpoch);
>     } else {
> 	SET_INDEXEPOCH(objPtr, 0);
>     }
>     return indexPtr;
> }
> 
> CONST TkTextIndex*
> TkTextGetIndexFromObj(interp, textPtr, objPtr)
>     Tcl_Interp *interp;		/* Use this for error reporting. */
>     TkText *textPtr;		/* Information about text widget. */
>     Tcl_Obj *objPtr;		/* Object containing description of position. */
> {
>     TkTextIndex index;
>     TkTextIndex *indexPtr = NULL;
>     int cache;
>     
>     if (objPtr->typePtr == &tclTextIndexType) {
> 	int epoch;
> 	
> 	indexPtr = GET_TEXTINDEX(objPtr);
> 	epoch = GET_INDEXEPOCH(objPtr);
> 	
> 	if (epoch == textPtr->stateEpoch) {
> 	    if (indexPtr->textPtr == textPtr) {
> 		return indexPtr;
> 	    }
> 	}
>     }
> 
>     /* 
>      * The object is either not an index type or referred to a different
>      * text widget, or referred to the correct widget, but it is out of
>      * date (text has been added/deleted since).
>      */
>     
>     if (GetIndex(interp, textPtr, Tcl_GetString(objPtr), 
> 		 &index, &cache) != TCL_OK) {
> 	return NULL;
>     }
>     
>     if (objPtr->typePtr != NULL) {
> 	if (objPtr->bytes == NULL) {
> 	    objPtr->typePtr->updateStringProc(objPtr);
> 	}
> 	if ((objPtr->typePtr->freeIntRepProc) != NULL) {
> 	    (*objPtr->typePtr->freeIntRepProc)(objPtr);
> 	}
>     }
>     
>     if (cache) {
> 	return MakeObjIndex(textPtr, objPtr, &index);
>     } else {
> 	return MakeObjIndex(NULL, objPtr, &index);
>     }
> }
> 
> /*
>  *---------------------------------------------------------------------------
>  *
>  * TkTextNewIndexObj --
>  *	
>  *	This procedure generates a Tcl_Obj description of an index,
>  *	suitable for reading in again later.  The index generated is
>  *	effectively stable to all except insertion/deletion operations on
>  *	the widget.
>  *
>  * Results:
>  *	A new Tcl_Obj with refCount zero.
>  *
>  * Side effects:
>  *	A small amount of memory is allocated.
>  *
>  *---------------------------------------------------------------------------
>  */
> 
> Tcl_Obj*
> TkTextNewIndexObj(textPtr, indexPtr)
>     TkText *textPtr;             /* text widget for this index */
>     CONST TkTextIndex *indexPtr; /* Pointer to index. */
> {
>     Tcl_Obj *retVal;
> 
>     retVal = Tcl_NewObj();
>     retVal->bytes = NULL;
> 
>     /* 
>      * Assumption that the above call returns an object with
>      * retVal->typePtr == NULL
>      */
>     MakeObjIndex(textPtr, retVal, indexPtr);
>     
>     /* 
>      * Unfortunately, it isn't possible for us to regenerate the
>      * string representation so we have to create it here, while we
>      * can be sure the contents of the index are still valid.
>      */
>     UpdateStringOfTextIndex(retVal);
>     return retVal;
> }
296a535,562
>  * TkTextGetObjIndex --
>  * 
>  *    Simpler wrapper around the string based function, but could be
>  *    enhanced with a new object type in the future.
>  *
>  * Results:
>  *    see TkTextGetIndex
>  *
>  * Side effects:
>  *    None.
>  *    
>  *---------------------------------------------------------------------------
>  */
> 
> int
> TkTextGetObjIndex(interp, textPtr, idxObj, indexPtr)
>     Tcl_Interp *interp;		/* Use this for error reporting. */
>     TkText *textPtr;		/* Information about text widget. */
>     Tcl_Obj *idxObj;	        /* Object containing textual description 
> 				 * of position. */
>     TkTextIndex *indexPtr;	/* Index structure to fill in. */
> {
>     return GetIndex(interp, textPtr, Tcl_GetString(idxObj), indexPtr, NULL);
> }
> 
> /*
>  *---------------------------------------------------------------------------
>  *
319a586,620
>     return GetIndex(interp, textPtr, string, indexPtr, NULL);
> }
> 
> /*
>  *---------------------------------------------------------------------------
>  *
>  * GetIndex --
>  *
>  *	Given a string, return the index that is described.
>  *
>  * Results:
>  *	The return value is a standard Tcl return result.  If TCL_OK is
>  *	returned, then everything went well and the index at *indexPtr is
>  *	filled in; otherwise TCL_ERROR is returned and an error message
>  *	is left in the interp's result.
>  *	
>  *	If *canCachePtr is non-NULL, and everything went well, the
>  *	integer it points to is set to 1 if the indexPtr is something
>  *	which can be cached, and zero otherwise.
>  *
>  * Side effects:
>  *	None.
>  *
>  *---------------------------------------------------------------------------
>  */
> 
> static int
> GetIndex(interp, textPtr, string, indexPtr, canCachePtr)
>     Tcl_Interp *interp;		/* Use this for error reporting. */
>     TkText *textPtr;		/* Information about text widget. */
>     CONST char *string;		/* Textual description of position. */
>     TkTextIndex *indexPtr;	/* Index structure to fill in. */
>     int *canCachePtr;           /* Pointer to integer to store whether
>                                  * we can cache the index (or NULL) */
> {
329c630,631
< 
---
>     int canCache = 0;
>     
445a748
> 	canCache = 1;
476a780
> 	canCache = 1;
534a839,841
>     if (canCachePtr != NULL) {
> 	*canCachePtr = canCache;
>     }
554c861,862
<  *	The characters pointed to by string are modified.
---
>  *	The characters pointed to by string are modified.  Returns the
>  *	number of characters in the string.
562c870
< void
---
> int
589c897
<     sprintf(string, "%d.%d", TkBTreeLineIndex(indexPtr->linePtr) + 1,
---
>     return sprintf(string, "%d.%d", TkBTreeLineIndex(indexPtr->linePtr) + 1,
Index: generic/tkTextMark.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextMark.c,v
retrieving revision 1.6
diff -r1.6 tkTextMark.c
98c98
< TkTextMarkCmd(textPtr, interp, argc, argv)
---
> TkTextMarkCmd(textPtr, interp, objc, objv)
101,102c101,102
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
104c104
< 				 * argv[1] is "mark". */
---
> 				 * objv[1] is "mark". */
106,107d105
<     int c, i;
<     size_t length;
114,116c112,128
<     if (argc < 3) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " mark option ?arg arg ...?\"", (char *) NULL);
---
>     int optionIndex;
>     
>     static CONST char *markOptionStrings[] = {
> 	"gravity", "names", "next", "previous", "set", 
> 	"unset", (char *) NULL 
>     };
>     enum markOptions {
> 	MARK_GRAVITY, MARK_NAMES, MARK_NEXT, MARK_PREVIOUS, 
> 	MARK_SET, MARK_UNSET
>     };
> 
>     if (objc < 3) {
> 	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
> 	return TCL_ERROR;
>     }
>     if (Tcl_GetIndexFromObj(interp, objv[2], markOptionStrings, 
> 			    "mark option", 0, &optionIndex) != TCL_OK) {
119,137c131,162
<     c = argv[2][0];
<     length = strlen(argv[2]);
<     if ((c == 'g') && (strncmp(argv[2], "gravity", length) == 0)) {
< 	if (argc < 4 || argc > 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " mark gravity markName ?gravity?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	hPtr = Tcl_FindHashEntry(&textPtr->markTable, argv[3]);
< 	if (hPtr == NULL) {
< 	    Tcl_AppendResult(interp, "there is no mark named \"",
< 		    argv[3], "\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
< 	if (argc == 4) {
< 	    if (markPtr->typePtr == &tkTextRightMarkType) {
< 		Tcl_SetResult(interp, "right", TCL_STATIC);
---
> 
>     switch ((enum markOptions)optionIndex) {
> 	case MARK_GRAVITY: {
> 	    char c;
> 	    size_t length;
> 	    char *str;
> 	    
> 	    if (objc < 4 || objc > 5) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?");
> 		return TCL_ERROR;
> 	    }
> 	    hPtr = Tcl_FindHashEntry(&textPtr->markTable, Tcl_GetString(objv[3]));
> 	    if (hPtr == NULL) {
> 		Tcl_AppendResult(interp, "there is no mark named \"",
> 				 Tcl_GetString(objv[3]), "\"", (char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
> 	    if (objc == 4) {
> 		if (markPtr->typePtr == &tkTextRightMarkType) {
> 		    Tcl_SetResult(interp, "right", TCL_STATIC);
> 		} else {
> 		    Tcl_SetResult(interp, "left", TCL_STATIC);
> 		}
> 		return TCL_OK;
> 	    }
> 	    str = Tcl_GetStringFromObj(objv[4],&length);
> 	    c = str[0];
> 	    if ((c == 'l') && (strncmp(str, "left", length) == 0)) {
> 		newTypePtr = &tkTextLeftMarkType;
> 	    } else if ((c == 'r') && (strncmp(str, "right", length) == 0)) {
> 		newTypePtr = &tkTextRightMarkType;
139c164,178
< 		Tcl_SetResult(interp, "left", TCL_STATIC);
---
> 		Tcl_AppendResult(interp, "bad mark gravity \"", str, 
> 				 "\": must be left or right", (char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    TkTextMarkSegToIndex(textPtr, markPtr, &index);
> 	    TkBTreeUnlinkSegment(textPtr->tree, markPtr,
> 		    markPtr->body.mark.linePtr);
> 	    markPtr->typePtr = newTypePtr;
> 	    TkBTreeLinkSegment(markPtr, &index);
> 	    break;
> 	}
> 	case MARK_NAMES: {
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
140a180,209
> 	    for (hPtr = Tcl_FirstHashEntry(&textPtr->markTable, &search);
> 		    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
> 		Tcl_AppendElement(interp,
> 			Tcl_GetHashKey(&textPtr->markTable, hPtr));
> 	    }
> 	    break;
> 	}
> 	case MARK_NEXT: {
> 	    if (objc != 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "index");
> 		return TCL_ERROR;
> 	    }
> 	    return MarkFindNext(interp, textPtr, Tcl_GetString(objv[3]));
> 	}
> 	case MARK_PREVIOUS: {
> 	    if (objc != 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "index");
> 		return TCL_ERROR;
> 	    }
> 	    return MarkFindPrev(interp, textPtr, Tcl_GetString(objv[3]));
> 	}
> 	case MARK_SET: {
> 	    if (objc != 5) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "markName index");
> 		return TCL_ERROR;
> 	    }
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[4], &index) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
> 	    TkTextSetMark(textPtr, Tcl_GetString(objv[3]), &index);
143,201c212,225
< 	length = strlen(argv[4]);
< 	c = argv[4][0];
< 	if ((c == 'l') && (strncmp(argv[4], "left", length) == 0)) {
< 	    newTypePtr = &tkTextLeftMarkType;
< 	} else if ((c == 'r') && (strncmp(argv[4], "right", length) == 0)) {
< 	    newTypePtr = &tkTextRightMarkType;
< 	} else {
< 	    Tcl_AppendResult(interp, "bad mark gravity \"",
< 		    argv[4], "\": must be left or right", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	TkTextMarkSegToIndex(textPtr, markPtr, &index);
< 	TkBTreeUnlinkSegment(textPtr->tree, markPtr,
< 		markPtr->body.mark.linePtr);
< 	markPtr->typePtr = newTypePtr;
< 	TkBTreeLinkSegment(markPtr, &index);
<     } else if ((c == 'n') && (strncmp(argv[2], "names", length) == 0)) {
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " mark names\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	for (hPtr = Tcl_FirstHashEntry(&textPtr->markTable, &search);
< 		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
< 	    Tcl_AppendElement(interp,
< 		    Tcl_GetHashKey(&textPtr->markTable, hPtr));
< 	}
<     } else if ((c == 'n') && (strncmp(argv[2], "next", length) == 0)) {
< 	if (argc != 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " mark next index\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	return MarkFindNext(interp, textPtr, argv[3]);
<     } else if ((c == 'p') && (strncmp(argv[2], "previous", length) == 0)) {
< 	if (argc != 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " mark previous index\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	return MarkFindPrev(interp, textPtr, argv[3]);
<     } else if ((c == 's') && (strncmp(argv[2], "set", length) == 0)) {
< 	if (argc != 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " mark set markName index\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[4], &index) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 	TkTextSetMark(textPtr, argv[3], &index);
<     } else if ((c == 'u') && (strncmp(argv[2], "unset", length) == 0)) {
< 	for (i = 3; i < argc; i++) {
< 	    hPtr = Tcl_FindHashEntry(&textPtr->markTable, argv[i]);
< 	    if (hPtr != NULL) {
< 		markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
< 		if ((markPtr == textPtr->insertMarkPtr)
< 			|| (markPtr == textPtr->currentMarkPtr)) {
< 		    continue;
---
> 	case MARK_UNSET: {
> 	    int i;
> 	    for (i = 3; i < objc; i++) {
> 		hPtr = Tcl_FindHashEntry(&textPtr->markTable, Tcl_GetString(objv[i]));
> 		if (hPtr != NULL) {
> 		    markPtr = (TkTextSegment *) Tcl_GetHashValue(hPtr);
> 		    if ((markPtr == textPtr->insertMarkPtr)
> 			    || (markPtr == textPtr->currentMarkPtr)) {
> 			continue;
> 		    }
> 		    TkBTreeUnlinkSegment(textPtr->tree, markPtr,
> 			    markPtr->body.mark.linePtr);
> 		    Tcl_DeleteHashEntry(hPtr);
> 		    ckfree((char *) markPtr);
203,206d226
< 		TkBTreeUnlinkSegment(textPtr->tree, markPtr,
< 			markPtr->body.mark.linePtr);
< 		Tcl_DeleteHashEntry(hPtr);
< 		ckfree((char *) markPtr);
207a228
> 	    break;
209,213c230
<     } else {
< 	Tcl_AppendResult(interp, "bad mark option \"", argv[2],
< 		"\": must be gravity, names, next, previous, set, or unset",
< 		(char *) NULL);
< 	return TCL_ERROR;
---
> 	
Index: generic/tkTextTag.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextTag.c,v
retrieving revision 1.8
diff -r1.8 tkTextTag.c
22,69c22,79
< static Tk_ConfigSpec tagConfigSpecs[] = {
<     {TK_CONFIG_BORDER, "-background", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, border), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_BITMAP, "-bgstipple", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, bgStipple), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-borderwidth", (char *) NULL, (char *) NULL,
< 	"0", Tk_Offset(TkTextTag, bdString),
< 	TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-elide", (char *) NULL, (char *) NULL,
< 	"0", Tk_Offset(TkTextTag, elideString),
< 	TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_BITMAP, "-fgstipple", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, fgStipple), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, tkfont), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, fgColor), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-justify", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, justifyString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-lmargin1", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, lMargin1String), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-lmargin2", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, lMargin2String), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-offset", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, offsetString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-overstrike", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, overstrikeString),
< 	TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-relief", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, reliefString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-rmargin", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, rMarginString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-spacing1", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, spacing1String), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-spacing2", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, spacing2String), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-spacing3", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, spacing3String), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-tabs", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, tabString), TK_CONFIG_NULL_OK},
<     {TK_CONFIG_STRING, "-underline", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, underlineString),
< 	TK_CONFIG_NULL_OK},
<     {TK_CONFIG_CUSTOM, "-wrap", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextTag, wrapMode),
< 	TK_CONFIG_NULL_OK, &textWrapModeOption},
<     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
< 	(char *) NULL, 0, 0}
---
> /*
>  * The 'TkWrapMode' enum in tkText.h is used to define a type for the
>  * -wrap option of tags in a Text widget.  These values are used as
>  * indices into the string table below.  Tags are allowed an empty wrap
>  * value, but the widget as a whole is not.
>  */
> 
> static char *wrapStrings[] = {
>     "char", "none", "word", "", (char *) NULL
> };
> 
> static Tk_OptionSpec tagOptionSpecs[] = {
>     {TK_OPTION_BORDER, "-background", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, border), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_BITMAP, "-bgstipple", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, bgStipple), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_PIXELS, "-borderwidth", (char *) NULL, (char *) NULL,
> 	"0", Tk_Offset(TkTextTag, borderWidthPtr), Tk_Offset(TkTextTag, borderWidth),
> 	TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-elide", (char *) NULL, (char *) NULL,
> 	"0", -1, Tk_Offset(TkTextTag, elideString),
> 	TK_OPTION_DONT_SET_DEFAULT|TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_BITMAP, "-fgstipple", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, fgStipple), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_FONT, "-font", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, tkfont), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_COLOR, "-foreground", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, fgColor), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-justify", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, justifyString), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-lmargin1", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, lMargin1String), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-lmargin2", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, lMargin2String), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-offset", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, offsetString), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-overstrike", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, overstrikeString),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-relief", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, reliefString), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-rmargin", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, rMarginString), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-spacing1", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, spacing1String), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-spacing2", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, spacing2String), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-spacing3", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, spacing3String), TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-tabs", (char *) NULL, (char *) NULL,
> 	(char *) NULL, Tk_Offset(TkTextTag, tabStringPtr), -1, TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING, "-underline", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, underlineString),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_STRING_TABLE, "-wrap", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextTag, wrapMode),
> 	TK_OPTION_NULL_OK, (ClientData) wrapStrings, 0},
>     {TK_OPTION_END}
79c89
< 			    TkText *textPtr, CONST char *tagName));
---
> 			    TkText *textPtr, Tcl_Obj *tagName));
104c114
< TkTextTagCmd(textPtr, interp, argc, argv)
---
> TkTextTagCmd(textPtr, interp, objc, objv)
107,108c117,118
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
110c120
< 				 * argv[1] is "tag". */
---
> 				 * objv[1] is "tag". */
112,114c122,135
<     int c, i, addTag;
<     size_t length;
<     char *fullOption;
---
>     int optionIndex;
>     
>     static CONST char *tagOptionStrings[] = {
> 	"add", "bind", "cget", "configure", "delete", "lower",
> 	"names", "nextrange", "prevrange", "raise", "ranges", 
> 	"remove", (char *) NULL 
>     };
>     enum tagOptions {
> 	TAG_ADD, TAG_BIND, TAG_CGET, TAG_CONFIGURE, TAG_DELETE,
> 	TAG_LOWER, TAG_NAMES, TAG_NEXTRANGE, TAG_PREVRANGE,
> 	TAG_RAISE, TAG_RANGES, TAG_REMOVE
>     };
> 
>     int i;
118,120c139,140
<     if (argc < 3) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " tag option ?arg arg ...?\"", (char *) NULL);
---
>     if (objc < 3) {
> 	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
123,139c143,160
<     c = argv[2][0];
<     length = strlen(argv[2]);
<     if ((c == 'a') && (strncmp(argv[2], "add", length) == 0)) {
< 	fullOption = "add";
< 	addTag = 1;
< 
< 	addAndRemove:
< 	if (argc < 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag ", fullOption,
< 		    " tagName index1 ?index2 index1 index2 ...?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = TkTextCreateTag(textPtr, argv[3]);
< 	for (i = 4; i < argc; i += 2) {
< 	    if (TkTextGetIndex(interp, textPtr, argv[i], &index1) != TCL_OK) {
---
>     
>     if (Tcl_GetIndexFromObj(interp, objv[2], tagOptionStrings, 
> 			    "tag option", 0, &optionIndex) != TCL_OK) {
> 	return TCL_ERROR;
>     }
> 
>     switch ((enum tagOptions)optionIndex) {
> 	case TAG_ADD: 
> 	case TAG_REMOVE: {
> 	    int addTag;
> 	    if (((enum tagOptions)optionIndex) == TAG_ADD) {
> 	        addTag = 1;
> 	    } else {
> 		addTag = 0;
> 	    }
> 	    if (objc < 5) {
> 		Tcl_WrongNumArgs(interp, 3, objv, 
> 				 "tagName index1 ?index2 index1 index2 ...?");
142,144c163,165
< 	    if (argc > (i+1)) {
< 		if (TkTextGetIndex(interp, textPtr, argv[i+1], &index2)
< 			!= TCL_OK) {
---
> 	    tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]));
> 	    for (i = 4; i < objc; i += 2) {
> 		if (TkTextGetObjIndex(interp, textPtr, objv[i], &index1) != TCL_OK) {
147,148c168,178
< 		if (TkTextIndexCmp(&index1, &index2) >= 0) {
< 		    return TCL_OK;
---
> 		if (objc > (i+1)) {
> 		    if (TkTextGetObjIndex(interp, textPtr, objv[i+1], &index2)
> 			    != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		    if (TkTextIndexCmp(&index1, &index2) >= 0) {
> 			return TCL_OK;
> 		    }
> 		} else {
> 		    index2 = index1;
> 		    TkTextIndexForwChars(&index2, 1, &index2);
150,153d179
< 	    } else {
< 		index2 = index1;
< 		TkTextIndexForwChars(&index2, 1, &index2);
< 	    }
155,157c181,192
< 	    if (tagPtr->affectsDisplay) {
< 		TkTextRedrawTag(textPtr, &index1, &index2, tagPtr, !addTag);
< 	    } else {
---
> 		if (tagPtr->affectsDisplay) {
> 		    TkTextRedrawTag(textPtr, &index1, &index2, tagPtr, !addTag);
> 		} else {
> 		    /*
> 		     * Still need to trigger enter/leave events on tags that
> 		     * have changed.
> 		     */
> 
> 		    TkTextEventuallyRepick(textPtr);
> 		}
> 		TkBTreeTag(&index1, &index2, tagPtr, addTag);
> 
159,160c194,196
< 		 * Still need to trigger enter/leave events on tags that
< 		 * have changed.
---
> 		 * If the tag is "sel" then grab the selection if we're supposed
> 		 * to export it and don't already have it.  Also, invalidate
> 		 * partially-completed selection retrievals.
163c199,230
< 		TkTextEventuallyRepick(textPtr);
---
> 		if (tagPtr == textPtr->selTagPtr) {
> 		    XEvent event;
> 		    /*
> 		     * Send an event that the selection changed.
> 		     * This is equivalent to
> 		     * "event generate $textWidget <<Selection>>"
> 		     */
> 
> 		    memset((VOID *) &event, 0, sizeof(event));
> 		    event.xany.type = VirtualEvent;
> 		    event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
> 		    event.xany.send_event = False;
> 		    event.xany.window = Tk_WindowId(textPtr->tkwin);
> 		    event.xany.display = Tk_Display(textPtr->tkwin);
> 		    ((XVirtualEvent *) &event)->name = Tk_GetUid("Selection");
> 		    Tk_HandleEvent(&event);
> 
> 		    if (addTag && textPtr->exportSelection
> 			    && !(textPtr->flags & GOT_SELECTION)) {
> 			Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY,
> 				TkTextLostSelection, (ClientData) textPtr);
> 			textPtr->flags |= GOT_SELECTION;
> 		    }
> 		    textPtr->abortSelections = 1;
> 		}
> 	    }
> 	    break;
> 	}
> 	case TAG_BIND: {
> 	    if ((objc < 4) || (objc > 6)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName ?sequence? ?command?");
> 		return TCL_ERROR;
165c232
< 	    TkBTreeTag(&index1, &index2, tagPtr, addTag);
---
> 	    tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]));
168,170c235,236
< 	     * If the tag is "sel" then grab the selection if we're supposed
< 	     * to export it and don't already have it.  Also, invalidate
< 	     * partially-completed selection retrievals.
---
> 	     * Make a binding table if the widget doesn't already have
> 	     * one.
173,245c239,240
< 	    if (tagPtr == textPtr->selTagPtr) {
< 		XEvent event;
< 		/*
< 		 * Send an event that the selection changed.
< 		 * This is equivalent to
< 		 * "event generate $textWidget <<Selection>>"
< 		 */
< 
< 		memset((VOID *) &event, 0, sizeof(event));
< 		event.xany.type = VirtualEvent;
< 		event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
< 		event.xany.send_event = False;
< 		event.xany.window = Tk_WindowId(textPtr->tkwin);
< 		event.xany.display = Tk_Display(textPtr->tkwin);
< 		((XVirtualEvent *) &event)->name = Tk_GetUid("Selection");
< 		Tk_HandleEvent(&event);
< 
< 		if (addTag && textPtr->exportSelection
< 			&& !(textPtr->flags & GOT_SELECTION)) {
< 		    Tk_OwnSelection(textPtr->tkwin, XA_PRIMARY,
< 			    TkTextLostSelection, (ClientData) textPtr);
< 		    textPtr->flags |= GOT_SELECTION;
< 		}
< 		textPtr->abortSelections = 1;
< 	    }
< 	}
<     } else if ((c == 'b') && (strncmp(argv[2], "bind", length) == 0)) {
< 	if ((argc < 4) || (argc > 6)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag bind tagName ?sequence? ?command?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = TkTextCreateTag(textPtr, argv[3]);
< 
< 	/*
< 	 * Make a binding table if the widget doesn't already have
< 	 * one.
< 	 */
< 
< 	if (textPtr->bindingTable == NULL) {
< 	    textPtr->bindingTable = Tk_CreateBindingTable(interp);
< 	}
< 
< 	if (argc == 6) {
< 	    int append = 0;
< 	    unsigned long mask;
< 
< 	    if (argv[5][0] == 0) {
< 		return Tk_DeleteBinding(interp, textPtr->bindingTable,
< 			(ClientData) tagPtr, argv[4]);
< 	    }
< 	    if (argv[5][0] == '+') {
< 		argv[5]++;
< 		append = 1;
< 	    }
< 	    mask = Tk_CreateBinding(interp, textPtr->bindingTable,
< 		    (ClientData) tagPtr, argv[4], argv[5], append);
< 	    if (mask == 0) {
< 		return TCL_ERROR;
< 	    }
< 	    if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
< 		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
< 		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
< 		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
< 		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
< 		Tk_DeleteBinding(interp, textPtr->bindingTable,
< 			(ClientData) tagPtr, argv[4]);
< 		Tcl_ResetResult(interp);
< 		Tcl_AppendResult(interp, "requested illegal events; ",
< 			"only key, button, motion, enter, leave, and virtual ",
< 			"events may be used", (char *) NULL);
< 		return TCL_ERROR;
---
> 	    if (textPtr->bindingTable == NULL) {
> 		textPtr->bindingTable = Tk_CreateBindingTable(interp);
247,259d241
< 	} else if (argc == 5) {
< 	    CONST char *command;
<     
< 	    command = Tk_GetBinding(interp, textPtr->bindingTable,
< 		    (ClientData) tagPtr, argv[4]);
< 	    if (command == NULL) {
< 		CONST char *string = Tcl_GetStringResult(interp); 
< 
< 		/*
< 		 * Ignore missing binding errors.  This is a special hack
< 		 * that relies on the error message returned by FindSequence
< 		 * in tkBind.c.
< 		 */
261c243,272
< 		if (string[0] != '\0') {
---
> 	    if (objc == 6) {
> 		int append = 0;
> 		unsigned long mask;
> 		char *fifth = Tcl_GetString(objv[5]);
> 
> 		if (fifth[0] == 0) {
> 		    return Tk_DeleteBinding(interp, textPtr->bindingTable,
> 			    (ClientData) tagPtr, Tcl_GetString(objv[4]));
> 		}
> 		if (fifth[0] == '+') {
> 		    fifth++;
> 		    append = 1;
> 		}
> 		mask = Tk_CreateBinding(interp, textPtr->bindingTable,
> 			(ClientData) tagPtr, Tcl_GetString(objv[4]), 
> 					fifth, append);
> 		if (mask == 0) {
> 		    return TCL_ERROR;
> 		}
> 		if (mask & (unsigned) ~(ButtonMotionMask|Button1MotionMask
> 			|Button2MotionMask|Button3MotionMask|Button4MotionMask
> 			|Button5MotionMask|ButtonPressMask|ButtonReleaseMask
> 			|EnterWindowMask|LeaveWindowMask|KeyPressMask
> 			|KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
> 		    Tk_DeleteBinding(interp, textPtr->bindingTable,
> 			    (ClientData) tagPtr, Tcl_GetString(objv[4]));
> 		    Tcl_ResetResult(interp);
> 		    Tcl_AppendResult(interp, "requested illegal events; ",
> 			    "only key, button, motion, enter, leave, and virtual ",
> 			    "events may be used", (char *) NULL);
262a274,293
> 		}
> 	    } else if (objc == 5) {
> 		CONST char *command;
> 	
> 		command = Tk_GetBinding(interp, textPtr->bindingTable,
> 			(ClientData) tagPtr, Tcl_GetString(objv[4]));
> 		if (command == NULL) {
> 		    CONST char *string = Tcl_GetStringResult(interp); 
> 
> 		    /*
> 		     * Ignore missing binding errors.  This is a special hack
> 		     * that relies on the error message returned by FindSequence
> 		     * in tkBind.c.
> 		     */
> 
> 		    if (string[0] != '\0') {
> 			return TCL_ERROR;
> 		    } else {
> 			Tcl_ResetResult(interp);
> 		    }
264c295
< 		    Tcl_ResetResult(interp);
---
> 		    Tcl_SetResult(interp, (char *) command, TCL_STATIC);
267c298,299
< 		Tcl_SetResult(interp, (char *) command, TCL_STATIC);
---
> 		Tk_GetAllBindings(interp, textPtr->bindingTable,
> 			(ClientData) tagPtr);
269,316c301,311
< 	} else {
< 	    Tk_GetAllBindings(interp, textPtr->bindingTable,
< 		    (ClientData) tagPtr);
< 	}
<     } else if ((c == 'c') && (strncmp(argv[2], "cget", length) == 0)
< 	    && (length >= 2)) {
< 	if (argc != 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag cget tagName option\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag(interp, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_ERROR;
< 	}
< 	return Tk_ConfigureValue(interp, textPtr->tkwin, tagConfigSpecs,
< 		(char *) tagPtr, argv[4], 0);
<     } else if ((c == 'c') && (strncmp(argv[2], "configure", length) == 0)
< 	    && (length >= 2)) {
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag configure tagName ?option? ?value? ",
< 		    "?option value ...?\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = TkTextCreateTag(textPtr, argv[3]);
< 	if (argc == 4) {
< 	    return Tk_ConfigureInfo(interp, textPtr->tkwin, tagConfigSpecs,
< 		    (char *) tagPtr, (char *) NULL, 0);
< 	} else if (argc == 5) {
< 	    return Tk_ConfigureInfo(interp, textPtr->tkwin, tagConfigSpecs,
< 		    (char *) tagPtr, argv[4], 0);
< 	} else {
< 	    int result;
< 
< 	    result = Tk_ConfigureWidget(interp, textPtr->tkwin, tagConfigSpecs,
< 		    argc-4, argv+4, (char *) tagPtr, 0);
< 	    /*
< 	     * Some of the configuration options, like -underline
< 	     * and -justify, require additional translation (this is
< 	     * needed because we need to distinguish a particular value
< 	     * of an option from "unspecified").
< 	     */
< 
< 	    if (tagPtr->bdString != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin, tagPtr->bdString,
< 			&tagPtr->borderWidth) != TCL_OK) {
---
> 	    break;
> 	}
> 	case TAG_CGET: {
> 	    if (objc != 5) {
> 		Tcl_WrongNumArgs(interp, 1, objv, "tag cget tagName option");
> 		return TCL_ERROR;
> 	    } else {
> 		Tcl_Obj *objPtr;
> 		
> 		tagPtr = FindTag(interp, textPtr, objv[3]);
> 		if (tagPtr == NULL) {
319,325c314,316
< 		if (tagPtr->borderWidth < 0) {
< 		    tagPtr->borderWidth = 0;
< 		}
< 	    }
< 	    if (tagPtr->reliefString != NULL) {
< 		if (Tk_GetRelief(interp, tagPtr->reliefString,
< 			&tagPtr->relief) != TCL_OK) {
---
> 		objPtr = Tk_GetOptionValue(interp, (char *) tagPtr,
> 					   tagPtr->optionTable, objv[4], textPtr->tkwin);
> 		if (objPtr == NULL) {
326a318,320
> 		} else {
> 		    Tcl_SetObjResult(interp, objPtr);
> 		    return TCL_OK;
329,333c323,328
< 	    if (tagPtr->justifyString != NULL) {
< 		if (Tk_GetJustify(interp, tagPtr->justifyString,
< 			&tagPtr->justify) != TCL_OK) {
< 		    return TCL_ERROR;
< 		}
---
> 	    break;
> 	}
> 	case TAG_CONFIGURE: {
> 	    if (objc < 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName ?option? ?value? ?option value ...?");
> 		return TCL_ERROR;
335,337c330,336
< 	    if (tagPtr->lMargin1String != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->lMargin1String, &tagPtr->lMargin1) != TCL_OK) {
---
> 	    tagPtr = TkTextCreateTag(textPtr, Tcl_GetString(objv[3]));
> 	    if (objc <= 5) {
> 		Tcl_Obj* objPtr = Tk_GetOptionInfo(interp, (char *) tagPtr,
> 						   tagPtr->optionTable,
> 			(objc == 5) ? objv[4] : (Tcl_Obj *) NULL,
> 					  textPtr->tkwin);
> 		if (objPtr == NULL) {
338a338,340
> 		} else {
> 		    Tcl_SetObjResult(interp, objPtr);
> 		    return TCL_OK;
340,343c342,346
< 	    }
< 	    if (tagPtr->lMargin2String != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->lMargin2String, &tagPtr->lMargin2) != TCL_OK) {
---
> 	    } else {
> 		int result = TCL_OK;
> 
> 		if (Tk_SetOptions(interp, (char*)tagPtr, tagPtr->optionTable,
> 			objc-4, objv+4, textPtr->tkwin, NULL, NULL) != TCL_OK) {
346,350c349,357
< 	    }
< 	    if (tagPtr->offsetString != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin, tagPtr->offsetString,
< 			&tagPtr->offset) != TCL_OK) {
< 		    return TCL_ERROR;
---
> 		/*
> 		 * Some of the configuration options, like -underline
> 		 * and -justify, require additional translation (this is
> 		 * needed because we need to distinguish a particular value
> 		 * of an option from "unspecified").
> 		 */
> 
> 		if (tagPtr->borderWidth < 0) {
> 		    tagPtr->borderWidth = 0;
352,356c359,449
< 	    }
< 	    if (tagPtr->overstrikeString != NULL) {
< 		if (Tcl_GetBoolean(interp, tagPtr->overstrikeString,
< 			&tagPtr->overstrike) != TCL_OK) {
< 		    return TCL_ERROR;
---
> 		if (tagPtr->reliefString != NULL) {
> 		    if (Tk_GetRelief(interp, tagPtr->reliefString,
> 			    &tagPtr->relief) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->justifyString != NULL) {
> 		    if (Tk_GetJustify(interp, tagPtr->justifyString,
> 			    &tagPtr->justify) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->lMargin1String != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->lMargin1String, &tagPtr->lMargin1) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->lMargin2String != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->lMargin2String, &tagPtr->lMargin2) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->offsetString != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin, tagPtr->offsetString,
> 			    &tagPtr->offset) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->overstrikeString != NULL) {
> 		    if (Tcl_GetBoolean(interp, tagPtr->overstrikeString,
> 			    &tagPtr->overstrike) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->rMarginString != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->rMarginString, &tagPtr->rMargin) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->spacing1String != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->spacing1String, &tagPtr->spacing1) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		    if (tagPtr->spacing1 < 0) {
> 			tagPtr->spacing1 = 0;
> 		    }
> 		}
> 		if (tagPtr->spacing2String != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->spacing2String, &tagPtr->spacing2) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		    if (tagPtr->spacing2 < 0) {
> 			tagPtr->spacing2 = 0;
> 		    }
> 		}
> 		if (tagPtr->spacing3String != NULL) {
> 		    if (Tk_GetPixels(interp, textPtr->tkwin,
> 			    tagPtr->spacing3String, &tagPtr->spacing3) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		    if (tagPtr->spacing3 < 0) {
> 			tagPtr->spacing3 = 0;
> 		    }
> 		}
> 		if (tagPtr->tabArrayPtr != NULL) {
> 		    ckfree((char *) tagPtr->tabArrayPtr);
> 		    tagPtr->tabArrayPtr = NULL;
> 		}
> 		if (tagPtr->tabStringPtr != NULL) {
> 		    tagPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin,
> 			    tagPtr->tabStringPtr);
> 		    if (tagPtr->tabArrayPtr == NULL) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->underlineString != NULL) {
> 		    if (Tcl_GetBoolean(interp, tagPtr->underlineString,
> 			    &tagPtr->underline) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
> 		}
> 		if (tagPtr->elideString != NULL) {
> 		    if (Tcl_GetBoolean(interp, tagPtr->elideString,
> 			    &tagPtr->elide) != TCL_OK) {
> 			return TCL_ERROR;
> 		    }
358,362c451,485
< 	    }
< 	    if (tagPtr->rMarginString != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->rMarginString, &tagPtr->rMargin) != TCL_OK) {
< 		    return TCL_ERROR;
---
> 
> 		/*
> 		 * If the "sel" tag was changed, be sure to mirror information
> 		 * from the tag back into the text widget record.   NOTE: we
> 		 * don't have to free up information in the widget record
> 		 * before overwriting it, because it was mirrored in the tag
> 		 * and hence freed when the tag field was overwritten.
> 		 */
> 
> 		if (tagPtr == textPtr->selTagPtr) {
> 		    textPtr->selBorder = tagPtr->border;
> 		    textPtr->selBorderWidth = tagPtr->borderWidth;
> 		    textPtr->selBorderWidthPtr = tagPtr->borderWidthPtr;
> 		    textPtr->selFgColorPtr = tagPtr->fgColor;
> 		}
> 		tagPtr->affectsDisplay = 0;
> 		if ((tagPtr->border != NULL)
> 			|| (tagPtr->reliefString != NULL)
> 			|| (tagPtr->bgStipple != None)
> 			|| (tagPtr->fgColor != NULL) || (tagPtr->tkfont != None)
> 			|| (tagPtr->fgStipple != None)
> 			|| (tagPtr->justifyString != NULL)
> 			|| (tagPtr->lMargin1String != NULL)
> 			|| (tagPtr->lMargin2String != NULL)
> 			|| (tagPtr->offsetString != NULL)
> 			|| (tagPtr->overstrikeString != NULL)
> 			|| (tagPtr->rMarginString != NULL)
> 			|| (tagPtr->spacing1String != NULL)
> 			|| (tagPtr->spacing2String != NULL)
> 			|| (tagPtr->spacing3String != NULL)
> 			|| (tagPtr->tabStringPtr != NULL)
> 			|| (tagPtr->underlineString != NULL)
> 			|| (tagPtr->elideString != NULL)
> 			|| (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
> 		    tagPtr->affectsDisplay = 1;
363a487,489
> 		TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
> 			(TkTextIndex *) NULL, tagPtr, 1);
> 		return result;
365,371c491,539
< 	    if (tagPtr->spacing1String != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->spacing1String, &tagPtr->spacing1) != TCL_OK) {
< 		    return TCL_ERROR;
< 		}
< 		if (tagPtr->spacing1 < 0) {
< 		    tagPtr->spacing1 = 0;
---
> 	    break;
> 	}
> 	case TAG_DELETE: {
> 	    Tcl_HashEntry *hPtr;
> 
> 	    if (objc < 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName ?tagName ...?");
> 		return TCL_ERROR;
> 	    }
> 	    for (i = 3; i < objc; i++) {
> 		hPtr = Tcl_FindHashEntry(&textPtr->tagTable, Tcl_GetString(objv[i]));
> 		if (hPtr == NULL) {
> 		    continue;
> 		}
> 		tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr);
> 		if (tagPtr == textPtr->selTagPtr) {
> 		    continue;
> 		}
> 		if (tagPtr->affectsDisplay) {
> 		    TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
> 			    (TkTextIndex *) NULL, tagPtr, 1);
> 		}
> 		TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
> 		TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
> 			0, &last),
> 		TkBTreeTag(&first, &last, tagPtr, 0);
> 
> 		if (tagPtr == textPtr->selTagPtr) {
> 		    XEvent event;
> 		    /*
> 		     * Send an event that the selection changed.
> 		     * This is equivalent to
> 		     * "event generate $textWidget <<Selection>>"
> 		     */
> 
> 		    memset((VOID *) &event, 0, sizeof(event));
> 		    event.xany.type = VirtualEvent;
> 		    event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
> 		    event.xany.send_event = False;
> 		    event.xany.window = Tk_WindowId(textPtr->tkwin);
> 		    event.xany.display = Tk_Display(textPtr->tkwin);
> 		    ((XVirtualEvent *) &event)->name = Tk_GetUid("Selection");
> 		    Tk_HandleEvent(&event);
> 		}
> 
> 		Tcl_DeleteHashEntry(hPtr);
> 		if (textPtr->bindingTable != NULL) {
> 		    Tk_DeleteAllBindings(textPtr->bindingTable,
> 			    (ClientData) tagPtr);
372a541,562
> 	    
> 		/*
> 		 * Update the tag priorities to reflect the deletion of this tag.
> 		 */
> 
> 		ChangeTagPriority(textPtr, tagPtr, textPtr->numTags-1);
> 		textPtr->numTags -= 1;
> 		TkTextFreeTag(textPtr, tagPtr);
> 	    }
> 	    break;
> 	}
> 	case TAG_LOWER: {
> 	    TkTextTag *tagPtr2;
> 	    int prio;
> 
> 	    if ((objc != 4) && (objc != 5)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName ?belowThis?");
> 		return TCL_ERROR;
> 	    }
> 	    tagPtr = FindTag(interp, textPtr, objv[3]);
> 	    if (tagPtr == NULL) {
> 		return TCL_ERROR;
374,376c564,566
< 	    if (tagPtr->spacing2String != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->spacing2String, &tagPtr->spacing2) != TCL_OK) {
---
> 	    if (objc == 5) {
> 		tagPtr2 = FindTag(interp, textPtr, objv[4]);
> 		if (tagPtr2 == NULL) {
379,380c569,572
< 		if (tagPtr->spacing2 < 0) {
< 		    tagPtr->spacing2 = 0;
---
> 		if (tagPtr->priority < tagPtr2->priority) {
> 		    prio = tagPtr2->priority - 1;
> 		} else {
> 		    prio = tagPtr2->priority;
381a574,588
> 	    } else {
> 		prio = 0;
> 	    }
> 	    ChangeTagPriority(textPtr, tagPtr, prio);
> 	    TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
> 		    tagPtr, 1);
> 	    break;
> 	}
> 	case TAG_NAMES: {
> 	    TkTextTag **arrayPtr;
> 	    int arraySize;
> 
> 	    if ((objc != 3) && (objc != 4)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "?index?");
> 		return TCL_ERROR;
383,385c590,603
< 	    if (tagPtr->spacing3String != NULL) {
< 		if (Tk_GetPixels(interp, textPtr->tkwin,
< 			tagPtr->spacing3String, &tagPtr->spacing3) != TCL_OK) {
---
> 	    if (objc == 3) {
> 		Tcl_HashSearch search;
> 		Tcl_HashEntry *hPtr;
> 
> 		arrayPtr = (TkTextTag **) ckalloc((unsigned)
> 			(textPtr->numTags * sizeof(TkTextTag *)));
> 		for (i = 0, hPtr = Tcl_FirstHashEntry(&textPtr->tagTable, &search);
> 			hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
> 		    arrayPtr[i] = (TkTextTag *) Tcl_GetHashValue(hPtr);
> 		}
> 		arraySize = textPtr->numTags;
> 	    } else {
> 		if (TkTextGetObjIndex(interp, textPtr, objv[3], &index1)
> 			!= TCL_OK) {
388,389c606,608
< 		if (tagPtr->spacing3 < 0) {
< 		    tagPtr->spacing3 = 0;
---
> 		arrayPtr = TkBTreeGetTags(&index1, &arraySize);
> 		if (arrayPtr == NULL) {
> 		    return TCL_OK;
392,401c611,625
< 	    if (tagPtr->tabArrayPtr != NULL) {
< 		ckfree((char *) tagPtr->tabArrayPtr);
< 		tagPtr->tabArrayPtr = NULL;
< 	    }
< 	    if (tagPtr->tabString != NULL) {
< 		tagPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin,
< 			tagPtr->tabString);
< 		if (tagPtr->tabArrayPtr == NULL) {
< 		    return TCL_ERROR;
< 		}
---
> 	    SortTags(arraySize, arrayPtr);
> 	    for (i = 0; i < arraySize; i++) {
> 		tagPtr = arrayPtr[i];
> 		Tcl_AppendElement(interp, tagPtr->name);
> 	    }
> 	    ckfree((char *) arrayPtr);
> 	    break;
> 	}
> 	case TAG_NEXTRANGE: {
> 	    TkTextSearch tSearch;
> 	    char position[TK_POS_CHARS];
> 
> 	    if ((objc != 5) && (objc != 6)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
> 		return TCL_ERROR;
403,407c627,629
< 	    if (tagPtr->underlineString != NULL) {
< 		if (Tcl_GetBoolean(interp, tagPtr->underlineString,
< 			&tagPtr->underline) != TCL_OK) {
< 		    return TCL_ERROR;
< 		}
---
> 	    tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, objv[3]);
> 	    if (tagPtr == NULL) {
> 		return TCL_OK;
409,413c631,640
< 	    if (tagPtr->elideString != NULL) {
< 		if (Tcl_GetBoolean(interp, tagPtr->elideString,
< 			&tagPtr->elide) != TCL_OK) {
< 		    return TCL_ERROR;
< 		}
---
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
> 	    TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
> 		    0, &last);
> 	    if (objc == 5) {
> 		index2 = last;
> 	    } else if (TkTextGetObjIndex(interp, textPtr, objv[5], &index2)
> 		    != TCL_OK) {
> 		return TCL_ERROR;
417,421c644,650
< 	     * If the "sel" tag was changed, be sure to mirror information
< 	     * from the tag back into the text widget record.   NOTE: we
< 	     * don't have to free up information in the widget record
< 	     * before overwriting it, because it was mirrored in the tag
< 	     * and hence freed when the tag field was overwritten.
---
> 	     * The search below is a bit tricky.  Rather than use the B-tree
> 	     * facilities to stop the search at index2, let it search up
> 	     * until the end of the file but check for a position past index2
> 	     * ourselves.  The reason for doing it this way is that we only
> 	     * care whether the *start* of the range is before index2;  once
> 	     * we find the start, we don't want TkBTreeNextTag to abort the
> 	     * search because the end of the range is after index2.
424,480c653,656
< 	    if (tagPtr == textPtr->selTagPtr) {
< 		textPtr->selBorder = tagPtr->border;
< 		textPtr->selBdString = tagPtr->bdString;
< 		textPtr->selFgColorPtr = tagPtr->fgColor;
< 	    }
< 	    tagPtr->affectsDisplay = 0;
< 	    if ((tagPtr->border != NULL)
< 		    || (tagPtr->bdString != NULL)
< 		    || (tagPtr->reliefString != NULL)
< 		    || (tagPtr->bgStipple != None)
< 		    || (tagPtr->fgColor != NULL) || (tagPtr->tkfont != None)
< 		    || (tagPtr->fgStipple != None)
< 		    || (tagPtr->justifyString != NULL)
< 		    || (tagPtr->lMargin1String != NULL)
< 		    || (tagPtr->lMargin2String != NULL)
< 		    || (tagPtr->offsetString != NULL)
< 		    || (tagPtr->overstrikeString != NULL)
< 		    || (tagPtr->rMarginString != NULL)
< 		    || (tagPtr->spacing1String != NULL)
< 		    || (tagPtr->spacing2String != NULL)
< 		    || (tagPtr->spacing3String != NULL)
< 		    || (tagPtr->tabString != NULL)
< 		    || (tagPtr->underlineString != NULL)
< 		    || (tagPtr->elideString != NULL)
< 		    || (tagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
< 		tagPtr->affectsDisplay = 1;
< 	    }
< 	    TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
< 		    (TkTextIndex *) NULL, tagPtr, 1);
< 	    return result;
< 	}
<     } else if ((c == 'd') && (strncmp(argv[2], "delete", length) == 0)) {
< 	Tcl_HashEntry *hPtr;
< 
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag delete tagName tagName ...\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	for (i = 3; i < argc; i++) {
< 	    hPtr = Tcl_FindHashEntry(&textPtr->tagTable, argv[i]);
< 	    if (hPtr == NULL) {
< 		continue;
< 	    }
< 	    tagPtr = (TkTextTag *) Tcl_GetHashValue(hPtr);
< 	    if (tagPtr == textPtr->selTagPtr) {
< 		continue;
< 	    }
< 	    if (tagPtr->affectsDisplay) {
< 		TkTextRedrawTag(textPtr, (TkTextIndex *) NULL,
< 			(TkTextIndex *) NULL, tagPtr, 1);
< 	    }
< 	    TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
< 	    TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
< 		    0, &last),
< 	    TkBTreeTag(&first, &last, tagPtr, 0);
---
> 	    TkBTreeStartSearch(&index1, &last, tagPtr, &tSearch);
> 	    if (TkBTreeCharTagged(&index1, tagPtr)) {
> 		TkTextSegment *segPtr;
> 		int offset;
482,483d657
< 	    if (tagPtr == textPtr->selTagPtr) {
< 		XEvent event;
485,487c659,661
< 		 * Send an event that the selection changed.
< 		 * This is equivalent to
< 		 * "event generate $textWidget <<Selection>>"
---
> 		 * The first character is tagged.  See if there is an
> 		 * on-toggle just before the character.  If not, then
> 		 * skip to the end of this tagged range.
490,497c664,674
< 		memset((VOID *) &event, 0, sizeof(event));
< 		event.xany.type = VirtualEvent;
< 		event.xany.serial = NextRequest(Tk_Display(textPtr->tkwin));
< 		event.xany.send_event = False;
< 		event.xany.window = Tk_WindowId(textPtr->tkwin);
< 		event.xany.display = Tk_Display(textPtr->tkwin);
< 		((XVirtualEvent *) &event)->name = Tk_GetUid("Selection");
< 		Tk_HandleEvent(&event);
---
> 		for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex; 
> 			offset >= 0;
> 			offset -= segPtr->size, segPtr = segPtr->nextPtr) {
> 		    if ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType)
> 			    && (segPtr->body.toggle.tagPtr == tagPtr)) {
> 			goto gotStart;
> 		    }
> 		}
> 		if (!TkBTreeNextTag(&tSearch)) {
> 		     return TCL_OK;
> 		}
500,505d676
< 	    Tcl_DeleteHashEntry(hPtr);
< 	    if (textPtr->bindingTable != NULL) {
< 		Tk_DeleteAllBindings(textPtr->bindingTable,
< 			(ClientData) tagPtr);
< 	    }
< 	
507c678
< 	     * Update the tag priorities to reflect the deletion of this tag.
---
> 	     * Find the start of the tagged range.
510,531c681,682
< 	    ChangeTagPriority(textPtr, tagPtr, textPtr->numTags-1);
< 	    textPtr->numTags -= 1;
< 	    TkTextFreeTag(textPtr, tagPtr);
< 	}
<     } else if ((c == 'l') && (strncmp(argv[2], "lower", length) == 0)) {
< 	TkTextTag *tagPtr2;
< 	int prio;
< 
< 	if ((argc != 4) && (argc != 5)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag lower tagName ?belowThis?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag(interp, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_ERROR;
< 	}
< 	if (argc == 5) {
< 	    tagPtr2 = FindTag(interp, textPtr, argv[4]);
< 	    if (tagPtr2 == NULL) {
< 		return TCL_ERROR;
---
> 	    if (!TkBTreeNextTag(&tSearch)) {
> 		return TCL_OK;
533,536c684,686
< 	    if (tagPtr->priority < tagPtr2->priority) {
< 		prio = tagPtr2->priority - 1;
< 	    } else {
< 		prio = tagPtr2->priority;
---
> 	    gotStart:
> 	    if (TkTextIndexCmp(&tSearch.curIndex, &index2) >= 0) {
> 		return TCL_OK;
538,553c688,693
< 	} else {
< 	    prio = 0;
< 	}
< 	ChangeTagPriority(textPtr, tagPtr, prio);
< 	TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
< 		tagPtr, 1);
<     } else if ((c == 'n') && (strncmp(argv[2], "names", length) == 0)
< 	    && (length >= 2)) {
< 	TkTextTag **arrayPtr;
< 	int arraySize;
< 
< 	if ((argc != 3) && (argc != 4)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag names ?index?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
---
> 	    TkTextPrintIndex(&tSearch.curIndex, position);
> 	    Tcl_AppendElement(interp, position);
> 	    TkBTreeNextTag(&tSearch);
> 	    TkTextPrintIndex(&tSearch.curIndex, position);
> 	    Tcl_AppendElement(interp, position);
> 	    break;
555,557c695,698
< 	if (argc == 3) {
< 	    Tcl_HashSearch search;
< 	    Tcl_HashEntry *hPtr;
---
> 	case TAG_PREVRANGE: {
> 	    TkTextSearch tSearch;
> 	    char position1[TK_POS_CHARS];
> 	    char position2[TK_POS_CHARS];
559,568c700,701
< 	    arrayPtr = (TkTextTag **) ckalloc((unsigned)
< 		    (textPtr->numTags * sizeof(TkTextTag *)));
< 	    for (i = 0, hPtr = Tcl_FirstHashEntry(&textPtr->tagTable, &search);
< 		    hPtr != NULL; i++, hPtr = Tcl_NextHashEntry(&search)) {
< 		arrayPtr[i] = (TkTextTag *) Tcl_GetHashValue(hPtr);
< 	    }
< 	    arraySize = textPtr->numTags;
< 	} else {
< 	    if (TkTextGetIndex(interp, textPtr, argv[3], &index1)
< 		    != TCL_OK) {
---
> 	    if ((objc != 5) && (objc != 6)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName index1 ?index2?");
571,572c704,705
< 	    arrayPtr = TkBTreeGetTags(&index1, &arraySize);
< 	    if (arrayPtr == NULL) {
---
> 	    tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, objv[3]);
> 	    if (tagPtr == NULL) {
575,622c708,716
< 	}
< 	SortTags(arraySize, arrayPtr);
< 	for (i = 0; i < arraySize; i++) {
< 	    tagPtr = arrayPtr[i];
< 	    Tcl_AppendElement(interp, tagPtr->name);
< 	}
< 	ckfree((char *) arrayPtr);
<     } else if ((c == 'n') && (strncmp(argv[2], "nextrange", length) == 0)
< 	    && (length >= 2)) {
< 	TkTextSearch tSearch;
< 	char position[TK_POS_CHARS];
< 
< 	if ((argc != 5) && (argc != 6)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag nextrange tagName index1 ?index2?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_OK;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[4], &index1) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 	TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
< 		0, &last);
< 	if (argc == 5) {
< 	    index2 = last;
< 	} else if (TkTextGetIndex(interp, textPtr, argv[5], &index2)
< 		!= TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 
< 	/*
< 	 * The search below is a bit tricky.  Rather than use the B-tree
< 	 * facilities to stop the search at index2, let it search up
< 	 * until the end of the file but check for a position past index2
< 	 * ourselves.  The reason for doing it this way is that we only
< 	 * care whether the *start* of the range is before index2;  once
< 	 * we find the start, we don't want TkBTreeNextTag to abort the
< 	 * search because the end of the range is after index2.
< 	 */
< 
< 	TkBTreeStartSearch(&index1, &last, tagPtr, &tSearch);
< 	if (TkBTreeCharTagged(&index1, tagPtr)) {
< 	    TkTextSegment *segPtr;
< 	    int offset;
---
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[4], &index1) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
> 	    if (objc == 5) {
> 		TkTextMakeByteIndex(textPtr->tree, 0, 0, &index2);
> 	    } else if (TkTextGetObjIndex(interp, textPtr, objv[5], &index2)
> 		    != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
625,627c719,722
< 	     * The first character is tagged.  See if there is an
< 	     * on-toggle just before the character.  If not, then
< 	     * skip to the end of this tagged range.
---
> 	     * The search below is a bit weird.  The previous toggle can be
> 	     * either an on or off toggle. If it is an on toggle, then we
> 	     * need to turn around and search forward for the end toggle.
> 	     * Otherwise we keep searching backwards.
630,636c725,728
< 	    for (segPtr = index1.linePtr->segPtr, offset = index1.byteIndex; 
< 		    offset >= 0;
< 		    offset -= segPtr->size, segPtr = segPtr->nextPtr) {
< 		if ((offset == 0) && (segPtr->typePtr == &tkTextToggleOnType)
< 			&& (segPtr->body.toggle.tagPtr == tagPtr)) {
< 		    goto gotStart;
< 		}
---
> 	    TkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch);
> 
> 	    if (!TkBTreePrevTag(&tSearch)) {
> 		return TCL_OK;
638,639c730,743
< 	    if (!TkBTreeNextTag(&tSearch)) {
< 		 return TCL_OK;
---
> 	    if (tSearch.segPtr->typePtr == &tkTextToggleOnType) {
> 		TkTextPrintIndex(&tSearch.curIndex, position1);
> 		TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
> 			0, &last);
> 		TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch);
> 		TkBTreeNextTag(&tSearch);
> 		TkTextPrintIndex(&tSearch.curIndex, position2);
> 	    } else {
> 		TkTextPrintIndex(&tSearch.curIndex, position2);
> 		TkBTreePrevTag(&tSearch);
> 		if (TkTextIndexCmp(&tSearch.curIndex, &index2) < 0) {
> 		    return TCL_OK;
> 		}
> 		TkTextPrintIndex(&tSearch.curIndex, position1);
641,690c745,751
< 	}
< 
< 	/*
< 	 * Find the start of the tagged range.
< 	 */
< 
< 	if (!TkBTreeNextTag(&tSearch)) {
< 	    return TCL_OK;
< 	}
< 	gotStart:
< 	if (TkTextIndexCmp(&tSearch.curIndex, &index2) >= 0) {
< 	    return TCL_OK;
< 	}
< 	TkTextPrintIndex(&tSearch.curIndex, position);
< 	Tcl_AppendElement(interp, position);
< 	TkBTreeNextTag(&tSearch);
< 	TkTextPrintIndex(&tSearch.curIndex, position);
< 	Tcl_AppendElement(interp, position);
<     } else if ((c == 'p') && (strncmp(argv[2], "prevrange", length) == 0)
< 	    && (length >= 2)) {
< 	TkTextSearch tSearch;
< 	char position1[TK_POS_CHARS];
< 	char position2[TK_POS_CHARS];
< 
< 	if ((argc != 5) && (argc != 6)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag prevrange tagName index1 ?index2?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_OK;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[4], &index1) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 	if (argc == 5) {
< 	    TkTextMakeByteIndex(textPtr->tree, 0, 0, &index2);
< 	} else if (TkTextGetIndex(interp, textPtr, argv[5], &index2)
< 		!= TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 
< 	/*
< 	 * The search below is a bit weird.  The previous toggle can be
< 	 * either an on or off toggle. If it is an on toggle, then we
< 	 * need to turn around and search forward for the end toggle.
< 	 * Otherwise we keep searching backwards.
< 	 */
---
> 	    Tcl_AppendElement(interp, position1);
> 	    Tcl_AppendElement(interp, position2);
> 	    break;
> 	}
> 	case TAG_RAISE: {
> 	    TkTextTag *tagPtr2;
> 	    int prio;
692,708c753,755
< 	TkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch);
< 
< 	if (!TkBTreePrevTag(&tSearch)) {
< 	    return TCL_OK;
< 	}
< 	if (tSearch.segPtr->typePtr == &tkTextToggleOnType) {
< 	    TkTextPrintIndex(&tSearch.curIndex, position1);
< 	    TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
< 		    0, &last);
< 	    TkBTreeStartSearch(&tSearch.curIndex, &last, tagPtr, &tSearch);
< 	    TkBTreeNextTag(&tSearch);
< 	    TkTextPrintIndex(&tSearch.curIndex, position2);
< 	} else {
< 	    TkTextPrintIndex(&tSearch.curIndex, position2);
< 	    TkBTreePrevTag(&tSearch);
< 	    if (TkTextIndexCmp(&tSearch.curIndex, &index2) < 0) {
< 		return TCL_OK;
---
> 	    if ((objc != 4) && (objc != 5)) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName ?aboveThis?");
> 		return TCL_ERROR;
710,731c757,758
< 	    TkTextPrintIndex(&tSearch.curIndex, position1);
< 	}
< 	Tcl_AppendElement(interp, position1);
< 	Tcl_AppendElement(interp, position2);
<     } else if ((c == 'r') && (strncmp(argv[2], "raise", length) == 0)
< 	    && (length >= 3)) {
< 	TkTextTag *tagPtr2;
< 	int prio;
< 
< 	if ((argc != 4) && (argc != 5)) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag raise tagName ?aboveThis?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag(interp, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_ERROR;
< 	}
< 	if (argc == 5) {
< 	    tagPtr2 = FindTag(interp, textPtr, argv[4]);
< 	    if (tagPtr2 == NULL) {
---
> 	    tagPtr = FindTag(interp, textPtr, objv[3]);
> 	    if (tagPtr == NULL) {
734,735c761,770
< 	    if (tagPtr->priority <= tagPtr2->priority) {
< 		prio = tagPtr2->priority;
---
> 	    if (objc == 5) {
> 		tagPtr2 = FindTag(interp, textPtr, objv[4]);
> 		if (tagPtr2 == NULL) {
> 		    return TCL_ERROR;
> 		}
> 		if (tagPtr->priority <= tagPtr2->priority) {
> 		    prio = tagPtr2->priority;
> 		} else {
> 		    prio = tagPtr2->priority + 1;
> 		}
737c772
< 		prio = tagPtr2->priority + 1;
---
> 		prio = textPtr->numTags-1;
739,769c774,803
< 	} else {
< 	    prio = textPtr->numTags-1;
< 	}
< 	ChangeTagPriority(textPtr, tagPtr, prio);
< 	TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
< 		tagPtr, 1);
<     } else if ((c == 'r') && (strncmp(argv[2], "ranges", length) == 0)
< 	    && (length >= 3)) {
< 	TkTextSearch tSearch;
< 	char position[TK_POS_CHARS];
< 
< 	if (argc != 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " tag ranges tagName\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, argv[3]);
< 	if (tagPtr == NULL) {
< 	    return TCL_OK;
< 	}
< 	TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
< 	TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
< 		0, &last);
< 	TkBTreeStartSearch(&first, &last, tagPtr, &tSearch);
< 	if (TkBTreeCharTagged(&first, tagPtr)) {
< 	    TkTextPrintIndex(&first, position);
< 	    Tcl_AppendElement(interp, position);
< 	}
< 	while (TkBTreeNextTag(&tSearch)) {
< 	    TkTextPrintIndex(&tSearch.curIndex, position);
< 	    Tcl_AppendElement(interp, position);
---
> 	    ChangeTagPriority(textPtr, tagPtr, prio);
> 	    TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
> 		    tagPtr, 1);
> 	    break;
> 	}
> 	case TAG_RANGES: {
> 	    TkTextSearch tSearch;
> 	    char position[TK_POS_CHARS];
> 
> 	    if (objc != 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "tagName");
> 		return TCL_ERROR;
> 	    }
> 	    tagPtr = FindTag((Tcl_Interp *) NULL, textPtr, objv[3]);
> 	    if (tagPtr == NULL) {
> 		return TCL_OK;
> 	    }
> 	    TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
> 	    TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree),
> 		    0, &last);
> 	    TkBTreeStartSearch(&first, &last, tagPtr, &tSearch);
> 	    if (TkBTreeCharTagged(&first, tagPtr)) {
> 		TkTextPrintIndex(&first, position);
> 		Tcl_AppendElement(interp, position);
> 	    }
> 	    while (TkBTreeNextTag(&tSearch)) {
> 		TkTextPrintIndex(&tSearch.curIndex, position);
> 		Tcl_AppendElement(interp, position);
> 	    }
> 	    break;
771,781d804
<     } else if ((c == 'r') && (strncmp(argv[2], "remove", length) == 0)
< 	    && (length >= 2)) {
< 	fullOption = "remove";
< 	addTag = 0;
< 	goto addAndRemove;
<     } else {
< 	Tcl_AppendResult(interp, "bad tag option \"", argv[2],
< 		"\": must be add, bind, cget, configure, delete, lower, ",
< 		"names, nextrange, raise, ranges, or remove",
< 		(char *) NULL);
< 	return TCL_ERROR;
829d851
<     tagPtr->bdString = NULL;
830a853
>     tagPtr->borderWidthPtr = NULL;
855c878
<     tagPtr->tabString = NULL;
---
>     tagPtr->tabStringPtr = NULL;
864a888
>     tagPtr->optionTable = Tk_CreateOptionTable(textPtr->interp, tagOptionSpecs);
893c917
<     CONST char *tagName;	/* Name of desired tag. */
---
>     Tcl_Obj *tagName;	        /* Name of desired tag. */
897c921
<     hPtr = Tcl_FindHashEntry(&textPtr->tagTable, tagName);
---
>     hPtr = Tcl_FindHashEntry(&textPtr->tagTable, Tcl_GetString(tagName));
902c926
< 	Tcl_AppendResult(interp, "tag \"", tagName,
---
> 	Tcl_AppendResult(interp, "tag \"", Tcl_GetString(tagName),
930,978c954,957
<     if (tagPtr->border != None) {
< 	Tk_Free3DBorder(tagPtr->border);
<     }
<     if (tagPtr->bdString != NULL) {
< 	ckfree(tagPtr->bdString);
<     }
<     if (tagPtr->reliefString != NULL) {
< 	ckfree(tagPtr->reliefString);
<     }
<     if (tagPtr->bgStipple != None) {
< 	Tk_FreeBitmap(textPtr->display, tagPtr->bgStipple);
<     }
<     if (tagPtr->fgColor != None) {
< 	Tk_FreeColor(tagPtr->fgColor);
<     }
<     Tk_FreeFont(tagPtr->tkfont);
<     if (tagPtr->fgStipple != None) {
< 	Tk_FreeBitmap(textPtr->display, tagPtr->fgStipple);
<     }
<     if (tagPtr->justifyString != NULL) {
< 	ckfree(tagPtr->justifyString);
<     }
<     if (tagPtr->lMargin1String != NULL) {
< 	ckfree(tagPtr->lMargin1String);
<     }
<     if (tagPtr->lMargin2String != NULL) {
< 	ckfree(tagPtr->lMargin2String);
<     }
<     if (tagPtr->offsetString != NULL) {
< 	ckfree(tagPtr->offsetString);
<     }
<     if (tagPtr->overstrikeString != NULL) {
< 	ckfree(tagPtr->overstrikeString);
<     }
<     if (tagPtr->rMarginString != NULL) {
< 	ckfree(tagPtr->rMarginString);
<     }
<     if (tagPtr->spacing1String != NULL) {
< 	ckfree(tagPtr->spacing1String);
<     }
<     if (tagPtr->spacing2String != NULL) {
< 	ckfree(tagPtr->spacing2String);
<     }
<     if (tagPtr->spacing3String != NULL) {
< 	ckfree(tagPtr->spacing3String);
<     }
<     if (tagPtr->tabString != NULL) {
< 	ckfree(tagPtr->tabString);
<     }
---
>     /* Let Tk do most of the hard work for us */
>     Tk_FreeConfigOptions((char *) tagPtr, tagPtr->optionTable,
> 			 textPtr->tkwin);
>     /* This associated information is managed by us */
981,983d959
<     }
<     if (tagPtr->underlineString != NULL) {
< 	ckfree(tagPtr->underlineString);
Index: generic/tkTextWind.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkTextWind.c,v
retrieving revision 1.6
diff -r1.6 tkTextWind.c
38,46d37
<  * Definitions for alignment values:
<  */
< 
< #define ALIGN_BOTTOM		0
< #define ALIGN_CENTER		1
< #define ALIGN_TOP		2
< #define ALIGN_BASELINE		3
< 
< /*
57,62d47
< static int		AlignParseProc _ANSI_ARGS_((ClientData clientData,
< 			    Tcl_Interp *interp, Tk_Window tkwin,
< 			    CONST char *value, char *widgRec, int offset));
< static char *		AlignPrintProc _ANSI_ARGS_((ClientData clientData,
< 			    Tk_Window tkwin, char *widgRec, int offset,
< 			    Tcl_FreeProc **freeProcPtr));
72c57
< 			    TkTextSegment *ewPtr, int argc, CONST char **argv));
---
> 			    TkTextSegment *ewPtr, int objc, Tcl_Obj *CONST objv[]));
107c92
<  * Information used for parsing window configuration options:
---
>  * Definitions for alignment values:
110,111c95,101
< static Tk_CustomOption alignOption = {AlignParseProc, AlignPrintProc,
< 	(ClientData) NULL};
---
> static char *alignStrings[] = {
>     "baseline", "bottom", "center", "top", (char *) NULL
> };
> 
> typedef enum {	
>     ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER, ALIGN_TOP
> } alignMode;
113,132c103,126
< static Tk_ConfigSpec configSpecs[] = {
<     {TK_CONFIG_CUSTOM, "-align", (char *) NULL, (char *) NULL,
< 	"center", 0, TK_CONFIG_DONT_SET_DEFAULT, &alignOption},
<     {TK_CONFIG_STRING, "-create", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextEmbWindow, create),
< 	TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_INT, "-padx", (char *) NULL, (char *) NULL,
< 	"0", Tk_Offset(TkTextEmbWindow, padX),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_INT, "-pady", (char *) NULL, (char *) NULL,
< 	"0", Tk_Offset(TkTextEmbWindow, padY),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
< 	"0", Tk_Offset(TkTextEmbWindow, stretch),
< 	TK_CONFIG_DONT_SET_DEFAULT},
<     {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
< 	(char *) NULL, Tk_Offset(TkTextEmbWindow, tkwin),
< 	TK_CONFIG_DONT_SET_DEFAULT|TK_CONFIG_NULL_OK},
<     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
< 	(char *) NULL, 0, 0}
---
> /*
>  * Information used for parsing window configuration options:
>  */
> 
> static Tk_OptionSpec optionSpecs[] = {
>     {TK_OPTION_STRING_TABLE, "-align", (char *) NULL, (char *) NULL,
>         "center", -1, Tk_Offset(TkTextEmbWindow, align), 
> 	0, (ClientData) alignStrings, 0},
>     {TK_OPTION_STRING, "-create", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextEmbWindow, create),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_PIXELS, "-padx", (char *) NULL, (char *) NULL,
> 	"0", -1, Tk_Offset(TkTextEmbWindow, padX), 
> 	0, 0, 0},
>     {TK_OPTION_PIXELS, "-pady", (char *) NULL, (char *) NULL,
> 	"0", -1, Tk_Offset(TkTextEmbWindow, padY), 
> 	0, 0, 0},
>     {TK_OPTION_BOOLEAN, "-stretch", (char *) NULL, (char *) NULL,
> 	"0", -1, Tk_Offset(TkTextEmbWindow, stretch), 
> 	0, 0, 0},
>     {TK_OPTION_WINDOW, "-window", (char *) NULL, (char *) NULL,
> 	(char *) NULL, -1, Tk_Offset(TkTextEmbWindow, tkwin),
> 	TK_OPTION_NULL_OK, 0, 0},
>     {TK_OPTION_END}
154c148
< TkTextWindowCmd(textPtr, interp, argc, argv)
---
> TkTextWindowCmd(textPtr, interp, objc, objv)
157,158c151,152
<     int argc;			/* Number of arguments. */
<     CONST char **argv;		/* Argument strings.  Someone else has already
---
>     int objc;			/* Number of arguments. */
>     Tcl_Obj *CONST objv[];	/* Argument objects. Someone else has already
160c154
< 				 * argv[1] is "window". */
---
> 				 * objv[1] is "window". */
162c156,164
<     size_t length;
---
>     int optionIndex;
>     
>     static CONST char *windOptionStrings[] = {
> 	"cget", "configure", "create", "names", (char *) NULL 
>     };
>     enum windOptions {
> 	WIND_CGET, WIND_CONFIGURE, WIND_CREATE, WIND_NAMES
>     };
> 
165,167c167,168
<     if (argc < 3) {
< 	Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		argv[0], " window option ?arg arg ...?\"", (char *) NULL);
---
>     if (objc < 3) {
> 	Tcl_WrongNumArgs(interp, 2, objv, "option ?arg arg ...?");
170,209c171,202
<     length = strlen(argv[2]);
<     if ((strncmp(argv[2], "cget", length) == 0) && (length >= 2)) {
< 	TkTextIndex index;
< 	TkTextSegment *ewPtr;
< 
< 	if (argc != 5) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " window cget index option\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 	ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
< 	if (ewPtr->typePtr != &tkTextEmbWindowType) {
< 	    Tcl_AppendResult(interp, "no embedded window at index \"",
< 		    argv[3], "\"", (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	return Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs,
< 		(char *) &ewPtr->body.ew, argv[4], 0);
<     } else if ((strncmp(argv[2], "configure", length) == 0) && (length >= 2)) {
< 	TkTextIndex index;
< 	TkTextSegment *ewPtr;
< 
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " window configure index ?option value ...?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
< 	ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
< 	if (ewPtr->typePtr != &tkTextEmbWindowType) {
< 	    Tcl_AppendResult(interp, "no embedded window at index \"",
< 		    argv[3], "\"", (char *) NULL);
< 	    return TCL_ERROR;
---
>     if (Tcl_GetIndexFromObj(interp, objv[2], windOptionStrings, 
> 			    "window option", 0, &optionIndex) != TCL_OK) {
> 	return TCL_ERROR;
>     }
>     switch ((enum windOptions)optionIndex) {
> 	case WIND_CGET: {
> 	    TkTextIndex index;
> 	    TkTextSegment *ewPtr;
> 	    Tcl_Obj *objPtr;
> 	    
> 	    if (objc != 5) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "index option");
> 		return TCL_ERROR;
> 	    }
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
> 	    ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
> 	    if (ewPtr->typePtr != &tkTextEmbWindowType) {
> 		Tcl_AppendResult(interp, "no embedded window at index \"",
> 				 Tcl_GetString(objv[3]), "\"", (char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    objPtr = Tk_GetOptionValue(interp, (char *) &ewPtr->body.ew,
> 			ewPtr->body.ew.optionTable, objv[4], textPtr->tkwin);
> 	    if (objPtr == NULL) {
> 		return TCL_ERROR;
> 	    } else {
> 		Tcl_SetObjResult(interp, objPtr);
> 		return TCL_OK;
> 	    }
> 	    break;
211,219c204,236
< 	if (argc == 4) {
< 	    return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
< 		    (char *) &ewPtr->body.ew, (char *) NULL, 0);
< 	} else if (argc == 5) {
< 	    return Tk_ConfigureInfo(interp, textPtr->tkwin, configSpecs,
< 		    (char *) &ewPtr->body.ew, argv[4], 0);
< 	} else {
< 	    TkTextChanged(textPtr, &index, &index);
< 	    return EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4);
---
> 	case WIND_CONFIGURE: {
> 	    TkTextIndex index;
> 	    TkTextSegment *ewPtr;
> 
> 	    if (objc < 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
> 		return TCL_ERROR;
> 	    }
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
> 	    ewPtr = TkTextIndexToSeg(&index, (int *) NULL);
> 	    if (ewPtr->typePtr != &tkTextEmbWindowType) {
> 		Tcl_AppendResult(interp, "no embedded window at index \"",
> 				 Tcl_GetString(objv[3]), "\"", (char *) NULL);
> 		return TCL_ERROR;
> 	    }
> 	    if (objc <= 5) {
> 		Tcl_Obj* objPtr = Tk_GetOptionInfo(interp, (char *) &ewPtr->body.ew,
> 			ewPtr->body.ew.optionTable,
> 			(objc == 5) ? objv[4] : (Tcl_Obj *) NULL,
> 					  textPtr->tkwin);
> 		if (objPtr == NULL) {
> 		    return TCL_ERROR;
> 		} else {
> 		    Tcl_SetObjResult(interp, objPtr);
> 		    return TCL_OK;
> 		}
> 	    } else {
> 		TkTextChanged(textPtr, &index, &index);
> 		return EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4);
> 	    }
> 	    break;
221,228c238,240
<     } else if ((strncmp(argv[2], "create", length) == 0) && (length >= 2)) {
< 	TkTextIndex index;
< 	int lineIndex;
< 
< 	/*
< 	 * Add a new window.  Find where to put the new window, and
< 	 * mark that position for redisplay.
< 	 */
---
> 	case WIND_CREATE: {
> 	    TkTextIndex index;
> 	    int lineIndex;
230,238c242,245
< 	if (argc < 4) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " window create index ?option value ...?\"",
< 		    (char *) NULL);
< 	    return TCL_ERROR;
< 	}
< 	if (TkTextGetIndex(interp, textPtr, argv[3], &index) != TCL_OK) {
< 	    return TCL_ERROR;
< 	}
---
> 	    /*
> 	     * Add a new window.  Find where to put the new window, and
> 	     * mark that position for redisplay.
> 	     */
240,248c247,253
< 	/*
< 	 * Don't allow insertions on the last (dummy) line of the text.
< 	 */
<     
< 	lineIndex = TkBTreeLineIndex(index.linePtr);
< 	if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
< 	    lineIndex--;
< 	    TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
< 	}
---
> 	    if (objc < 4) {
> 		Tcl_WrongNumArgs(interp, 3, objv, "index ?option value ...?");
> 		return TCL_ERROR;
> 	    }
> 	    if (TkTextGetObjIndex(interp, textPtr, objv[3], &index) != TCL_OK) {
> 		return TCL_ERROR;
> 	    }
250,252c255,263
< 	/*
< 	 * Create the new window segment and initialize it.
< 	 */
---
> 	    /*
> 	     * Don't allow insertions on the last (dummy) line of the text.
> 	     */
> 	
> 	    lineIndex = TkBTreeLineIndex(index.linePtr);
> 	    if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
> 		lineIndex--;
> 		TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, &index);
> 	    }
254,265c265,267
< 	ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);
< 	ewPtr->typePtr = &tkTextEmbWindowType;
< 	ewPtr->size = 1;
< 	ewPtr->body.ew.textPtr = textPtr;
< 	ewPtr->body.ew.linePtr = NULL;
< 	ewPtr->body.ew.tkwin = NULL;
< 	ewPtr->body.ew.create = NULL;
< 	ewPtr->body.ew.align = ALIGN_CENTER;
< 	ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
< 	ewPtr->body.ew.stretch = 0;
< 	ewPtr->body.ew.chunkCount = 0;
< 	ewPtr->body.ew.displayed = 0;
---
> 	    /*
> 	     * Create the new window segment and initialize it.
> 	     */
267,270c269,285
< 	/*
< 	 * Link the segment into the text widget, then configure it (delete
< 	 * it again if the configuration fails).
< 	 */
---
> 	    ewPtr = (TkTextSegment *) ckalloc(EW_SEG_SIZE);
> 	    ewPtr->typePtr = &tkTextEmbWindowType;
> 	    ewPtr->size = 1;
> 	    ewPtr->body.ew.textPtr = textPtr;
> 	    ewPtr->body.ew.linePtr = NULL;
> 	    ewPtr->body.ew.tkwin = NULL;
> 	    ewPtr->body.ew.create = NULL;
> 	    ewPtr->body.ew.align = ALIGN_CENTER;
> 	    ewPtr->body.ew.padX = ewPtr->body.ew.padY = 0;
> 	    ewPtr->body.ew.stretch = 0;
> 	    ewPtr->body.ew.chunkCount = 0;
> 	    ewPtr->body.ew.displayed = 0;
> 	    ewPtr->body.ew.optionTable = Tk_CreateOptionTable(interp, optionSpecs);
> 	    /*
> 	     * Link the segment into the text widget, then configure it (delete
> 	     * it again if the configuration fails).
> 	     */
272,288c287,296
< 	TkTextChanged(textPtr, &index, &index);
< 	TkBTreeLinkSegment(ewPtr, &index);
< 	if (EmbWinConfigure(textPtr, ewPtr, argc-4, argv+4) != TCL_OK) {
< 	    TkTextIndex index2;
< 
< 	    TkTextIndexForwChars(&index, 1, &index2);
< 	    TkBTreeDeleteChars(&index, &index2);
< 	    return TCL_ERROR;
< 	}
<     } else if (strncmp(argv[2], "names", length) == 0) {
< 	Tcl_HashSearch search;
< 	Tcl_HashEntry *hPtr;
< 
< 	if (argc != 3) {
< 	    Tcl_AppendResult(interp, "wrong # args: should be \"",
< 		    argv[0], " window names\"", (char *) NULL);
< 	    return TCL_ERROR;
---
> 	    TkTextChanged(textPtr, &index, &index);
> 	    TkBTreeLinkSegment(ewPtr, &index);
> 	    if (EmbWinConfigure(textPtr, ewPtr, objc-4, objv+4) != TCL_OK) {
> 		TkTextIndex index2;
> 
> 		TkTextIndexForwChars(&index, 1, &index2);
> 		TkBTreeDeleteChars(&index, &index2);
> 		return TCL_ERROR;
> 	    }
> 	    break;
290,293c298,311
< 	for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);
< 		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
< 	    Tcl_AppendElement(interp,
< 		    Tcl_GetHashKey(&textPtr->markTable, hPtr));
---
> 	case WIND_NAMES: {
> 	    Tcl_HashSearch search;
> 	    Tcl_HashEntry *hPtr;
> 
> 	    if (objc != 3) {
> 		Tcl_WrongNumArgs(interp, 3, objv, NULL);
> 		return TCL_ERROR;
> 	    }
> 	    for (hPtr = Tcl_FirstHashEntry(&textPtr->windowTable, &search);
> 		    hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
> 		Tcl_AppendElement(interp,
> 			Tcl_GetHashKey(&textPtr->markTable, hPtr));
> 	    }
> 	    break;
295,299d312
<     } else {
< 	Tcl_AppendResult(interp, "bad window option \"", argv[2],
< 		"\": must be cget, configure, create, or names",
< 		(char *) NULL);
< 	return TCL_ERROR;
310c323
<  *	for an embedded window, using an argc/argv list.
---
>  *	for an embedded window, using an objc/objv list.
325c338
< EmbWinConfigure(textPtr, ewPtr, argc, argv)
---
> EmbWinConfigure(textPtr, ewPtr, objc, objv)
329,330c342,343
<     int argc;			/* Number of strings in argv. */
<     CONST char **argv;		/* Array of strings describing configuration
---
>     int objc;			/* Number of strings in objv. */
>     Tcl_Obj *CONST objv[];	/* Array of objects describing configuration
338,340c351,353
<     if (Tk_ConfigureWidget(textPtr->interp, textPtr->tkwin, configSpecs,
< 	    argc, argv, (char *) &ewPtr->body.ew, TK_CONFIG_ARGV_ONLY)
< 	    != TCL_OK) {
---
>     if (Tk_SetOptions(textPtr->interp, (char*)&ewPtr->body.ew, 
>             ewPtr->body.ew.optionTable,
> 	    objc, objv, textPtr->tkwin, NULL, NULL) != TCL_OK) {
417,509d429
<  * AlignParseProc --
<  *
<  *	This procedure is invoked by Tk_ConfigureWidget during
<  *	option processing to handle "-align" options for embedded
<  *	windows.
<  *
<  * Results:
<  *	A standard Tcl return value.
<  *
<  * Side effects:
<  *	The alignment for the embedded window may change.
<  *
<  *--------------------------------------------------------------
<  */
< 
< 	/* ARGSUSED */
< static int
< AlignParseProc(clientData, interp, tkwin, value, widgRec, offset)
<     ClientData clientData;		/* Not used.*/
<     Tcl_Interp *interp;			/* Used for reporting errors. */
<     Tk_Window tkwin;			/* Window for text widget. */
<     CONST char *value;			/* Value of option. */
<     char *widgRec;			/* Pointer to TkTextEmbWindow
< 					 * structure. */
<     int offset;				/* Offset into item (ignored). */
< {
<     register TkTextEmbWindow *embPtr = (TkTextEmbWindow *) widgRec;
< 
<     if (strcmp(value, "baseline") == 0) {
< 	embPtr->align = ALIGN_BASELINE;
<     } else if (strcmp(value, "bottom") == 0) {
< 	embPtr->align = ALIGN_BOTTOM;
<     } else if (strcmp(value, "center") == 0) {
< 	embPtr->align = ALIGN_CENTER;
<     } else if (strcmp(value, "top") == 0) {
< 	embPtr->align = ALIGN_TOP;
<     } else {
< 	Tcl_AppendResult(interp, "bad alignment \"", value,
< 		"\": must be baseline, bottom, center, or top",
< 		(char *) NULL);
< 	return TCL_ERROR;
<     }
<     return TCL_OK;
< }
< 
< /*
<  *--------------------------------------------------------------
<  *
<  * AlignPrintProc --
<  *
<  *	This procedure is invoked by the Tk configuration code
<  *	to produce a printable string for the "-align" configuration
<  *	option for embedded windows.
<  *
<  * Results:
<  *	The return value is a string describing the embedded
<  *	window's current alignment.
<  *
<  * Side effects:
<  *	None.
<  *
<  *--------------------------------------------------------------
<  */
< 
< 	/* ARGSUSED */
< static char *
< AlignPrintProc(clientData, tkwin, widgRec, offset, freeProcPtr)
<     ClientData clientData;		/* Ignored. */
<     Tk_Window tkwin;			/* Window for text widget. */
<     char *widgRec;			/* Pointer to TkTextEmbWindow
< 					 * structure. */
<     int offset;				/* Ignored. */
<     Tcl_FreeProc **freeProcPtr;		/* Pointer to variable to fill in with
< 					 * information about how to reclaim
< 					 * storage for return string. */
< {
<     switch (((TkTextEmbWindow *) widgRec)->align) {
< 	case ALIGN_BASELINE:
< 	    return "baseline";
< 	case ALIGN_BOTTOM:
< 	    return "bottom";
< 	case ALIGN_CENTER:
< 	    return "center";
< 	case ALIGN_TOP:
< 	    return "top";
< 	default:
< 	    return "??";
<     }
< }
< 
< /*
<  *--------------------------------------------------------------
<  *
681,682c601,602
<     Tk_FreeOptions(configSpecs, (char *) &ewPtr->body.ew,
< 	    ewPtr->body.ew.textPtr->display, 0);
---
>     Tk_FreeConfigOptions((char *) &ewPtr->body.ew, ewPtr->body.ew.optionTable,
> 			 ewPtr->body.ew.tkwin);
Index: generic/tkUndo.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkUndo.c,v
retrieving revision 1.1
diff -r1.1 tkUndo.c
15a16,18
> static int UndoScriptsEvaluate _ANSI_ARGS_ ((Tcl_Interp *interp, 
> 				     Tcl_Obj *objPtr, TkUndoAtomType type));
> 
115c118,120
<  *    action and revert are given through Tcl_DStrings
---
>  *    action and revert are given through Tcl_Obj's to which
>  *    we will retain a reference.  (So they can be passed in
>  *    with a zero refCount if desired).
124,127c129,133
< void TkUndoPushAction ( stack, actionScript, revertScript )
<     TkUndoRedoStack * stack;      /* An Undo or Redo stack */
<     Tcl_DString * actionScript; /* The script to get the action (redo) */
<     Tcl_DString * revertScript; /* The script to revert the action (undo) */
---
> void TkUndoPushAction ( stack, actionScript, revertScript, isList )
>     TkUndoRedoStack *stack;   /* An Undo or Redo stack */
>     Tcl_Obj *actionScript;    /* The script to get the action (redo) */
>     Tcl_Obj *revertScript;    /* The script to revert the action (undo) */
>     int isList;               /* Are the given objects lists of scripts? */
132c138,142
<     atom->type = TK_UNDO_ACTION;
---
>     if (isList) {
> 	atom->type = TK_UNDO_ACTION_LIST;
>     } else {
> 	atom->type = TK_UNDO_ACTION;
>     }
134c144
<     atom->apply = Tcl_NewStringObj(Tcl_DStringValue(actionScript),Tcl_DStringLength(actionScript));
---
>     atom->apply = actionScript;
137c147
<     atom->revert = Tcl_NewStringObj(Tcl_DStringValue(revertScript),Tcl_DStringLength(revertScript));
---
>     atom->revert = revertScript;
336c346
<         Tcl_EvalObjEx(stack->interp,elem->revert,TCL_EVAL_GLOBAL);
---
> 	UndoScriptsEvaluate(stack->interp,elem->revert,elem->type);
350d359
< 
386c395
<         Tcl_EvalObjEx(stack->interp,elem->apply,TCL_EVAL_GLOBAL);
---
> 	UndoScriptsEvaluate(stack->interp,elem->apply,elem->type);
398a408,444
> }
> 
> 
> /*
>  * UndoScriptsEvaluate --
>  *    Execute either a single script, or a set of scripts
>  *
>  * Results:
>  *    A TCL status code
>  *
>  * Side effects:
>  *    None.
>  */
> static int 
> UndoScriptsEvaluate(interp, objPtr, type)
>     Tcl_Interp *interp;
>     Tcl_Obj *objPtr;
>     TkUndoAtomType type;
> {
>     if (type == TK_UNDO_ACTION_LIST) {
> 	int objc;
> 	Tcl_Obj **objv;
> 	int res, i;
> 	res = Tcl_ListObjGetElements(interp, objPtr, &objc, &objv);
> 	if (res != TCL_OK) {
> 	    return res;
> 	}
> 	for (i=0;i<objc;i++) {
> 	    res = Tcl_EvalObjEx(interp, objv[i], TCL_EVAL_GLOBAL);
> 	    if (res != TCL_OK) {
> 	        return res;
> 	    }
> 	}
> 	return res;
>     } else {
> 	return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL);
>     }
Index: generic/tkUndo.h
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkUndo.h,v
retrieving revision 1.1
diff -r1.1 tkUndo.h
31c31,32
<     TK_UNDO_ACTION			   /* Command */
---
>     TK_UNDO_ACTION,			/* Command */
>     TK_UNDO_ACTION_LIST			/* Command list */
37,40c38,42
<     TkUndoAtomType type;		 /* The type that will trigger the
< 					 * required action*/
<     Tcl_Obj * apply;			   /* Command to apply the action that was taken */
<     Tcl_Obj * revert;			/* The command to undo the action */
---
>     TkUndoAtomType type;	/* The type that will trigger the
> 				 * required action*/
>     Tcl_Obj *apply;		/* Command to apply the action that 
>                    		 * was taken */
>     Tcl_Obj *revert;		/* The command to undo the action */
42c44
< 					 * stack */
---
> 				 * stack */
48,50c50,53
<     TkUndoAtom * undoStack;		 /* The undo stack */
<     TkUndoAtom * redoStack;		 /* The redo stack */
<     Tcl_Interp * interp   ;       /* The interpreter in which to execute the revert and apply scripts */
---
>     TkUndoAtom * undoStack;	  /* The undo stack */
>     TkUndoAtom * redoStack;	  /* The redo stack */
>     Tcl_Interp * interp   ;       /* The interpreter in which to execute 
>                                    * the revert and apply scripts */
81c84
<     Tcl_DString * actionScript, Tcl_DString * revertScript));
---
>     Tcl_Obj *actionScript, Tcl_Obj *revertScript, int isList));
Index: generic/tkWindow.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkWindow.c,v
retrieving revision 1.54
diff -r1.54 tkWindow.c
151c151
<     {"text",		Tk_TextCmd,		NULL,			1, 1},
---
>     {"text",		NULL,		        Tk_TextObjCmd,		1, 1},
Index: tests/text.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/text.test,v
retrieving revision 1.19
diff -r1.19 text.test
225c225
< } {1 {bad option "co": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
---
> } {1 {ambiguous option "co": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
234c234
< } {1 {bad option "de": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
---
> } {1 {ambiguous option "de": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
394c394
< } {1 {bad option "in": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
---
> } {1 {ambiguous option "in": must be bbox, cget, compare, configure, debug, delete, dlineinfo, dump, edit, get, image, index, insert, mark, scan, search, see, tag, window, xview, or yview}}
457c457
< } {1 {bad state value "foobar": must be normal or disabled}}
---
> } {1 {bad state "foobar": must be disabled or normal}}
485c485
< } {1 {bad wrap mode "bogus": must be char, none, or word}}
---
> } {1 {bad wrap "bogus": must be char, none, or word}}
938c938
< } {1 {bad switch "-": must be --, -backward, -count, -elide, -exact, -forward, -nocase, or -regexp}}
---
> } {1 {bad switch "-": must be --, -all, -backward, -count, -elide, -exact, -forward, -nocase, or -regexp}}
1012c1012
< test text-20.25 {TextSearchCmd procedure, stripping newlines} {
---
> test text-20.25 {TextSearchCmd procedure, handling newlines} {
1014c1014
< } {}
---
> } {1.12}
1018c1018
< test text-20.27 {TextSearchCmd procedure, stripping newlines} {
---
> test text-20.27 {TextSearchCmd procedure, handling newlines} {
1020c1020
< } {}
---
> } {1.15}
1247c1247,1503
<     
---
> test text-20.73 {TextSearchCmd, hidden text and start index} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search bar 1.3
> } 1.3
> test text-20.74 {TextSearchCmd, hidden text shouldn't influence start index} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 tag configure hidden -elide true
>     .t2 tag add hidden 1.0 1.2
>     .t2 search bar 1.3
> } 1.3
> test text-20.75 {TextSearchCmd, hidden text inside match must count in length} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 tag configure hidden -elide true
>     .t2 tag add hidden 1.2 1.4
>     list [.t2 search -count foo foar 1.3] $foo
> } {1.0 6}
> test text-20.76 {TextSearchCmd, hidden text and start index} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search -regexp bar 1.3
> } 1.3
> test text-20.77 {TextSearchCmd, hidden text shouldn't influence start index} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 tag configure hidden -elide true
>     .t2 tag add hidden 1.0 1.2
>     .t2 search -regexp bar 1.3
> } 1.3
> test text-20.78 {TextSearchCmd, hidden text inside match must count in length} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 tag configure hidden -elide true
>     .t2 tag add hidden 1.2 1.4
>     list [.t2 search -regexp -count foo foar 1.3] $foo
> } {1.0 6}
> 
> test text-20.79 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -count foo foobar\nfoo 1.0] $foo
> } {1.0 10}
> 
> test text-20.80 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -count foo bar\nfoo 1.0] $foo
> } {1.3 7}
> 
> test text-20.81 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -count foo \nfoo 1.0] $foo
> } {1.6 4}
> 
> test text-20.82 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -count foo bar\nfoobar\nfoo 1.0] $foo
> } {1.3 14}
> 
> test text-20.83 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search -count foo bar\nfoobar\nfoobanearly 1.0
> } {}
> 
> test text-20.84 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -regexp -count foo foobar\nfoo 1.0] $foo
> } {1.0 10}
> 
> test text-20.85 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -regexp -count foo bar\nfoo 1.0] $foo
> } {1.3 7}
> 
> test text-20.86 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -regexp -count foo \nfoo 1.0] $foo
> } {1.6 4}
> 
> test text-20.87 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -regexp -count foo bar\nfoobar\nfoo 1.0] $foo
> } {1.3 14}
> 
> test text-20.88 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search -regexp -count foo bar\nfoobar\nfoobanearly 1.0
> } {}
> 
> test text-20.89 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfaoobar\nfoobar"
>     .t2 search -regexp -count foo bar\nfoo 1.0
> } {2.4}
> 
> test text-20.90 {TextSearchCmd, multiline matching end of window} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfaoobar\nfoobar"
>     .t2 search -regexp -count foo bar\nfoobar\n\n 1.0
> } {}
> 
> test text-20.91 {TextSearchCmd, multiline matching end of window} {
>     deleteWindows
>     pack [text .t2]
>     .t2 search "\n\n" 1.0
> } {}
> 
> test text-20.92 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -count foo foobar\nfoo end] $foo
> } {2.0 10}
> 
> test text-20.93 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -count foo bar\nfoo 1.0] $foo
> } {2.3 7}
> 
> test text-20.94 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -count foo \nfoo 1.0] $foo
> } {2.6 4}
> 
> test text-20.95 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -count foo bar\nfoobar\nfoo 1.0] $foo
> } {1.3 14}
> 
> test text-20.96 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search -backwards -count foo bar\nfoobar\nfoobanearly 1.0
> } {}
> 
> test text-20.97 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -regexp -count foo foobar\nfoo 1.0] $foo
> } {2.0 10}
> 
> test text-20.98 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -regexp -count foo bar\nfoo 1.0] $foo
> } {2.3 7}
> 
> test text-20.99 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -regexp -count foo \nfoo 1.0] $foo
> } {2.6 4}
> 
> test text-20.100 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     list [.t2 search -backwards -regexp -count foo bar\nfoobar\nfoo 1.0] $foo
> } {1.3 14}
> 
> test text-20.101 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfoobar\nfoobar"
>     .t2 search -backwards -regexp -count foo bar\nfoobar\nfoobanearly 1.0
> } {}
> 
> test text-20.102 {TextSearchCmd, multiline matching} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfaoobar\nfoobar"
>     .t2 search -backwards -regexp -count foo bar\nfoo 1.0
> } {2.4}
> 
> test text-20.103 {TextSearchCmd, multiline matching end of window} {
>     deleteWindows
>     pack [text .t2]
>     .t2 insert end "foobar\nfaoobar\nfoobar"
>     .t2 search -backwards -regexp -count foo bar\nfoobar\n\n 1.0
> } {}
> 
> test text-20.104 {TextSearchCmd, multiline matching end of window} {
>     deleteWindows
>     pack [text .t2]
>     .t2 search -backwards "\n\n" 1.0
> } {}
> 
> test text-20.105 {TextSearchCmd, multiline regexp matching} {
>     # This practical test is ok, but the similar 20.106 crashes
>     return
>     deleteWindows
>     pack [text .t2]
>     .t2 insert 1.0 {    Tcl_Obj *objPtr));
> static Tcl_Obj*         FSNormalizeAbsolutePath 
> 			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
>     set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
>     append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
>     append markExpr "\[ \n\t\r\]*\\()"
>     .t2 search -forwards -regexp $markExpr 1.41 end
> } {}
> 
> test text-20.106 {TextSearchCmd, multiline regexp matching} {
>     # Practical example which crashes Tk, but only after the
>     # search is complete.  This is memory corruption caused by
>     # a bug in Tcl's handling of string objects.
>     deleteWindows
>     pack [text .t2]
>     .t2 insert 1.0 {static int		SetFsPathFromAny _ANSI_ARGS_((Tcl_Interp *interp,
> 			    Tcl_Obj *objPtr));
> static Tcl_Obj*         FSNormalizeAbsolutePath 
> 			    _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj *pathPtr));}
>     set markExpr "^(\[A-Za-z0-9~_\]+\[ \t\n\r\]*\\(|(\[^ \t\(#\n\r/@:\*\]\[^=\(\r\n\]*\[ \t\]+\\*?)?"
>     append markExpr "(\[A-Za-z0-9~_\]+(<\[^>\]*>)?(::)?(\[A-Za-z0-9~_\]+::)*\[-A-Za-z0-9~_+ <>\|\\*/\]+|\[A-Za-z0-9~_\]+)"
>     append markExpr "\[ \n\t\r\]*\\()"
>     .t2 search -forwards -regexp $markExpr 1.41 end
> } {}
> 
> 
> 
1456c1712
< } {1 {bad edit option "gorp": must be modified, redo, reset, separator or undo}}
---
> } {1 {bad edit option "gorp": must be modified, redo, reset, separator, or undo}}
Index: tests/textIndex.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/textIndex.test,v
retrieving revision 1.7
diff -r1.7 textIndex.test
660d659
< 
668a668,685
> 
> test testIndex-17.1 {Object indices} {
>     set res {}
>     set t [text .t2 -height 20]
>     for {set i 0} {$i < 100} {incr i} {
> 	$t insert end $i\n
>     }
>     pack $t
>     update
>     set idx @0,0
>     lappend res $idx [$t index $idx]
>     $t yview scroll 2 pages
>     lappend res $idx [$t index $idx]
>     catch {destroy $t}
>     unset i
>     unset idx
>     list $res
> } {{@0,0 1.0 @0,0 37.0}}
Index: tests/textMark.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/textMark.test,v
retrieving revision 1.5
diff -r1.5 textMark.test
85c85
<     lsort [.t mark n]
---
>     lsort [.t mark na]
Index: tests/textTag.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/textTag.test,v
retrieving revision 1.6
diff -r1.6 textTag.test
107c107
< } {1 {bad tag option "gorp": must be add, bind, cget, configure, delete, lower, names, nextrange, raise, ranges, or remove}}
---
> } {1 {bad tag option "gorp": must be add, bind, cget, configure, delete, lower, names, nextrange, prevrange, raise, ranges, or remove}}
319c319
< } {1 {wrong # args: should be ".t tag delete tagName tagName ..."}}
---
> } {1 {wrong # args: should be ".t tag delete tagName ?tagName ...?"}}
Index: tests/textWind.test
===================================================================
RCS file: /cvsroot/tktoolkit/tk/tests/textWind.test,v
retrieving revision 1.5
diff -r1.5 textWind.test
24c24
<     option add *Text.font {Courier -14}
---
>     option add *Text.font {Courier -12}
197c197
< } {1 {bad window option "c": must be cget, configure, create, or names}}
---
> } {1 {ambiguous window option "c": must be cget, configure, create, or names}}
314c314
< } {1 {bad alignment "gorp": must be baseline, bottom, center, or top} {-align {} {} center top}}
---
> } {1 {bad align "gorp": must be baseline, bottom, center, or top} {-align {} {} center top}}
Index: win/makefile.vc
===================================================================
RCS file: /cvsroot/tktoolkit/tk/win/makefile.vc,v
retrieving revision 1.65
diff -r1.65 makefile.vc
209,210c209
< 	$(TMP_DIR)\tkWinTest.obj \
< 	$(TCLTMP_DIR)\tclThreadTest.obj
---
> 	$(TMP_DIR)\tkWinTest.obj
453c452
< 	$(TKTEST) $(ROOT)/tests/all.tcl $(TESTFLAGS) | $(CAT32)
---
> 	$(TKTEST) $(ROOT)\tests\all.tcl $(TESTFLAGS) | $(CAT32)
455c454
< 	$(TKTEST) $(ROOT)/tests/all.tcl $(TESTFLAGS) | $(CAT32)
---
> 	$(TKTEST) $(ROOT)\tests\all.tcl $(TESTFLAGS) | $(CAT32)
