📄 tktexttag.c
字号:
/* * Update the tag priorities to reflect the deletion of this tag. */ 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 (tagPtr->priority < tagPtr2->priority) { prio = tagPtr2->priority - 1; } else { prio = tagPtr2->priority; } } 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; } if (argc == 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 (TkTextGetIndex(interp, textPtr, argv[3], &index1) != TCL_OK) { return TCL_ERROR; } arrayPtr = TkBTreeGetTags(&index1, &arraySize); if (arrayPtr == NULL) { return TCL_OK; } } 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; } TkTextMakeIndex(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; /* * 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. */ for (segPtr = index1.linePtr->segPtr, offset = index1.charIndex; 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; } } /* * 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) { TkTextMakeIndex(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. */ TkBTreeStartSearchBack(&index1, &index2, tagPtr, &tSearch); if (!TkBTreePrevTag(&tSearch)) { return TCL_OK; } if (tSearch.segPtr->typePtr == &tkTextToggleOnType) { TkTextPrintIndex(&tSearch.curIndex, position1); TkTextMakeIndex(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); } 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) { return TCL_ERROR; } if (tagPtr->priority <= tagPtr2->priority) { prio = tagPtr2->priority; } else { prio = tagPtr2->priority + 1; } } 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; } TkTextMakeIndex(textPtr->tree, 0, 0, &first); TkTextMakeIndex(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); } } 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; } return TCL_OK;}/* *---------------------------------------------------------------------- * * TkTextCreateTag -- * * Find the record describing a tag within a given text widget, * creating a new record if one doesn't already exist. * * Results: * The return value is a pointer to the TkTextTag record for tagName. * * Side effects: * A new tag record is created if there isn't one already defined * for tagName. * *---------------------------------------------------------------------- */TkTextTag *TkTextCreateTag(textPtr, tagName) TkText *textPtr; /* Widget in which tag is being used. */ char *tagName; /* Name of desired tag. */{ register TkTextTag *tagPtr; Tcl_HashEntry *hPtr; int new; hPtr = Tcl_CreateHashEntry(&textPtr->tagTable, tagName, &new); if (!new) { return (TkTextTag *) Tcl_GetHashValue(hPtr); } /* * No existing entry. Create a new one, initialize it, and add a * pointer to it to the hash table entry. */ tagPtr = (TkTextTag *) ckalloc(sizeof(TkTextTag)); tagPtr->name = Tcl_GetHashKey(&textPtr->tagTable, hPtr); tagPtr->toggleCount = 0; tagPtr->tagRootPtr = NULL; tagPtr->priority = textPtr->numTags; tagPtr->border = NULL; tagPtr->bdString = NULL; tagPtr->borderWidth = 0; tagPtr->reliefString = NULL; tagPtr->relief = TK_RELIEF_FLAT; tagPtr->bgStipple = None; tagPtr->fgColor = NULL; tagPtr->tkfont = NULL; tagPtr->fgStipple = None; tagPtr->justifyString = NULL; tagPtr->justify = TK_JUSTIFY_LEFT; tagPtr->lMargin1String = NULL; tagPtr->lMargin1 = 0; tagPtr->lMargin2String = NULL; tagPtr->lMargin2 = 0; tagPtr->offsetString = NULL; tagPtr->offset = 0; tagPtr->overstrikeString = NULL; tagPtr->overstrike = 0; tagPtr->rMarginString = NULL; tagPtr->rMargin = 0; tagPtr->spacing1String = NULL; tagPtr->spacing1 = 0; tagPtr->spacing2String = NULL; tagPtr->spacing2 = 0; tagPtr->spacing3String = NULL; tagPtr->spacing3 = 0; tagPtr->tabString = NULL; tagPtr->tabArrayPtr = NULL; tagPtr->underlineString = NULL; tagPtr->underline = 0; tagPtr->wrapMode = NULL; tagPtr->affectsDisplay = 0; textPtr->numTags++; Tcl_SetHashValue(hPtr, tagPtr); return tagPtr;}/* *---------------------------------------------------------------------- * * FindTag -- * * See if tag is defined for a given widget. * * Results: * If tagName is defined in textPtr, a pointer to its TkTextTag * structure is returned. Otherwise NULL is returned and an * error message is recorded in interp->result unless interp * is NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */static TkTextTag *FindTag(interp, textPtr, tagName) Tcl_Interp *interp; /* Interpreter to use for error message; * if NULL, then don't record an error * message. */ TkText *textPtr; /* Widget in which tag is being used. */ char *tagName; /* Name of desired tag. */{ Tcl_HashEntry *hPtr; hPtr = Tcl_FindHashEntry(&textPtr->tagTable, tagName); if (hPtr != NULL) { return (TkTextTag *) Tcl_GetHashValue(hPtr); } if (interp != NULL) { Tcl_AppendResult(interp, "tag \"", tagName, "\" isn't defined in text widget", (char *) NULL); } return NULL;}/* *---------------------------------------------------------------------- * * TkTextFreeTag -- * * This procedure is called when a tag is deleted to free up the * memory and other resources associated with the tag. * * Results: * None. * * Side effects: * Memory and other resources are freed. * *---------------------------------------------------------------------- */voidTkTextFreeTag(textPtr, tagPtr) TkText *textPtr; /* Info about overall widget. */ register TkTextTag *tagPtr; /* Tag being deleted. */{ 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -