📄 tktext.c
字号:
if (noCase) { for (p = Tcl_DStringValue(&line); *p != 0; p++) { if (isupper(UCHAR(*p))) { *p = tolower(UCHAR(*p)); } } } /* * 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. */ matchChar = -1; firstChar = 0; lastChar = INT_MAX; 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 = startingChar; for (segPtr = linePtr->segPtr, leftToScan = startingChar; 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. */ firstChar = indexInDString; if (firstChar >= Tcl_DStringLength(&line)) { goto nextLine; } } else { /* * Use only the first part of the line. */ lastChar = indexInDString; } } do { int thisLength; if (exact) { p = strstr(startOfLine + firstChar, pattern); if (p == NULL) { break; } i = p - startOfLine; thisLength = patLength; } else { char *start, *end; int match; match = Tcl_RegExpExec(interp, regexp, startOfLine + firstChar, 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 >= lastChar) { break; } matchChar = i; matchLength = thisLength; firstChar = matchChar+1; } 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 (matchChar >= 0) { /* * 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. * Scan through the line's segments again to adjust both * matchChar and matchCount. */ for (segPtr = linePtr->segPtr, leftToScan = matchChar; leftToScan >= 0; segPtr = segPtr->nextPtr) { if (segPtr->typePtr != &tkTextCharType) { matchChar += segPtr->size; continue; } leftToScan -= segPtr->size; } for (leftToScan += matchLength; leftToScan > 0; segPtr = segPtr->nextPtr) { if (segPtr->typePtr != &tkTextCharType) { matchLength += segPtr->size; continue; } leftToScan -= segPtr->size; } TkTextMakeIndex(textPtr->tree, lineNum, matchChar, &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", matchLength); if (Tcl_SetVar(interp, varName, buffer, TCL_LEAVE_ERR_MSG) == NULL) { code = TCL_ERROR; goto done; } } TkTextPrintIndex(&index, interp->result); goto done; } /* * Go to the next (or previous) line; */ nextLine: if (backwards) { lineNum--; if (!searchWholeText) { if (lineNum < stopLine) { break; } } else if (lineNum < 0) { lineNum = numLines-1; } } else { lineNum++; if (!searchWholeText) { if (lineNum > stopLine) { break; } } else if (lineNum >= numLines) { lineNum = 0; } } Tcl_DStringSetLength(&line, 0); } done: Tcl_DStringFree(&line); if (noCase) { Tcl_DStringFree(&patDString); } return code;}/* *---------------------------------------------------------------------- * * TkTextGetTabs -- * * Parses a string description of a set of tab stops. * * Results: * 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. * * Side effects: * Memory is allocated for the structure that is returned. It is * up to the caller to free this structure when it is no longer * needed. * *---------------------------------------------------------------------- */TkTextTabArray *TkTextGetTabs(interp, tkwin, string) Tcl_Interp *interp; /* Used for error reporting. */ Tk_Window tkwin; /* Window in which the tabs will be * used. */ char *string; /* Description of the tab stops. See * the text manual entry for details. */{ int argc, i, count, c; char **argv; TkTextTabArray *tabArrayPtr; TkTextTab *tabPtr; if (Tcl_SplitList(interp, string, &argc, &argv) != TCL_OK) { return NULL; } /* * First find out how many entries we need to allocate in the * tab array. */ count = 0; for (i = 0; i < argc; i++) { c = argv[i][0]; if ((c != 'l') && (c != 'r') && (c != 'c') && (c != 'n')) { count++; } } /* * Parse the elements of the list one at a time to fill in the * array. */ tabArrayPtr = (TkTextTabArray *) ckalloc((unsigned) (sizeof(TkTextTabArray) + (count-1)*sizeof(TkTextTab))); tabArrayPtr->numTabs = 0; for (i = 0, tabPtr = &tabArrayPtr->tabs[0]; i < argc; i++, tabPtr++) { if (Tk_GetPixels(interp, tkwin, argv[i], &tabPtr->location) != TCL_OK) { goto error; } tabArrayPtr->numTabs++; /* * See if there is an explicit alignment in the next list * element. Otherwise just use "left". */ tabPtr->alignment = LEFT; if ((i+1) == argc) { continue; } c = UCHAR(argv[i+1][0]); if (!isalpha(c)) { continue; } i += 1; 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); goto error; } } ckfree((char *) argv); return tabArrayPtr; error: ckfree((char *) tabArrayPtr); ckfree((char *) argv); return NULL;}/* *---------------------------------------------------------------------- * * TextDumpCmd -- * * Return information about the text, tags, marks, and embedded windows * and images in a text widget. See the man page for the description * of the text dump operation for all the details. * * Results: * A standard Tcl result. * * Side effects: * Memory is allocated for the result, if needed (standard Tcl result * side effects). * *---------------------------------------------------------------------- */static intTextDumpCmd(textPtr, interp, argc, argv) register TkText *textPtr; /* Information about text widget. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. Someone else has already * parsed this command enough to know that * argv[1] is "dump". */{ TkTextIndex index1, index2; int arg; int lineno; /* Current line number */ int what = 0; /* bitfield to select segment types */ int atEnd; /* True if dumping up to logical end */ TkTextLine *linePtr; char *command = NULL; /* Script callback to apply to segments */#define TK_DUMP_TEXT 0x1#define TK_DUMP_MARK 0x2#define TK_DUMP_TAG 0x4#define TK_DUMP_WIN 0x8#define TK_DUMP_IMG 0x10#define TK_DUMP_ALL (TK_DUMP_TEXT|TK_DUMP_MARK|TK_DUMP_TAG| \ TK_DUMP_WIN|TK_DUMP_IMG) for (arg=2 ; argv[arg] != (char *) NULL ; arg++) { size_t len; if (argv[arg][0] != '-') { break; } len = strlen(argv[arg]); if (strncmp("-all", argv[arg], len) == 0) { what = TK_DUMP_ALL; } else if (strncmp("-text", argv[arg], len) == 0) { what |= TK_DUMP_TEXT; } else if (strncmp("-tag", argv[arg], len) == 0) { what |= TK_DUMP_TAG; } else if (strncmp("-mark", argv[arg], len) == 0) { what |= TK_DUMP_MARK; } else if (strncmp("-image", argv[arg], len) == 0) { what |= TK_DUMP_IMG; } else if (strncmp("-window", argv[arg], len) == 0) { what |= TK_DUMP_WIN; } else if (strncmp("-command", argv[arg], len) == 0) { arg++; if (arg >= argc) { Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); return TCL_ERROR; } command = argv[arg]; } else { Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); return TCL_ERROR; } } if (arg >= argc) { Tcl_AppendResult(interp, "Usage: ", argv[0], " dump ?-all -image -text -mark -tag -window? ?-command script? index ?index2?", NULL); return TCL_ERROR; } if (what == 0) { what = TK_DUMP_ALL; } if (TkTextGetIndex(interp, textPtr, argv[arg], &index1) != TCL_OK) { return TCL_ERROR; } lineno = TkBTreeLineIndex(index1.linePtr) + 1; arg++; atEnd = 0; if (argc == arg) { TkTextIndexForwChars(&index1, 1, &index2); } else { if (TkTextGetIndex(interp, textPtr, argv[arg], &index2) != TCL_OK) { return TCL_ERROR; } if (strncmp(argv[arg], "end", strlen(argv[arg])) == 0) { atEnd = 1; } } if (TkTextIndexCmp(&index1, &index2) >= 0) { return TCL_OK; } if (index1.linePtr == index2.linePtr) { DumpLine(interp, textPtr, what, index1.linePtr, index1.charIndex, index2.charIndex, lineno, command); } else { DumpLine(interp, textPtr, what, index1.linePtr, index1.charIndex, 32000000, lineno, command); linePtr = index1.linePtr; while ((linePtr = TkBTreeNextLine(linePtr)) != (TkTextLine *)NULL) { lineno++; if (linePtr == index2.linePtr) { break; } DumpLine(interp, textPtr, what, linePtr, 0, 32000000, lineno, command); } DumpLine(interp, textPtr, what, index2.linePtr, 0, index2.charIndex, 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); } return TCL_OK;}/* * DumpLine * Return information about a given text line from character * position "start" up to, but not including, "end". * * Results: * A standard Tcl result. * * Side effects: * None, but see DumpSegment. */static voidDumpLine(interp, textPtr, what, linePtr, start, end, lineno, command) Tcl_Interp *interp; TkText *textPtr; int what; /* bit flags to select segment types
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -