📄 tktext.c
字号:
/* * tkText.c -- * * This module provides a big chunk of the implementation of * multi-line editable text widgets for Tk. Among other things, * it provides the Tcl command interfaces to text widgets and * the display code. The B-tree representation of text is * implemented elsewhere. * * Copyright (c) 1992-1994 The Regents of the University of California. * Copyright (c) 1994-1996 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: @(#) tkText.c 1.104 97/10/13 15:18:24 */#include "default.h"#include "tkPort.h"#include "tkInt.h"#ifdef MAC_TCL#define Style TkStyle#define DInfo TkDInfo#endif#include "tkText.h"/* * Information used to parse text configuration options: */static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_TEXT_BG_COLOR, Tk_Offset(TkText, border), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_TEXT_BG_MONO, Tk_Offset(TkText, border), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth", DEF_TEXT_BORDER_WIDTH, Tk_Offset(TkText, borderWidth), 0}, {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", DEF_TEXT_CURSOR, Tk_Offset(TkText, cursor), TK_CONFIG_NULL_OK}, {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_TEXT_EXPORT_SELECTION, Tk_Offset(TkText, exportSelection), 0}, {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_FONT, "-font", "font", "Font", DEF_TEXT_FONT, Tk_Offset(TkText, tkfont), 0}, {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", DEF_TEXT_FG, Tk_Offset(TkText, fgColor), 0}, {TK_CONFIG_PIXELS, "-height", "height", "Height", DEF_TEXT_HEIGHT, Tk_Offset(TkText, height), 0}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_TEXT_HIGHLIGHT_BG, Tk_Offset(TkText, highlightBgColorPtr), 0}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_TEXT_HIGHLIGHT, Tk_Offset(TkText, highlightColorPtr), 0}, {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_TEXT_HIGHLIGHT_WIDTH, Tk_Offset(TkText, highlightWidth), 0}, {TK_CONFIG_BORDER, "-insertbackground", "insertBackground", "Foreground", DEF_TEXT_INSERT_BG, Tk_Offset(TkText, insertBorder), 0}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_TEXT_INSERT_BD_COLOR, Tk_Offset(TkText, insertBorderWidth), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_PIXELS, "-insertborderwidth", "insertBorderWidth", "BorderWidth", DEF_TEXT_INSERT_BD_MONO, Tk_Offset(TkText, insertBorderWidth), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_INT, "-insertofftime", "insertOffTime", "OffTime", DEF_TEXT_INSERT_OFF_TIME, Tk_Offset(TkText, insertOffTime), 0}, {TK_CONFIG_INT, "-insertontime", "insertOnTime", "OnTime", DEF_TEXT_INSERT_ON_TIME, Tk_Offset(TkText, insertOnTime), 0}, {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", DEF_TEXT_INSERT_WIDTH, Tk_Offset(TkText, insertWidth), 0}, {TK_CONFIG_PIXELS, "-padx", "padX", "Pad", DEF_TEXT_PADX, Tk_Offset(TkText, padX), 0}, {TK_CONFIG_PIXELS, "-pady", "padY", "Pad", DEF_TEXT_PADY, Tk_Offset(TkText, padY), 0}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_TEXT_RELIEF, Tk_Offset(TkText, relief), 0}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_TEXT_SELECT_COLOR, Tk_Offset(TkText, selBorder), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_TEXT_SELECT_MONO, Tk_Offset(TkText, selBorder), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_TEXT_SELECT_BD_COLOR, Tk_Offset(TkText, selBdString), TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_TEXT_SELECT_BD_MONO, Tk_Offset(TkText, selBdString), TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_TEXT_SELECT_FG_COLOR, Tk_Offset(TkText, selFgColorPtr), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_TEXT_SELECT_FG_MONO, Tk_Offset(TkText, selFgColorPtr), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_BOOLEAN, "-setgrid", "setGrid", "SetGrid", DEF_TEXT_SET_GRID, Tk_Offset(TkText, setGrid), 0}, {TK_CONFIG_PIXELS, "-spacing1", "spacing1", "Spacing", DEF_TEXT_SPACING1, Tk_Offset(TkText, spacing1), TK_CONFIG_DONT_SET_DEFAULT}, {TK_CONFIG_PIXELS, "-spacing2", "spacing2", "Spacing", DEF_TEXT_SPACING2, Tk_Offset(TkText, spacing2), TK_CONFIG_DONT_SET_DEFAULT}, {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_STRING, "-tabs", "tabs", "Tabs", DEF_TEXT_TABS, Tk_Offset(TkText, tabOptionString), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_TEXT_TAKE_FOCUS, Tk_Offset(TkText, takeFocus), 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_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_TEXT_XSCROLL_COMMAND, Tk_Offset(TkText, xScrollCmd), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", DEF_TEXT_YSCROLL_COMMAND, Tk_Offset(TkText, yScrollCmd), TK_CONFIG_NULL_OK}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0}};/* * Tk_Uid's used to represent text states: */Tk_Uid tkTextCharUid = NULL;Tk_Uid tkTextDisabledUid = NULL;Tk_Uid tkTextNoneUid = NULL;Tk_Uid tkTextNormalUid = NULL;Tk_Uid tkTextWordUid = NULL;/* * Boolean variable indicating whether or not special debugging code * should be executed. */int tkTextDebug = 0;/* * Forward declarations for procedures defined later in this file: */static int ConfigureText _ANSI_ARGS_((Tcl_Interp *interp, TkText *textPtr, int argc, char **argv, int flags));static int DeleteChars _ANSI_ARGS_((TkText *textPtr, char *index1String, char *index2String));static void DestroyText _ANSI_ARGS_((char *memPtr));static void InsertChars _ANSI_ARGS_((TkText *textPtr, TkTextIndex *indexPtr, char *string));static void TextBlinkProc _ANSI_ARGS_((ClientData clientData));static void TextCmdDeletedProc _ANSI_ARGS_(( ClientData clientData));static void TextEventProc _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr));static int TextFetchSelection _ANSI_ARGS_((ClientData clientData, int offset, char *buffer, int maxBytes));static int TextSearchCmd _ANSI_ARGS_((TkText *textPtr, Tcl_Interp *interp, int argc, char **argv));static int TextWidgetCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv));static void TextWorldChanged _ANSI_ARGS_(( ClientData instanceData));static int TextDumpCmd _ANSI_ARGS_((TkText *textPtr, Tcl_Interp *interp, int argc, char **argv));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, int what));/* * The structure below defines text class behavior by means of procedures * that can be invoked from generic window code. */static TkClassProcs textClass = { NULL, /* createProc. */ TextWorldChanged, /* geometryProc. */ NULL /* modalProc. */};/* *-------------------------------------------------------------- * * Tk_TextCmd -- * * This procedure is invoked to process the "text" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */intTk_TextCmd(clientData, interp, argc, argv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ Tk_Window tkwin = (Tk_Window) clientData; Tk_Window new; register TkText *textPtr; TkTextIndex startIndex; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " pathName ?options?\"", (char *) NULL); return TCL_ERROR; } /* * 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. */ new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); if (new == NULL) { return TCL_ERROR; } textPtr = (TkText *) ckalloc(sizeof(TkText)); textPtr->tkwin = new; textPtr->display = Tk_Display(new); textPtr->interp = interp; textPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(textPtr->tkwin), TextWidgetCmd, (ClientData) textPtr, TextCmdDeletedProc); textPtr->tree = TkBTreeCreate(textPtr); Tcl_InitHashTable(&textPtr->tagTable, TCL_STRING_KEYS); textPtr->numTags = 0; 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->border = NULL; textPtr->borderWidth = 0; textPtr->padX = 0; textPtr->padY = 0; textPtr->relief = TK_RELIEF_FLAT; textPtr->highlightWidth = 0; textPtr->highlightBgColorPtr = NULL; textPtr->highlightColorPtr = NULL; textPtr->cursor = None; textPtr->fgColor = NULL; textPtr->tkfont = NULL; textPtr->charWidth = 1; textPtr->spacing1 = 0; textPtr->spacing2 = 0; textPtr->spacing3 = 0; textPtr->tabOptionString = NULL; textPtr->tabArrayPtr = NULL; textPtr->wrapMode = tkTextCharUid; 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); TkTextSetYView(textPtr, &startIndex, 0); textPtr->selTagPtr = NULL; textPtr->selBorder = NULL; textPtr->selBdString = NULL; textPtr->selFgColorPtr = NULL; textPtr->exportSelection = 1; textPtr->abortSelections = 0; textPtr->insertMarkPtr = NULL; textPtr->insertBorder = NULL; textPtr->insertWidth = 0; textPtr->insertBorderWidth = 0; textPtr->insertOnTime = 0; textPtr->insertOffTime = 0; textPtr->insertBlinkHandler = (Tcl_TimerToken) NULL; textPtr->bindingTable = NULL; textPtr->currentMarkPtr = NULL; textPtr->pickEvent.type = LeaveNotify; textPtr->pickEvent.xcrossing.x = 0; textPtr->pickEvent.xcrossing.y = 0; textPtr->numCurTags = 0; textPtr->curTagArrayPtr = NULL; textPtr->takeFocus = NULL; textPtr->xScrollCmd = NULL; textPtr->yScrollCmd = NULL; textPtr->flags = 0; /* * Create the "sel" tag and the "current" and "insert" marks. */ textPtr->selTagPtr = TkTextCreateTag(textPtr, "sel"); textPtr->selTagPtr->reliefString = (char *) ckalloc(7); strcpy(textPtr->selTagPtr->reliefString, DEF_TEXT_SELECT_RELIEF); textPtr->selTagPtr->relief = TK_RELIEF_RAISED; textPtr->currentMarkPtr = TkTextSetMark(textPtr, "current", &startIndex); textPtr->insertMarkPtr = TkTextSetMark(textPtr, "insert", &startIndex); Tk_SetClass(textPtr->tkwin, "Text"); TkSetClassProcs(textPtr->tkwin, &textClass, (ClientData) textPtr); Tk_CreateEventHandler(textPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, TextEventProc, (ClientData) textPtr); Tk_CreateEventHandler(textPtr->tkwin, KeyPressMask|KeyReleaseMask |ButtonPressMask|ButtonReleaseMask|EnterWindowMask |LeaveWindowMask|PointerMotionMask|VirtualEventMask, TkTextBindProc, (ClientData) textPtr); Tk_CreateSelHandler(textPtr->tkwin, XA_PRIMARY, XA_STRING, TextFetchSelection, (ClientData) textPtr, XA_STRING); if (ConfigureText(interp, textPtr, argc-2, argv+2, 0) != TCL_OK) { Tk_DestroyWindow(textPtr->tkwin); return TCL_ERROR; } interp->result = Tk_PathName(textPtr->tkwin); return TCL_OK;}/* *-------------------------------------------------------------- * * TextWidgetCmd -- * * This procedure is invoked to process the Tcl command * that corresponds to a text widget. See the user * documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */static intTextWidgetCmd(clientData, interp, argc, argv) ClientData clientData; /* Information about text widget. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ register TkText *textPtr = (TkText *) clientData; int result = TCL_OK; size_t length; int c; TkTextIndex index1, index2; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " option ?arg arg ...?\"", (char *) NULL); return TCL_ERROR; } Tcl_Preserve((ClientData) textPtr); c = argv[1][0]; length = strlen(argv[1]); if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { int x, y, width, height; if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " bbox index\"", (char *) NULL); result = TCL_ERROR; goto done; } if (TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) { result = TCL_ERROR; goto done; } if (TkTextCharBbox(textPtr, &index1, &x, &y, &width, &height) == 0) { sprintf(interp->result, "%d %d %d %d", x, y, width, height); } } else if ((c == 'c') && (strncmp(argv[1], "cget", length) == 0) && (length >= 2)) { if (argc != 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " cget option\"", (char *) NULL); result = TCL_ERROR; goto done; } result = Tk_ConfigureValue(interp, textPtr->tkwin, configSpecs, (char *) textPtr, argv[2], 0); } else if ((c == 'c') && (strncmp(argv[1], "compare", length) == 0) && (length >= 3)) { int relation, value; char *p; if (argc != 5) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " compare index1 op index2\"", (char *) NULL); result = TCL_ERROR; goto done; } if ((TkTextGetIndex(interp, textPtr, argv[2], &index1) != TCL_OK) || (TkTextGetIndex(interp, textPtr, argv[4], &index2) != TCL_OK)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -