summaryrefslogtreecommitdiff
path: root/tk/generic/tkText.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk/generic/tkText.c')
-rw-r--r--tk/generic/tkText.c531
1 files changed, 335 insertions, 196 deletions
diff --git a/tk/generic/tkText.c b/tk/generic/tkText.c
index d9ff1cc9165..560c0260d9c 100644
--- a/tk/generic/tkText.c
+++ b/tk/generic/tkText.c
@@ -9,6 +9,7 @@
*
* Copyright (c) 1992-1994 The Regents of the University of California.
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -28,6 +29,15 @@
#include "tkText.h"
/*
+ * Custom options for handling "-state"
+ */
+
+static Tk_CustomOption stateOption = {
+ (Tk_OptionParseProc *) TkStateParseProc,
+ TkStatePrintProc, (ClientData) NULL /* only "normal" and "disabled" */
+};
+
+/*
* Information used to parse text configuration options:
*/
@@ -112,8 +122,8 @@ static Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_PIXELS, "-spacing3", "spacing3", "Spacing",
DEF_TEXT_SPACING3, Tk_Offset(TkText, spacing3),
TK_CONFIG_DONT_SET_DEFAULT},
- {TK_CONFIG_UID, "-state", "state", "State",
- DEF_TEXT_STATE, Tk_Offset(TkText, state), 0},
+ {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",
@@ -121,8 +131,8 @@ static Tk_ConfigSpec configSpecs[] = {
TK_CONFIG_NULL_OK},
{TK_CONFIG_INT, "-width", "width", "Width",
DEF_TEXT_WIDTH, Tk_Offset(TkText, width), 0},
- {TK_CONFIG_UID, "-wrap", "wrap", "Wrap",
- DEF_TEXT_WRAP, Tk_Offset(TkText, wrapMode), 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},
@@ -143,21 +153,133 @@ static Tk_ConfigSpec configSpecs[] = {
};
/*
- * Tk_Uid's used to represent text states:
+ * Boolean variable indicating whether or not special debugging code
+ * should be executed.
*/
-Tk_Uid tkTextCharUid = NULL;
-Tk_Uid tkTextDisabledUid = NULL;
-Tk_Uid tkTextNoneUid = NULL;
-Tk_Uid tkTextNormalUid = NULL;
-Tk_Uid tkTextWordUid = NULL;
+int tkTextDebug = 0;
/*
- * Boolean variable indicating whether or not special debugging code
- * should be executed.
+ * Custom options for handling "-wrap":
*/
-int tkTextDebug = 0;
+static int WrapModeParseProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, 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
+};
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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. */
+ 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;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+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 "";
+ }
+}
/*
* Forward declarations for procedures defined later in this file:
@@ -189,7 +311,7 @@ static void DumpLine _ANSI_ARGS_((Tcl_Interp *interp,
TkText *textPtr, int what, TkTextLine *linePtr,
int start, int end, int lineno, char *command));
static int DumpSegment _ANSI_ARGS_((Tcl_Interp *interp, char *key,
- char *value, char * command, int lineno, int offset,
+ char *value, char * command, TkTextIndex *index,
int what));
/*
@@ -241,18 +363,6 @@ Tk_TextCmd(clientData, interp, argc, argv)
}
/*
- * Perform once-only initialization:
- */
-
- if (tkTextNormalUid == NULL) {
- tkTextCharUid = Tk_GetUid("char");
- tkTextDisabledUid = Tk_GetUid("disabled");
- tkTextNoneUid = Tk_GetUid("none");
- tkTextNormalUid = Tk_GetUid("normal");
- tkTextWordUid = Tk_GetUid("word");
- }
-
- /*
* Create the window.
*/
@@ -274,7 +384,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
Tcl_InitHashTable(&textPtr->markTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&textPtr->windowTable, TCL_STRING_KEYS);
Tcl_InitHashTable(&textPtr->imageTable, TCL_STRING_KEYS);
- textPtr->state = tkTextNormalUid;
+ textPtr->state = TK_STATE_NORMAL;
textPtr->border = NULL;
textPtr->borderWidth = 0;
textPtr->padX = 0;
@@ -293,14 +403,14 @@ Tk_TextCmd(clientData, interp, argc, argv)
textPtr->tabOptionString = NULL;
textPtr->tabsize = 8;
textPtr->tabArrayPtr = NULL;
- textPtr->wrapMode = tkTextCharUid;
+ textPtr->wrapMode = TEXT_WRAPMODE_CHAR;
textPtr->width = 0;
textPtr->height = 0;
textPtr->setGrid = 0;
textPtr->prevWidth = Tk_Width(new);
textPtr->prevHeight = Tk_Height(new);
TkTextCreateDInfo(textPtr);
- TkTextMakeIndex(textPtr->tree, 0, 0, &startIndex);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &startIndex);
TkTextSetYView(textPtr, &startIndex, 0);
textPtr->selTagPtr = NULL;
textPtr->selBorder = NULL;
@@ -336,7 +446,8 @@ Tk_TextCmd(clientData, interp, argc, argv)
*/
textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel");
- textPtr->selTagPtr->reliefString = (char *) ckalloc(7);
+ textPtr->selTagPtr->reliefString =
+ (char *) ckalloc(sizeof(DEF_TEXT_SELECT_RELIEF));
strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF);
textPtr->selTagPtr->relief = TK_RELIEF_RAISED;
textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex);
@@ -357,7 +468,7 @@ Tk_TextCmd(clientData, interp, argc, argv)
Tk_DestroyWindow(textPtr->tkwin);
return TCL_ERROR;
}
- interp->result = Tk_PathName(textPtr->tkwin);
+ Tcl_SetResult(interp, Tk_PathName(textPtr->tkwin), TCL_STATIC);
return TCL_OK;
}
@@ -474,7 +585,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
goto done;
}
if (TkTextCharBbox(textPtr, &index1, &x, &y, &width, &height) == 0) {
- sprintf(interp->result, "%d %d %d %d", x, y, width, height);
+ char buf[TCL_INTEGER_SPACE * 4];
+
+ sprintf(buf, "%d %d %d %d", x, y, width, height);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0)
&& (length >= 2)) {
@@ -532,7 +646,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
} else {
goto compareError;
}
- interp->result = (value) ? "1" : "0";
+ Tcl_SetResult(interp, ((value) ? "1" : "0"), TCL_STATIC);
} else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)
&& (length >= 3)) {
if (argc == 2) {
@@ -554,7 +668,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
goto done;
}
if (argc == 2) {
- interp->result = (tkBTreeDebug) ? "1" : "0";
+ Tcl_SetResult(interp, ((tkBTreeDebug) ? "1" : "0"), TCL_STATIC);
} else {
if (Tcl_GetBoolean(interp, argv[2], &tkBTreeDebug) != TCL_OK) {
result = TCL_ERROR;
@@ -573,18 +687,7 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == tkTextNormalUid) {
- /*
- * KHAMIS
- * Call synchronize command
- * BEFORE INSERTING INTO THE EDITOR
- ***********************************/
- if (textPtr->SyncCmd && *textPtr->SyncCmd) {
- result = ExecSyncCmd (interp, textPtr, argc, argv);
- if (result == TCL_ERROR) {
- goto done;
- }
- }
+ if (textPtr->state == TK_STATE_NORMAL) {
result = DeleteChars(textPtr, argv[2],
(argc == 4) ? argv[3] : (char *) NULL);
}
@@ -604,8 +707,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
}
if (TkTextDLineInfo(textPtr, &index1, &x, &y, &width, &height, &base)
== 0) {
- sprintf(interp->result, "%d %d %d %d %d", x, y, width,
- height, base);
+ char buf[TCL_INTEGER_SPACE * 5];
+
+ sprintf(buf, "%d %d %d %d %d", x, y, width, height, base);
+ Tcl_SetResult(interp, buf, TCL_VOLATILE);
}
} else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
if ((argc != 3) && (argc != 4)) {
@@ -638,10 +743,10 @@ TextWidgetCmd(clientData, interp, argc, argv)
if (index1.linePtr == index2.linePtr) {
int last2;
- if (index2.charIndex == index1.charIndex) {
+ if (index2.byteIndex == index1.byteIndex) {
break;
}
- last2 = index2.charIndex - index1.charIndex + offset;
+ last2 = index2.byteIndex - index1.byteIndex + offset;
if (last2 < last) {
last = last2;
}
@@ -653,10 +758,12 @@ TextWidgetCmd(clientData, interp, argc, argv)
(char *) NULL);
segPtr->body.chars[last] = savedChar;
}
- TkTextIndexForwChars(&index1, last-offset, &index1);
+ TkTextIndexForwBytes(&index1, last-offset, &index1);
}
} 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\"",
@@ -668,7 +775,8 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- TkTextPrintIndex(&index1, interp->result);
+ 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;
@@ -689,22 +797,11 @@ TextWidgetCmd(clientData, interp, argc, argv)
result = TCL_ERROR;
goto done;
}
- if (textPtr->state == tkTextNormalUid) {
- /*
- * KHAMIS
- * Call synchronize command
- * BEFORE INSERTING INTO THE EDITOR
- ***********************************/
- if (textPtr->SyncCmd && *textPtr->SyncCmd) {
- result = ExecSyncCmd (interp, textPtr, argc, argv);
- if (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)) {
- TkTextIndexForwChars(&index1, (int) strlen(argv[j]),
+ TkTextIndexForwBytes(&index1, (int) strlen(argv[j]),
&index2);
oldTagArrayPtr = TkBTreeGetTags(&index1, &numTags);
if (oldTagArrayPtr != NULL) {
@@ -752,8 +849,8 @@ TextWidgetCmd(clientData, interp, argc, argv)
} else {
Tcl_AppendResult(interp, "bad option \"", argv[1],
"\": must be bbox, cget, compare, configure, debug, delete, ",
- "dlineinfo, get, image, index, insert, mark, scan, search, see, ",
- "tag, window, xview, or yview",
+ "dlineinfo, dump, get, image, index, insert, mark, scan, ",
+ "search, see, tag, window, xview, or yview",
(char *) NULL);
result = TCL_ERROR;
}
@@ -845,7 +942,7 @@ DestroyText(memPtr)
*
* Results:
* The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then interp->result contains an error message.
+ * returned, then the interp's result contains an error message.
*
* Side effects:
* Configuration information, such as text string, colors, font,
@@ -876,23 +973,6 @@ ConfigureText(interp, textPtr, argc, argv, flags)
* the geometry and setting the background from a 3-D border.
*/
- if ((textPtr->state != tkTextNormalUid)
- && (textPtr->state != tkTextDisabledUid)) {
- Tcl_AppendResult(interp, "bad state value \"", textPtr->state,
- "\": must be normal or disabled", (char *) NULL);
- textPtr->state = tkTextNormalUid;
- return TCL_ERROR;
- }
-
- if ((textPtr->wrapMode != tkTextCharUid)
- && (textPtr->wrapMode != tkTextNoneUid)
- && (textPtr->wrapMode != tkTextWordUid)) {
- Tcl_AppendResult(interp, "bad wrap mode \"", textPtr->wrapMode,
- "\": must be char, none, or word", (char *) NULL);
- textPtr->wrapMode = tkTextCharUid;
- return TCL_ERROR;
- }
-
Tk_SetBackgroundFromBorder(textPtr->tkwin, textPtr->border);
/*
@@ -967,7 +1047,8 @@ ConfigureText(interp, textPtr, argc, argv, flags)
|| (textPtr->selTagPtr->spacing3String != NULL)
|| (textPtr->selTagPtr->tabString != NULL)
|| (textPtr->selTagPtr->underlineString != NULL)
- || (textPtr->selTagPtr->wrapMode != NULL)) {
+ || (textPtr->selTagPtr->elideString != NULL)
+ || (textPtr->selTagPtr->wrapMode != TEXT_WRAPMODE_NULL)) {
textPtr->selTagPtr->affectsDisplay = 1;
}
TkTextRedrawTag(textPtr, (TkTextIndex *) NULL, (TkTextIndex *) NULL,
@@ -982,8 +1063,8 @@ ConfigureText(interp, textPtr, argc, argv, flags)
TkTextSearch search;
TkTextIndex first, last;
- TkTextMakeIndex(textPtr->tree, 0, 0, &first);
- TkTextMakeIndex(textPtr->tree,
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &first);
+ TkTextMakeByteIndex(textPtr->tree,
TkBTreeNumLines(textPtr->tree), 0, &last);
TkBTreeStartSearch(&first, &last, textPtr->selTagPtr, &search);
if (TkBTreeCharTagged(&first, textPtr->selTagPtr)
@@ -1214,7 +1295,7 @@ InsertChars(textPtr, indexPtr, string)
lineIndex = TkBTreeLineIndex(indexPtr->linePtr);
if (lineIndex == TkBTreeNumLines(textPtr->tree)) {
lineIndex--;
- TkTextMakeIndex(textPtr->tree, lineIndex, 1000000, indexPtr);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 1000000, indexPtr);
}
/*
@@ -1227,16 +1308,16 @@ InsertChars(textPtr, indexPtr, string)
resetView = offset = 0;
if (indexPtr->linePtr == textPtr->topIndex.linePtr) {
resetView = 1;
- offset = textPtr->topIndex.charIndex;
- if (offset > indexPtr->charIndex) {
+ offset = textPtr->topIndex.byteIndex;
+ if (offset > indexPtr->byteIndex) {
offset += strlen(string);
}
}
TkTextChanged(textPtr, indexPtr, indexPtr);
TkBTreeInsertChars(indexPtr, string);
if (resetView) {
- TkTextMakeIndex(textPtr->tree, lineIndex, 0, &newTop);
- TkTextIndexForwChars(&newTop, offset, &newTop);
+ TkTextMakeByteIndex(textPtr->tree, lineIndex, 0, &newTop);
+ TkTextIndexForwBytes(&newTop, offset, &newTop);
TkTextSetYView(textPtr, &newTop, 0);
}
@@ -1275,7 +1356,7 @@ DeleteChars(textPtr, index1String, index2String)
* delete the one character given by
* index1String. */
{
- int line1, line2, line, charIndex, resetView;
+ int line1, line2, line, byteIndex, resetView;
TkTextIndex index1, index2;
/*
@@ -1326,7 +1407,7 @@ DeleteChars(textPtr, index1String, index2String)
oldIndex2 = index2;
TkTextIndexBackChars(&oldIndex2, 1, &index2);
line2--;
- if ((index1.charIndex == 0) && (line1 != 0)) {
+ if ((index1.byteIndex == 0) && (line1 != 0)) {
TkTextIndexBackChars(&index1, 1, &index1);
line1--;
}
@@ -1349,7 +1430,9 @@ DeleteChars(textPtr, index1String, index2String)
*/
TkTextChanged(textPtr, &index1, &index2);
- resetView = line = charIndex = 0;
+ resetView = 0;
+ line = 0;
+ byteIndex = 0;
if (TkTextIndexCmp(&index2, &textPtr->topIndex) >= 0) {
if (TkTextIndexCmp(&index1, &textPtr->topIndex) <= 0) {
/*
@@ -1359,7 +1442,7 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line1;
- charIndex = index1.charIndex;
+ byteIndex = index1.byteIndex;
} else if (index1.linePtr == textPtr->topIndex.linePtr) {
/*
* Deletion range starts on top line but after topIndex.
@@ -1368,7 +1451,7 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line1;
- charIndex = textPtr->topIndex.charIndex;
+ byteIndex = textPtr->topIndex.byteIndex;
}
} else if (index2.linePtr == textPtr->topIndex.linePtr) {
/*
@@ -1379,16 +1462,16 @@ DeleteChars(textPtr, index1String, index2String)
resetView = 1;
line = line2;
- charIndex = textPtr->topIndex.charIndex;
+ byteIndex = textPtr->topIndex.byteIndex;
if (index1.linePtr != index2.linePtr) {
- charIndex -= index2.charIndex;
+ byteIndex -= index2.byteIndex;
} else {
- charIndex -= (index2.charIndex - index1.charIndex);
+ byteIndex -= (index2.byteIndex - index1.byteIndex);
}
}
TkBTreeDeleteChars(&index1, &index2);
if (resetView) {
- TkTextMakeIndex(textPtr->tree, line, charIndex, &index1);
+ TkTextMakeByteIndex(textPtr->tree, line, byteIndex, &index1);
TkTextSetYView(textPtr, &index1, 0);
}
@@ -1452,12 +1535,12 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
*/
if (offset == 0) {
- TkTextMakeIndex(textPtr->tree, 0, 0, &textPtr->selIndex);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &textPtr->selIndex);
textPtr->abortSelections = 0;
} else if (textPtr->abortSelections) {
return 0;
}
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof);
TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search);
if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) {
if (!TkBTreeNextTag(&search)) {
@@ -1504,8 +1587,8 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
if (textPtr->selIndex.linePtr == search.curIndex.linePtr) {
int leftInRange;
- leftInRange = search.curIndex.charIndex
- - textPtr->selIndex.charIndex;
+ leftInRange = search.curIndex.byteIndex
+ - textPtr->selIndex.byteIndex;
if (leftInRange < chunkSize) {
chunkSize = leftInRange;
if (chunkSize <= 0) {
@@ -1513,14 +1596,15 @@ TextFetchSelection(clientData, offset, buffer, maxBytes)
}
}
}
- if (segPtr->typePtr == &tkTextCharType) {
+ if ((segPtr->typePtr == &tkTextCharType)
+ && !TkTextIsElided(textPtr, &textPtr->selIndex)) {
memcpy((VOID *) buffer, (VOID *) (segPtr->body.chars
+ offsetInSeg), (size_t) chunkSize);
buffer += chunkSize;
maxBytes -= chunkSize;
count += chunkSize;
}
- TkTextIndexForwChars(&textPtr->selIndex, chunkSize,
+ TkTextIndexForwBytes(&textPtr->selIndex, chunkSize,
&textPtr->selIndex);
}
@@ -1577,8 +1661,8 @@ TkTextLostSelection(clientData)
* just remove the "sel" tag from everything in the widget.
*/
- TkTextMakeIndex(textPtr->tree, 0, 0, &start);
- TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end);
+ TkTextMakeByteIndex(textPtr->tree, 0, 0, &start);
+ TkTextMakeByteIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end);
TkTextRedrawTag(textPtr, &start, &end, textPtr->selTagPtr, 1);
TkBTreeTag(&start, &end, textPtr->selTagPtr, 0);
#endif
@@ -1611,7 +1695,8 @@ TextBlinkProc(clientData)
TkTextIndex index;
int x, y, w, h;
- if (!(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
+ if ((textPtr->state == TK_STATE_DISABLED) ||
+ !(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) {
return;
}
if (textPtr->flags & INSERT_ON) {
@@ -1654,10 +1739,10 @@ TextSearchCmd(textPtr, interp, argc, argv)
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
- int backwards, exact, c, i, argsLeft, noCase, leftToScan;
+ int backwards, exact, searchElide, c, i, argsLeft, noCase, leftToScan;
size_t length;
- int numLines, startingLine, startingChar, lineNum, firstChar, lastChar;
- int code, matchLength, matchChar, passes, stopLine, searchWholeText;
+ int numLines, startingLine, startingByte, lineNum, firstByte, lastByte;
+ int code, matchLength, matchByte, passes, stopLine, searchWholeText;
int patLength;
char *arg, *pattern, *varName, *p, *startOfLine;
char buffer[20];
@@ -1665,6 +1750,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
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. */
@@ -1673,6 +1760,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
exact = 1;
+ searchElide = 0;
+ curIndex.tree = textPtr->tree;
backwards = 0;
noCase = 0;
varName = NULL;
@@ -1685,8 +1774,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
if (length < 2) {
badSwitch:
Tcl_AppendResult(interp, "bad switch \"", arg,
- "\": must be -forward, -backward, -exact, -regexp, ",
- "-nocase, -count, or --", (char *) NULL);
+ "\": must be --, -backward, -count, -elide, -exact, ",
+ "-forward, -nocase, or -regexp", (char *) NULL);
return TCL_ERROR;
}
c = arg[1];
@@ -1694,13 +1783,24 @@ TextSearchCmd(textPtr, interp, argc, argv)
backwards = 1;
} else if ((c == 'c') && (strncmp(argv[i], "-count", length) == 0)) {
if (i >= (argc-1)) {
- interp->result = "no value given for \"-count\" option";
+ Tcl_SetResult(interp, "no value given for \"-count\" option",
+ TCL_STATIC);
return TCL_ERROR;
}
i++;
varName = argv[i];
- } else if ((c == 'e') && (strncmp(argv[i], "-exact", length) == 0)) {
+ } else if ((c == 'e') && (length > 2)
+ && (strncmp(argv[i], "-exact", length) == 0)) {
exact = 1;
+ } else if ((c == 'e') && (length > 2)
+ && (strncmp(argv[i], "-elide", length) == 0)) {
+ searchElide = 1;
+ } else if ((c == 'h') && (strncmp(argv[i], "-hidden", length) == 0)) {
+ /*
+ * -hidden is kept around for backwards compatibility with
+ * the dash patch, but -elide is the official option
+ */
+ searchElide = 1;
} else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) {
backwards = 0;
} else if ((c == 'n') && (strncmp(argv[i], "-nocase", length) == 0)) {
@@ -1717,7 +1817,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
argsLeft = argc - (i+2);
if ((argsLeft != 0) && (argsLeft != 1)) {
Tcl_AppendResult(interp, "wrong # args: should be \"",
- argv[0], " search ?switches? pattern index ?stopIndex?",
+ argv[0], " search ?switches? pattern index ?stopIndex?\"",
(char *) NULL);
return TCL_ERROR;
}
@@ -1727,36 +1827,35 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Convert the pattern to lower-case if we're supposed to ignore case.
*/
- if (noCase) {
+ if (noCase && exact) {
Tcl_DStringInit(&patDString);
Tcl_DStringAppend(&patDString, pattern, -1);
pattern = Tcl_DStringValue(&patDString);
- for (p = pattern; *p != 0; p++) {
- if (isupper(UCHAR(*p))) {
- *p = tolower(UCHAR(*p));
- }
- }
+ Tcl_UtfToLower(pattern);
}
+ Tcl_DStringInit(&line);
if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
numLines = TkBTreeNumLines(textPtr->tree);
startingLine = TkBTreeLineIndex(index.linePtr);
- startingChar = index.charIndex;
+ startingByte = index.byteIndex;
if (startingLine >= numLines) {
if (backwards) {
startingLine = TkBTreeNumLines(textPtr->tree) - 1;
- startingChar = TkBTreeCharsInLine(TkBTreeFindLine(textPtr->tree,
+ startingByte = TkBTreeBytesInLine(TkBTreeFindLine(textPtr->tree,
startingLine));
} else {
startingLine = 0;
- startingChar = 0;
+ startingByte = 0;
}
}
if (argsLeft == 1) {
if (TkTextGetIndex(interp, textPtr, argv[i+2], &stopIndex) != TCL_OK) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
stopLine = TkBTreeLineIndex(stopIndex.linePtr);
if (!backwards && (stopLine == numLines)) {
@@ -1778,14 +1877,17 @@ TextSearchCmd(textPtr, interp, argc, argv)
if (exact) {
patLength = strlen(pattern);
} else {
- regexp = Tcl_RegExpCompile(interp, pattern);
+ patObj = Tcl_NewStringObj(pattern, -1);
+ Tcl_IncrRefCount(patObj);
+ regexp = Tcl_GetRegExpFromObj(interp, patObj,
+ (noCase ? TCL_REG_NOCASE : 0) | TCL_REG_ADVANCED);
if (regexp == NULL) {
- return TCL_ERROR;
+ code = TCL_ERROR;
+ goto done;
}
}
lineNum = startingLine;
code = TCL_OK;
- Tcl_DStringInit(&line);
for (passes = 0; passes < 2; ) {
if (lineNum >= numLines) {
/*
@@ -1802,9 +1904,11 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
linePtr = TkBTreeFindLine(textPtr->tree, lineNum);
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
for (segPtr = linePtr->segPtr; segPtr != NULL;
- segPtr = segPtr->nextPtr) {
- if (segPtr->typePtr != &tkTextCharType) {
+ curIndex.byteIndex += segPtr->size, segPtr = segPtr->nextPtr) {
+ if ((segPtr->typePtr != &tkTextCharType)
+ || (!searchElide && TkTextIsElided(textPtr, &curIndex))) {
continue;
}
Tcl_DStringAppend(&line, segPtr->body.chars, segPtr->size);
@@ -1819,22 +1923,20 @@ TextSearchCmd(textPtr, interp, argc, argv)
*/
if (noCase) {
- for (p = Tcl_DStringValue(&line); *p != 0; p++) {
- if (isupper(UCHAR(*p))) {
- *p = tolower(UCHAR(*p));
- }
- }
+ Tcl_DStringSetLength(&line,
+ Tcl_UtfToLower(Tcl_DStringValue(&line)));
}
/*
* 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.
+ * in the line. (Note: The lastByte should include the NULL char
+ * so we can handle searching for end of line easier.)
*/
- matchChar = -1;
- firstChar = 0;
- lastChar = INT_MAX;
+ matchByte = -1;
+ firstByte = 0;
+ lastByte = Tcl_DStringLength(&line) + 1;
if (lineNum == startingLine) {
int indexInDString;
@@ -1848,8 +1950,8 @@ TextSearchCmd(textPtr, interp, argc, argv)
* character.
*/
- indexInDString = startingChar;
- for (segPtr = linePtr->segPtr, leftToScan = startingChar;
+ indexInDString = startingByte;
+ for (segPtr = linePtr->segPtr, leftToScan = startingByte;
leftToScan > 0; segPtr = segPtr->nextPtr) {
if (segPtr->typePtr != &tkTextCharType) {
indexInDString -= segPtr->size;
@@ -1863,8 +1965,9 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Only use the last part of the line.
*/
- firstChar = indexInDString;
- if (firstChar >= Tcl_DStringLength(&line)) {
+ firstByte = indexInDString;
+ if ((firstByte >= Tcl_DStringLength(&line))
+ && !((Tcl_DStringLength(&line) == 0) && !exact)) {
goto nextLine;
}
} else {
@@ -1872,13 +1975,16 @@ TextSearchCmd(textPtr, interp, argc, argv)
* Use only the first part of the line.
*/
- lastChar = indexInDString;
+ lastByte = indexInDString;
}
}
do {
int thisLength;
+ Tcl_UniChar ch;
+
if (exact) {
- p = strstr(startOfLine + firstChar, pattern);
+ p = strstr(startOfLine + firstByte, /* INTL: Native. */
+ pattern);
if (p == NULL) {
break;
}
@@ -1889,7 +1995,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
int match;
match = Tcl_RegExpExec(interp, regexp,
- startOfLine + firstChar, startOfLine);
+ startOfLine + firstByte, startOfLine);
if (match < 0) {
code = TCL_ERROR;
goto done;
@@ -1901,12 +2007,12 @@ TextSearchCmd(textPtr, interp, argc, argv)
i = start - startOfLine;
thisLength = end - start;
}
- if (i >= lastChar) {
+ if (i >= lastByte) {
break;
}
- matchChar = i;
+ matchByte = i;
matchLength = thisLength;
- firstChar = matchChar+1;
+ firstByte = i + Tcl_UtfToUniChar(startOfLine + matchByte, &ch);
} while (backwards);
/*
@@ -1915,32 +2021,49 @@ TextSearchCmd(textPtr, interp, argc, argv)
* specified.
*/
- if (matchChar >= 0) {
+ 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 or any other non-textual info.
+ * 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.
*/
- for (segPtr = linePtr->segPtr, leftToScan = matchChar;
- leftToScan >= 0; segPtr = segPtr->nextPtr) {
- if (segPtr->typePtr != &tkTextCharType) {
- matchChar += segPtr->size;
- continue;
+ curIndex.linePtr = linePtr; curIndex.byteIndex = 0;
+ 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;
}
- leftToScan -= segPtr->size;
+ curIndex.byteIndex += segPtr->size;
}
for (leftToScan += matchLength; leftToScan > 0;
segPtr = segPtr->nextPtr) {
if (segPtr->typePtr != &tkTextCharType) {
- matchLength += segPtr->size;
+ numChars += segPtr->size;
continue;
}
leftToScan -= segPtr->size;
}
- TkTextMakeIndex(textPtr->tree, lineNum, matchChar, &index);
+ TkTextMakeByteIndex(textPtr->tree, lineNum, matchByte, &index);
if (!searchWholeText) {
if (!backwards && (TkTextIndexCmp(&index, &stopIndex) >= 0)) {
goto done;
@@ -1950,14 +2073,15 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
}
if (varName != NULL) {
- sprintf(buffer, "%d", matchLength);
+ sprintf(buffer, "%d", numChars);
if (Tcl_SetVar(interp, varName, buffer, TCL_LEAVE_ERR_MSG)
== NULL) {
code = TCL_ERROR;
goto done;
}
}
- TkTextPrintIndex(&index, interp->result);
+ TkTextPrintIndex(&index, buffer);
+ Tcl_SetResult(interp, buffer, TCL_VOLATILE);
goto done;
}
@@ -1989,9 +2113,12 @@ TextSearchCmd(textPtr, interp, argc, argv)
}
done:
Tcl_DStringFree(&line);
- if (noCase) {
+ if (noCase && exact) {
Tcl_DStringFree(&patDString);
}
+ if (patObj != NULL) {
+ Tcl_DecrRefCount(patObj);
+ }
return code;
}
@@ -2006,7 +2133,7 @@ TextSearchCmd(textPtr, interp, argc, argv)
* The return value is a pointer to a malloc'ed structure holding
* parsed information about the tab stops. If an error occurred
* then the return value is NULL and an error message is left in
- * interp->result.
+ * the interp's result.
*
* Side effects:
* Memory is allocated for the structure that is returned. It is
@@ -2028,6 +2155,7 @@ TkTextGetTabs(interp, tkwin, string)
char **argv;
TkTextTabArray *tabArrayPtr;
TkTextTab *tabPtr;
+ Tcl_UniChar ch;
if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) {
return NULL;
@@ -2070,11 +2198,12 @@ TkTextGetTabs(interp, tkwin, string)
if ((i+1) == argc) {
continue;
}
- c = UCHAR(argv[i+1][0]);
- if (!isalpha(c)) {
+ Tcl_UtfToUniChar(argv[i+1], &ch);
+ if (!Tcl_UniCharIsAlpha(ch)) {
continue;
}
i += 1;
+ c = argv[i][0];
if ((c == 'l') && (strncmp(argv[i], "left",
strlen(argv[i])) == 0)) {
tabPtr->alignment = LEFT;
@@ -2186,7 +2315,7 @@ TextDumpCmd(textPtr, interp, argc, argv)
if (TkTextGetIndex(interp, textPtr, argv[arg], &index1) != TCL_OK) {
return TCL_ERROR;
}
- lineno = TkBTreeLineIndex(index1.linePtr) + 1;
+ lineno = TkBTreeLineIndex(index1.linePtr);
arg++;
atEnd = 0;
if (argc == arg) {
@@ -2204,10 +2333,10 @@ TextDumpCmd(textPtr, interp, argc, argv)
}
if (index1.linePtr == index2.linePtr) {
DumpLine(interp, textPtr, what, index1.linePtr,
- index1.charIndex, index2.charIndex, lineno, command);
+ index1.byteIndex, index2.byteIndex, lineno, command);
} else {
DumpLine(interp, textPtr, what, index1.linePtr,
- index1.charIndex, 32000000, lineno, command);
+ index1.byteIndex, 32000000, lineno, command);
linePtr = index1.linePtr;
while ((linePtr = TkBTreeNextLine(linePtr)) != (TkTextLine *)NULL) {
lineno++;
@@ -2218,14 +2347,14 @@ TextDumpCmd(textPtr, interp, argc, argv)
lineno, command);
}
DumpLine(interp, textPtr, what, index2.linePtr, 0,
- index2.charIndex, lineno, command);
+ index2.byteIndex, lineno, command);
}
/*
* Special case to get the leftovers hiding at the end mark.
*/
if (atEnd) {
DumpLine(interp, textPtr, what & ~TK_DUMP_TEXT, index2.linePtr,
- 0, 1, lineno, command);
+ 0, 1, lineno, command);
}
return TCL_OK;
@@ -2243,17 +2372,18 @@ TextDumpCmd(textPtr, interp, argc, argv)
* None, but see DumpSegment.
*/
static void
-DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
+DumpLine(interp, textPtr, what, linePtr, startByte, endByte, lineno, command)
Tcl_Interp *interp;
TkText *textPtr;
int what; /* bit flags to select segment types */
TkTextLine *linePtr; /* The current line */
- int start, end; /* Character range to dump */
+ int startByte, endByte; /* Byte range to dump */
int lineno; /* Line number for indices dump */
char *command; /* Script to apply to the segment */
{
int offset;
TkTextSegment *segPtr;
+ TkTextIndex index;
/*
* Must loop through line looking at its segments.
* character
@@ -2262,47 +2392,54 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
* image
* window
*/
+
for (offset = 0, segPtr = linePtr->segPtr ;
- (offset < end) && (segPtr != (TkTextSegment *)NULL) ;
+ (offset < endByte) && (segPtr != (TkTextSegment *)NULL) ;
offset += segPtr->size, segPtr = segPtr->nextPtr) {
if ((what & TK_DUMP_TEXT) && (segPtr->typePtr == &tkTextCharType) &&
- (offset + segPtr->size > start)) {
+ (offset + segPtr->size > startByte)) {
char savedChar; /* Last char used in the seg */
int last = segPtr->size; /* Index of savedChar */
int first = 0; /* Index of first char in seg */
- if (offset + segPtr->size > end) {
- last = end - offset;
+ if (offset + segPtr->size > endByte) {
+ last = endByte - offset;
}
- if (start > offset) {
- first = start - offset;
+ if (startByte > offset) {
+ first = startByte - offset;
}
savedChar = segPtr->body.chars[last];
segPtr->body.chars[last] = '\0';
+
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset + first, &index);
DumpSegment(interp, "text", segPtr->body.chars + first,
- command, lineno, offset + first, what);
+ command, &index, what);
segPtr->body.chars[last] = savedChar;
- } else if ((offset >= start)) {
+ } else if ((offset >= startByte)) {
if ((what & TK_DUMP_MARK) && (segPtr->typePtr->name[0] == 'm')) {
TkTextMark *markPtr = (TkTextMark *)&segPtr->body;
char *name = Tcl_GetHashKey(&textPtr->markTable, markPtr->hPtr);
- DumpSegment(interp, "mark", name,
- command, lineno, offset, what);
+
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
+ DumpSegment(interp, "mark", name, command, &index, what);
} else if ((what & TK_DUMP_TAG) &&
(segPtr->typePtr == &tkTextToggleOnType)) {
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "tagon",
segPtr->body.toggle.tagPtr->name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_TAG) &&
(segPtr->typePtr == &tkTextToggleOffType)) {
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "tagoff",
segPtr->body.toggle.tagPtr->name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_IMG) &&
(segPtr->typePtr->name[0] == 'i')) {
TkTextEmbImage *eiPtr = (TkTextEmbImage *)&segPtr->body;
char *name = (eiPtr->name == NULL) ? "" : eiPtr->name;
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "image", name,
- command, lineno, offset, what);
+ command, &index, what);
} else if ((what & TK_DUMP_WIN) &&
(segPtr->typePtr->name[0] == 'w')) {
TkTextEmbWindow *ewPtr = (TkTextEmbWindow *)&segPtr->body;
@@ -2312,8 +2449,9 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
} else {
pathname = Tk_PathName(ewPtr->tkwin);
}
+ TkTextMakeByteIndex(textPtr->tree, lineno, offset, &index);
DumpSegment(interp, "window", pathname,
- command, lineno, offset, what);
+ command, &index, what);
}
}
}
@@ -2331,17 +2469,16 @@ DumpLine(interp, textPtr, what, linePtr, start, end, lineno, command)
* Either evals the callback or appends elements to the result string.
*/
static int
-DumpSegment(interp, key, value, command, lineno, offset, what)
+DumpSegment(interp, key, value, command, index, what)
Tcl_Interp *interp;
char *key; /* Segment type key */
char *value; /* Segment value */
char *command; /* Script callback */
- int lineno; /* Line number for indices dump */
- int offset; /* Character position */
+ TkTextIndex *index; /* index with line/byte position info */
int what; /* Look for TK_DUMP_INDEX bit */
{
- char buffer[30];
- sprintf(buffer, "%d.%d", lineno, offset);
+ char buffer[TCL_INTEGER_SPACE*2];
+ TkTextPrintIndex(index, buffer);
if (command == (char *) NULL) {
Tcl_AppendElement(interp, key);
Tcl_AppendElement(interp, value);
@@ -2362,3 +2499,5 @@ DumpSegment(interp, key, value, command, lineno, offset, what)
}
}
+
+