📄 tktexttag.c
字号:
/* * tkTextTag.c -- * * This module implements the "tag" subcommand of the widget command * for text widgets, plus most of the other high-level functions * related to tags. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkTextTag.c 1.39 97/02/07 13:51:52 */#include "default.h"#include "tkPort.h"#include "tk.h"#include "tkText.h"/* * Information used for parsing tag configuration information: */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_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_UID, "-wrap", (char *) NULL, (char *) NULL, (char *) NULL, Tk_Offset(TkTextTag, wrapMode), TK_CONFIG_NULL_OK}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0}};/* * Forward declarations for procedures defined later in this file: */static void ChangeTagPriority _ANSI_ARGS_((TkText *textPtr, TkTextTag *tagPtr, int prio));static TkTextTag * FindTag _ANSI_ARGS_((Tcl_Interp *interp, TkText *textPtr, char *tagName));static void SortTags _ANSI_ARGS_((int numTags, TkTextTag **tagArrayPtr));static int TagSortProc _ANSI_ARGS_((CONST VOID *first, CONST VOID *second));/* *-------------------------------------------------------------- * * TkTextTagCmd -- * * This procedure is invoked to process the "tag" options of * the 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. * *-------------------------------------------------------------- */intTkTextTagCmd(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 "tag". */{ int c, i, addTag; size_t length; char *fullOption; register TkTextTag *tagPtr; TkTextIndex first, last, index1, index2; if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " tag option ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } 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) { return TCL_ERROR; } if (argc > (i+1)) { if (TkTextGetIndex(interp, textPtr, argv[i+1], &index2) != TCL_OK) { return TCL_ERROR; } if (TkTextIndexCmp(&index1, &index2) >= 0) { return TCL_OK; } } else { index2 = index1; TkTextIndexForwChars(&index2, 1, &index2); } 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); /* * 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. */ if (tagPtr == textPtr->selTagPtr) { 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; } } else if (argc == 5) { char *command; command = Tk_GetBinding(interp, textPtr->bindingTable, (ClientData) tagPtr, argv[4]); if (command == NULL) { return TCL_ERROR; } interp->result = command; } 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) { return TCL_ERROR; } if (tagPtr->borderWidth < 0) { tagPtr->borderWidth = 0; } } 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->tabString != NULL) { tagPtr->tabArrayPtr = TkTextGetTabs(interp, textPtr->tkwin, tagPtr->tabString); 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->wrapMode != NULL) && (tagPtr->wrapMode != tkTextCharUid) && (tagPtr->wrapMode != tkTextNoneUid) && (tagPtr->wrapMode != tkTextWordUid)) { Tcl_AppendResult(interp, "bad wrap mode \"", tagPtr->wrapMode, "\": must be char, none, or word", (char *) NULL); tagPtr->wrapMode = NULL; 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->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->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); } TkBTreeTag(TkTextMakeIndex(textPtr->tree, 0, 0, &first), TkTextMakeIndex(textPtr->tree, TkBTreeNumLines(textPtr->tree), 0, &last), tagPtr, 0); Tcl_DeleteHashEntry(hPtr); if (textPtr->bindingTable != NULL) { Tk_DeleteAllBindings(textPtr->bindingTable, (ClientData) tagPtr); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -