📄 tklistbox.c
字号:
/* * tkListbox.c -- * * This module implements listbox widgets for the Tk * toolkit. A listbox displays a collection of strings, * one per line, and provides scrolling and selection. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 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: @(#) tkListbox.c 1.120 97/10/29 13:06:59 */#include "tkPort.h"#include "default.h"#include "tkInt.h"/* * One record of the following type is kept for each element * associated with a listbox widget: */typedef struct Element { int textLength; /* # non-NULL characters in text. */ int lBearing; /* Distance from first character's * origin to left edge of character. */ int pixelWidth; /* Total width of element in pixels (including * left bearing and right bearing). */ int selected; /* 1 means this item is selected, 0 means * it isn't. */ struct Element *nextPtr; /* Next in list of all elements of this * listbox, or NULL for last element. */ char text[4]; /* Characters of this element, NULL- * terminated. The actual space allocated * here will be as large as needed (> 4, * most likely). Must be the last field * of the record. */} Element;#define ElementSize(stringLength) \ ((unsigned) (sizeof(Element) - 3 + stringLength))/* * A data structure of the following type is kept for each listbox * widget managed by this file: */typedef struct { Tk_Window tkwin; /* Window that embodies the listbox. NULL * means that the window has been destroyed * but the data structures haven't yet been * cleaned up.*/ Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with listbox. */ Tcl_Command widgetCmd; /* Token for listbox's widget command. */ int numElements; /* Total number of elements in this listbox. */ Element *firstPtr; /* First in list of elements (NULL if no * elements). */ Element *lastPtr; /* Last in list of elements (NULL if no * elements). */ /* * Information used when displaying widget: */ Tk_3DBorder normalBorder; /* Used for drawing border around whole * window, plus used for background. */ int borderWidth; /* Width of 3-D border around window. */ int relief; /* 3-D effect: TK_RELIEF_RAISED, etc. */ int highlightWidth; /* Width in pixels of highlight to draw * around widget when it has the focus. * <= 0 means don't draw a highlight. */ XColor *highlightBgColorPtr; /* Color for drawing traversal highlight * area when highlight is off. */ XColor *highlightColorPtr; /* Color for drawing traversal highlight. */ int inset; /* Total width of all borders, including * traversal highlight and 3-D border. * Indicates how much interior stuff must * be offset from outside edges to leave * room for borders. */ Tk_Font tkfont; /* Information about text font, or NULL. */ XColor *fgColorPtr; /* Text color in normal mode. */ GC textGC; /* For drawing normal text. */ Tk_3DBorder selBorder; /* Borders and backgrounds for selected * elements. */ int selBorderWidth; /* Width of border around selection. */ XColor *selFgColorPtr; /* Foreground color for selected elements. */ GC selTextGC; /* For drawing selected text. */ int width; /* Desired width of window, in characters. */ int height; /* Desired height of window, in lines. */ int lineHeight; /* Number of pixels allocated for each line * in display. */ int topIndex; /* Index of top-most element visible in * window. */ int fullLines; /* Number of lines that fit are completely * visible in window. There may be one * additional line at the bottom that is * partially visible. */ int partialLine; /* 0 means that the window holds exactly * fullLines lines. 1 means that there is * one additional line that is partially * visble. */ int setGrid; /* Non-zero means pass gridding information * to window manager. */ /* * Information to support horizontal scrolling: */ int maxWidth; /* Width (in pixels) of widest string in * listbox. */ int xScrollUnit; /* Number of pixels in one "unit" for * horizontal scrolling (window scrolls * horizontally in increments of this size). * This is an average character size. */ int xOffset; /* The left edge of each string in the * listbox is offset to the left by this * many pixels (0 means no offset, positive * means there is an offset). */ /* * Information about what's selected or active, if any. */ Tk_Uid selectMode; /* Selection style: single, browse, multiple, * or extended. This value isn't used in C * code, but the Tcl bindings use it. */ int numSelected; /* Number of elements currently selected. */ int selectAnchor; /* Fixed end of selection (i.e. element * at which selection was started.) */ int exportSelection; /* Non-zero means tie internal listbox * to X selection. */ int active; /* Index of "active" element (the one that * has been selected by keyboard traversal). * -1 means none. */ /* * Information for scanning: */ int scanMarkX; /* X-position at which scan started (e.g. * button was pressed here). */ int scanMarkY; /* Y-position at which scan started (e.g. * button was pressed here). */ int scanMarkXOffset; /* Value of "xOffset" field when scan * started. */ int scanMarkYIndex; /* Index of line that was at top of window * when scan started. */ /* * Miscellaneous information: */ Tk_Cursor cursor; /* Current cursor for window, or None. */ char *takeFocus; /* Value of -takefocus option; not used in * the C code, but used by keyboard traversal * scripts. Malloc'ed, but may be NULL. */ char *yScrollCmd; /* Command prefix for communicating with * vertical scrollbar. NULL means no command * to issue. Malloc'ed. */ char *xScrollCmd; /* Command prefix for communicating with * horizontal scrollbar. NULL means no command * to issue. Malloc'ed. */ int flags; /* Various flag bits: see below for * definitions. */} Listbox;/* * Flag bits for listboxes: * * REDRAW_PENDING: Non-zero means a DoWhenIdle handler * has already been queued to redraw * this window. * UPDATE_V_SCROLLBAR: Non-zero means vertical scrollbar needs * to be updated. * UPDATE_H_SCROLLBAR: Non-zero means horizontal scrollbar needs * to be updated. * GOT_FOCUS: Non-zero means this widget currently * has the input focus. */#define REDRAW_PENDING 1#define UPDATE_V_SCROLLBAR 2#define UPDATE_H_SCROLLBAR 4#define GOT_FOCUS 8/* * Information used for argv parsing: */static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_LISTBOX_BG_COLOR, Tk_Offset(Listbox, normalBorder), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-background", "background", "Background", DEF_LISTBOX_BG_MONO, Tk_Offset(Listbox, normalBorder), 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_LISTBOX_BORDER_WIDTH, Tk_Offset(Listbox, borderWidth), 0}, {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor", DEF_LISTBOX_CURSOR, Tk_Offset(Listbox, cursor), TK_CONFIG_NULL_OK}, {TK_CONFIG_BOOLEAN, "-exportselection", "exportSelection", "ExportSelection", DEF_LISTBOX_EXPORT_SELECTION, Tk_Offset(Listbox, exportSelection), 0}, {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL, (char *) NULL, 0, 0}, {TK_CONFIG_FONT, "-font", "font", "Font", DEF_LISTBOX_FONT, Tk_Offset(Listbox, tkfont), 0}, {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground", DEF_LISTBOX_FG, Tk_Offset(Listbox, fgColorPtr), 0}, {TK_CONFIG_INT, "-height", "height", "Height", DEF_LISTBOX_HEIGHT, Tk_Offset(Listbox, height), 0}, {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground", "HighlightBackground", DEF_LISTBOX_HIGHLIGHT_BG, Tk_Offset(Listbox, highlightBgColorPtr), 0}, {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor", DEF_LISTBOX_HIGHLIGHT, Tk_Offset(Listbox, highlightColorPtr), 0}, {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness", "HighlightThickness", DEF_LISTBOX_HIGHLIGHT_WIDTH, Tk_Offset(Listbox, highlightWidth), 0}, {TK_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_LISTBOX_RELIEF, Tk_Offset(Listbox, relief), 0}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_LISTBOX_SELECT_COLOR, Tk_Offset(Listbox, selBorder), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground", DEF_LISTBOX_SELECT_MONO, Tk_Offset(Listbox, selBorder), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth", "BorderWidth", DEF_LISTBOX_SELECT_BD, Tk_Offset(Listbox, selBorderWidth), 0}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_LISTBOX_SELECT_FG_COLOR, Tk_Offset(Listbox, selFgColorPtr), TK_CONFIG_COLOR_ONLY}, {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background", DEF_LISTBOX_SELECT_FG_MONO, Tk_Offset(Listbox, selFgColorPtr), TK_CONFIG_MONO_ONLY}, {TK_CONFIG_UID, "-selectmode", "selectMode", "SelectMode", DEF_LISTBOX_SELECT_MODE, Tk_Offset(Listbox, selectMode), 0}, {TK_CONFIG_BOOLEAN, "-setgrid", "setGrid", "SetGrid", DEF_LISTBOX_SET_GRID, Tk_Offset(Listbox, setGrid), 0}, {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", DEF_LISTBOX_TAKE_FOCUS, Tk_Offset(Listbox, takeFocus), TK_CONFIG_NULL_OK}, {TK_CONFIG_INT, "-width", "width", "Width", DEF_LISTBOX_WIDTH, Tk_Offset(Listbox, width), 0}, {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand", DEF_LISTBOX_SCROLL_COMMAND, Tk_Offset(Listbox, xScrollCmd), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand", DEF_LISTBOX_SCROLL_COMMAND, Tk_Offset(Listbox, yScrollCmd), 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 ChangeListboxOffset _ANSI_ARGS_((Listbox *listPtr, int offset));static void ChangeListboxView _ANSI_ARGS_((Listbox *listPtr, int index));static int ConfigureListbox _ANSI_ARGS_((Tcl_Interp *interp, Listbox *listPtr, int argc, char **argv, int flags));static void DeleteEls _ANSI_ARGS_((Listbox *listPtr, int first, int last));static void DestroyListbox _ANSI_ARGS_((char *memPtr));static void DisplayListbox _ANSI_ARGS_((ClientData clientData));static int GetListboxIndex _ANSI_ARGS_((Tcl_Interp *interp, Listbox *listPtr, char *string, int endIsSize, int *indexPtr));static void InsertEls _ANSI_ARGS_((Listbox *listPtr, int index, int argc, char **argv));static void ListboxCmdDeletedProc _ANSI_ARGS_(( ClientData clientData));static void ListboxComputeGeometry _ANSI_ARGS_((Listbox *listPtr, int fontChanged, int maxIsStale, int updateGrid));static void ListboxEventProc _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr));static int ListboxFetchSelection _ANSI_ARGS_(( ClientData clientData, int offset, char *buffer, int maxBytes));static void ListboxLostSelection _ANSI_ARGS_(( ClientData clientData));static void ListboxRedrawRange _ANSI_ARGS_((Listbox *listPtr, int first, int last));static void ListboxScanTo _ANSI_ARGS_((Listbox *listPtr, int x, int y));static void ListboxSelect _ANSI_ARGS_((Listbox *listPtr, int first, int last, int select));static void ListboxUpdateHScrollbar _ANSI_ARGS_((Listbox *listPtr));static void ListboxUpdateVScrollbar _ANSI_ARGS_((Listbox *listPtr));static int ListboxWidgetCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int argc, char **argv));static void ListboxWorldChanged _ANSI_ARGS_(( ClientData instanceData));static int NearestListboxElement _ANSI_ARGS_((Listbox *listPtr, int y));/* * The structure below defines button class behavior by means of procedures * that can be invoked from generic window code. */static TkClassProcs listboxClass = { NULL, /* createProc. */ ListboxWorldChanged, /* geometryProc. */ NULL /* modalProc. */};/* *-------------------------------------------------------------- * * Tk_ListboxCmd -- * * This procedure is invoked to process the "listbox" Tcl * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */intTk_ListboxCmd(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. */{ register Listbox *listPtr; Tk_Window new; Tk_Window tkwin = (Tk_Window) clientData; if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " pathName ?options?\"", (char *) NULL); return TCL_ERROR; } new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], (char *) NULL); if (new == NULL) { return TCL_ERROR; } /* * Initialize the fields of the structure that won't be initialized * by ConfigureListbox, or that ConfigureListbox requires to be * initialized already (e.g. resource pointers). */ listPtr = (Listbox *) ckalloc(sizeof(Listbox)); listPtr->tkwin = new; listPtr->display = Tk_Display(new); listPtr->interp = interp; listPtr->widgetCmd = Tcl_CreateCommand(interp, Tk_PathName(listPtr->tkwin), ListboxWidgetCmd, (ClientData) listPtr, ListboxCmdDeletedProc); listPtr->numElements = 0; listPtr->firstPtr = NULL; listPtr->lastPtr = NULL; listPtr->normalBorder = NULL; listPtr->borderWidth = 0; listPtr->relief = TK_RELIEF_RAISED; listPtr->highlightWidth = 0; listPtr->highlightBgColorPtr = NULL; listPtr->highlightColorPtr = NULL; listPtr->inset = 0; listPtr->tkfont = NULL; listPtr->fgColorPtr = NULL; listPtr->textGC = None; listPtr->selBorder = NULL; listPtr->selBorderWidth = 0; listPtr->selFgColorPtr = None; listPtr->selTextGC = None; listPtr->width = 0; listPtr->height = 0; listPtr->lineHeight = 0; listPtr->topIndex = 0; listPtr->fullLines = 1; listPtr->partialLine = 0; listPtr->setGrid = 0; listPtr->maxWidth = 0; listPtr->xScrollUnit = 1; listPtr->xOffset = 0; listPtr->selectMode = NULL; listPtr->numSelected = 0; listPtr->selectAnchor = 0; listPtr->exportSelection = 1; listPtr->active = 0; listPtr->scanMarkX = 0; listPtr->scanMarkY = 0; listPtr->scanMarkXOffset = 0; listPtr->scanMarkYIndex = 0; listPtr->cursor = None; listPtr->takeFocus = NULL; listPtr->xScrollCmd = NULL; listPtr->yScrollCmd = NULL; listPtr->flags = 0; Tk_SetClass(listPtr->tkwin, "Listbox"); TkSetClassProcs(listPtr->tkwin, &listboxClass, (ClientData) listPtr); Tk_CreateEventHandler(listPtr->tkwin, ExposureMask|StructureNotifyMask|FocusChangeMask, ListboxEventProc, (ClientData) listPtr); Tk_CreateSelHandler(listPtr->tkwin, XA_PRIMARY, XA_STRING, ListboxFetchSelection, (ClientData) listPtr, XA_STRING); if (ConfigureListbox(interp, listPtr, argc-2, argv+2, 0) != TCL_OK) { goto error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -