📄 tktext.c
字号:
TkTextMakeIndex(textPtr->tree, line, charIndex, &index1); TkTextSetYView(textPtr, &index1, 0); } /* * Invalidate any selection retrievals in progress. */ textPtr->abortSelections = 1; return TCL_OK;}/* *---------------------------------------------------------------------- * * TextFetchSelection -- * * This procedure is called back by Tk when the selection is * requested by someone. It returns part or all of the selection * in a buffer provided by the caller. * * Results: * The return value is the number of non-NULL bytes stored * at buffer. Buffer is filled (or partially filled) with a * NULL-terminated string containing part or all of the selection, * as given by offset and maxBytes. * * Side effects: * None. * *---------------------------------------------------------------------- */static intTextFetchSelection(clientData, offset, buffer, maxBytes) ClientData clientData; /* Information about text widget. */ int offset; /* Offset within selection of first * character to be returned. */ char *buffer; /* Location in which to place * selection. */ int maxBytes; /* Maximum number of bytes to place * at buffer, not including terminating * NULL character. */{ register TkText *textPtr = (TkText *) clientData; TkTextIndex eof; int count, chunkSize, offsetInSeg; TkTextSearch search; TkTextSegment *segPtr; if (!textPtr->exportSelection) { return -1; } /* * Find the beginning of the next range of selected text. Note: if * the selection is being retrieved in multiple pieces (offset != 0) * and some modification has been made to the text that affects the * selection then reject the selection request (make 'em start over * again). */ if (offset == 0) { TkTextMakeIndex(textPtr->tree, 0, 0, &textPtr->selIndex); textPtr->abortSelections = 0; } else if (textPtr->abortSelections) { return 0; } TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &eof); TkBTreeStartSearch(&textPtr->selIndex, &eof, textPtr->selTagPtr, &search); if (!TkBTreeCharTagged(&textPtr->selIndex, textPtr->selTagPtr)) { if (!TkBTreeNextTag(&search)) { if (offset == 0) { return -1; } else { return 0; } } textPtr->selIndex = search.curIndex; } /* * Each iteration through the outer loop below scans one selected range. * Each iteration through the inner loop scans one segment in the * selected range. */ count = 0; while (1) { /* * Find the end of the current range of selected text. */ if (!TkBTreeNextTag(&search)) { panic("TextFetchSelection couldn't find end of range"); } /* * Copy information from character segments into the buffer * until either we run out of space in the buffer or we get * to the end of this range of text. */ while (1) { if (maxBytes == 0) { goto done; } segPtr = TkTextIndexToSeg(&textPtr->selIndex, &offsetInSeg); chunkSize = segPtr->size - offsetInSeg; if (chunkSize > maxBytes) { chunkSize = maxBytes; } if (textPtr->selIndex.linePtr == search.curIndex.linePtr) { int leftInRange; leftInRange = search.curIndex.charIndex - textPtr->selIndex.charIndex; if (leftInRange < chunkSize) { chunkSize = leftInRange; if (chunkSize <= 0) { break; } } } if (segPtr->typePtr == &tkTextCharType) { memcpy((VOID *) buffer, (VOID *) (segPtr->body.chars + offsetInSeg), (size_t) chunkSize); buffer += chunkSize; maxBytes -= chunkSize; count += chunkSize; } TkTextIndexForwChars(&textPtr->selIndex, chunkSize, &textPtr->selIndex); } /* * Find the beginning of the next range of selected text. */ if (!TkBTreeNextTag(&search)) { break; } textPtr->selIndex = search.curIndex; } done: *buffer = 0; return count;}/* *---------------------------------------------------------------------- * * TkTextLostSelection -- * * This procedure is called back by Tk when the selection is * grabbed away from a text widget. On Windows and Mac systems, we * want to remember the selection for the next time the focus * enters the window. On Unix, just remove the "sel" tag from * everything in the widget. * * Results: * None. * * Side effects: * The "sel" tag is cleared from the window. * *---------------------------------------------------------------------- */voidTkTextLostSelection(clientData) ClientData clientData; /* Information about text widget. */{ register TkText *textPtr = (TkText *) clientData;#ifdef ALWAYS_SHOW_SELECTION TkTextIndex start, end; if (!textPtr->exportSelection) { return; } /* * On Windows and Mac systems, we want to remember the selection * for the next time the focus enters the window. On Unix, * just remove the "sel" tag from everything in the widget. */ TkTextMakeIndex(textPtr->tree, 0, 0, &start); TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &end); TkTextRedrawTag(textPtr, &start, &end, textPtr->selTagPtr, 1); TkBTreeTag(&start, &end, textPtr->selTagPtr, 0);#endif textPtr->flags &= ~GOT_SELECTION;}/* *---------------------------------------------------------------------- * * TextBlinkProc -- * * This procedure is called as a timer handler to blink the * insertion cursor off and on. * * Results: * None. * * Side effects: * The cursor gets turned on or off, redisplay gets invoked, * and this procedure reschedules itself. * *---------------------------------------------------------------------- */static voidTextBlinkProc(clientData) ClientData clientData; /* Pointer to record describing text. */{ register TkText *textPtr = (TkText *) clientData; TkTextIndex index; int x, y, w, h; if (!(textPtr->flags & GOT_FOCUS) || (textPtr->insertOffTime == 0)) { return; } if (textPtr->flags & INSERT_ON) { textPtr->flags &= ~INSERT_ON; textPtr->insertBlinkHandler = Tcl_CreateTimerHandler( textPtr->insertOffTime, TextBlinkProc, (ClientData) textPtr); } else { textPtr->flags |= INSERT_ON; textPtr->insertBlinkHandler = Tcl_CreateTimerHandler( textPtr->insertOnTime, TextBlinkProc, (ClientData) textPtr); } TkTextMarkSegToIndex(textPtr, textPtr->insertMarkPtr, &index); TkTextCharBbox(textPtr, &index, &x, &y, &w, &h); TkTextRedrawRegion(textPtr, x - textPtr->insertWidth / 2, y, textPtr->insertWidth, h);}/* *---------------------------------------------------------------------- * * TextSearchCmd -- * * This procedure is invoked to process the "search" widget command * for text widgets. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */static intTextSearchCmd(textPtr, interp, argc, argv) TkText *textPtr; /* Information about text widget. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ int backwards, exact, c, i, argsLeft, noCase, leftToScan; size_t length; int numLines, startingLine, startingChar, lineNum, firstChar, lastChar; int code, matchLength, matchChar, passes, stopLine, searchWholeText; int patLength; char *arg, *pattern, *varName, *p, *startOfLine; char buffer[20]; TkTextIndex index, stopIndex; Tcl_DString line, patDString; TkTextSegment *segPtr; TkTextLine *linePtr; Tcl_RegExp regexp = NULL; /* Initialization needed only to * prevent compiler warning. */ /* * Parse switches and other arguments. */ exact = 1; backwards = 0; noCase = 0; varName = NULL; for (i = 2; i < argc; i++) { arg = argv[i]; if (arg[0] != '-') { break; } length = strlen(arg); if (length < 2) { badSwitch: Tcl_AppendResult(interp, "bad switch \"", arg, "\": must be -forward, -backward, -exact, -regexp, ", "-nocase, -count, or --", (char *) NULL); return TCL_ERROR; } c = arg[1]; 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)) { interp->result = "no value given for \"-count\" option"; return TCL_ERROR; } i++; varName = argv[i]; } else if ((c == 'e') && (strncmp(argv[i], "-exact", length) == 0)) { exact = 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)) { i++; break; } else { goto badSwitch; } } argsLeft = argc - (i+2); if ((argsLeft != 0) && (argsLeft != 1)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " search ?switches? pattern index ?stopIndex?", (char *) NULL); return TCL_ERROR; } pattern = argv[i]; /* * Convert the pattern to lower-case if we're supposed to ignore case. */ if (noCase) { 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)); } } } if (TkTextGetIndex(interp, textPtr, argv[i+1], &index) != TCL_OK) { return TCL_ERROR; } numLines = TkBTreeNumLines(textPtr->tree); startingLine = TkBTreeLineIndex(index.linePtr); startingChar = index.charIndex; if (startingLine >= numLines) { if (backwards) { startingLine = TkBTreeNumLines(textPtr->tree) - 1; startingChar = TkBTreeCharsInLine(TkBTreeFindLine(textPtr->tree, startingLine)); } else { startingLine = 0; startingChar = 0; } } if (argsLeft == 1) { if (TkTextGetIndex(interp, textPtr, argv[i+2], &stopIndex) != TCL_OK) { return TCL_ERROR; } stopLine = TkBTreeLineIndex(stopIndex.linePtr); if (!backwards && (stopLine == numLines)) { stopLine = numLines-1; } searchWholeText = 0; } else { stopLine = 0; searchWholeText = 1; } /* * Scan through all of the lines of the text circularly, starting * at the given index. */ matchLength = patLength = 0; /* Only needed to prevent compiler * warnings. */ if (exact) { patLength = strlen(pattern); } else { regexp = Tcl_RegExpCompile(interp, pattern); if (regexp == NULL) { return TCL_ERROR; } } lineNum = startingLine; code = TCL_OK; Tcl_DStringInit(&line); for (passes = 0; passes < 2; ) { if (lineNum >= numLines) { /* * Don't search the dummy last line of the text. */ goto nextLine; } /* * 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. */ linePtr = TkBTreeFindLine(textPtr->tree, lineNum); for (segPtr = linePtr->segPtr; segPtr != NULL; segPtr = segPtr->nextPtr) { if (segPtr->typePtr != &tkTextCharType) { continue; } Tcl_DStringAppend(&line, segPtr->body.chars, segPtr->size); } if (!exact) { Tcl_DStringSetLength(&line, Tcl_DStringLength(&line)-1); } startOfLine = Tcl_DStringValue(&line); /* * If we're ignoring case, convert the line to lower case. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -