tkEntry.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:129k
- /*
- * Entry.c --
- *
- * This module implements entry and spinbox widgets for the Tk toolkit.
- * An entry displays a string and allows the string to be edited.
- * A spinbox expands on the entry by adding up/down buttons that control
- * the value of the entry widget.
- *
- * Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
- * Copyright (c) 2000 Ajuba Solutions.
- * Copyright (c) 2002 ActiveState Corporation.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tkEntry.c,v 1.35.2.4 2007/04/29 02:24:02 das Exp $
- */
- #include "tkInt.h"
- #include "default.h"
- #include "tkEntry.h"
- /*
- * The following macro defines how many extra pixels to leave on each
- * side of the text in the entry.
- */
- #define XPAD 1
- #define YPAD 1
- /*
- * A comparison function for double values. For Spinboxes.
- */
- #define MIN_DBL_VAL 1E-9
- #define DOUBLES_EQ(d1, d2) (fabs((d1) - (d2)) < MIN_DBL_VAL)
- static char *stateStrings[] = {
- "disabled", "normal", "readonly", (char *) NULL
- };
- /*
- * Definitions for -validate option values:
- */
- static char *validateStrings[] = {
- "all", "key", "focus", "focusin", "focusout", "none", (char *) NULL
- };
- enum validateType {
- VALIDATE_ALL, VALIDATE_KEY, VALIDATE_FOCUS,
- VALIDATE_FOCUSIN, VALIDATE_FOCUSOUT, VALIDATE_NONE,
- /*
- * These extra enums are for use with EntryValidateChange
- */
- VALIDATE_FORCED, VALIDATE_DELETE, VALIDATE_INSERT, VALIDATE_BUTTON
- };
- #define DEF_ENTRY_VALIDATE "none"
- #define DEF_ENTRY_INVALIDCMD ""
- /*
- * Information used for Entry objv parsing.
- */
- static Tk_OptionSpec entryOptSpec[] = {
- {TK_OPTION_BORDER, "-background", "background", "Background",
- DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
- 0, (ClientData) DEF_ENTRY_BG_MONO, 0},
- {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
- {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth),
- 0, 0, 0},
- {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
- "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
- Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
- (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
- {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
- "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
- Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
- "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
- Tk_Offset(Entry, exportSelection), 0, 0, 0},
- {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
- {TK_OPTION_FONT, "-font", "font", "Font",
- DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
- {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
- DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0,
- 0, 0},
- {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
- -1, Tk_Offset(Entry, highlightBgColorPtr),
- 0, 0, 0},
- {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
- Tk_Offset(Entry, highlightWidth), 0, 0, 0},
- {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
- DEF_ENTRY_INSERT_BG,
- -1, Tk_Offset(Entry, insertBorder),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
- "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
- Tk_Offset(Entry, insertBorderWidth), 0,
- (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
- {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
- DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
- 0, 0, 0},
- {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
- DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
- DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth),
- 0, 0, 0},
- {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
- DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0},
- {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
- DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
- {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
- "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
- Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
- (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief),
- 0, 0, 0},
- {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
- 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0},
- {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
- "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
- Tk_Offset(Entry, selBorderWidth),
- 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
- {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
- {TK_OPTION_STRING, "-show", "show", "Show",
- DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_STRING_TABLE, "-state", "state", "State",
- DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
- 0, (ClientData) stateStrings, 0},
- {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
- DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
- DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
- 0, (ClientData) validateStrings, 0},
- {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
- (char *) NULL, -1, Tk_Offset(Entry, validateCmd),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0},
- {TK_OPTION_INT, "-width", "width", "Width",
- DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
- {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, 0, 0}
- };
- /*
- * Information used for Spinbox objv parsing.
- */
- #define DEF_SPINBOX_REPEAT_DELAY "400"
- #define DEF_SPINBOX_REPEAT_INTERVAL "100"
- #define DEF_SPINBOX_CMD ""
- #define DEF_SPINBOX_FROM "0"
- #define DEF_SPINBOX_TO "0"
- #define DEF_SPINBOX_INCREMENT "1"
- #define DEF_SPINBOX_FORMAT ""
- #define DEF_SPINBOX_VALUES ""
- #define DEF_SPINBOX_WRAP "0"
- static Tk_OptionSpec sbOptSpec[] = {
- {TK_OPTION_BORDER, "-activebackground", "activeBackground", "Background",
- DEF_BUTTON_ACTIVE_BG_COLOR, -1, Tk_Offset(Spinbox, activeBorder),
- 0, (ClientData) DEF_BUTTON_ACTIVE_BG_MONO, 0},
- {TK_OPTION_BORDER, "-background", "background", "Background",
- DEF_ENTRY_BG_COLOR, -1, Tk_Offset(Entry, normalBorder),
- 0, (ClientData) DEF_ENTRY_BG_MONO, 0},
- {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
- {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_ENTRY_BORDER_WIDTH, -1, Tk_Offset(Entry, borderWidth),
- 0, 0, 0},
- {TK_OPTION_BORDER, "-buttonbackground", "Button.background", "Background",
- DEF_BUTTON_BG_COLOR, -1, Tk_Offset(Spinbox, buttonBorder),
- 0, (ClientData) DEF_BUTTON_BG_MONO, 0},
- {TK_OPTION_CURSOR, "-buttoncursor", "Button.cursor", "Cursor",
- DEF_BUTTON_CURSOR, -1, Tk_Offset(Spinbox, bCursor),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_RELIEF, "-buttondownrelief", "Button.relief", "Relief",
- DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, bdRelief),
- 0, 0, 0},
- {TK_OPTION_RELIEF, "-buttonuprelief", "Button.relief", "Relief",
- DEF_BUTTON_RELIEF, -1, Tk_Offset(Spinbox, buRelief),
- 0, 0, 0},
- {TK_OPTION_STRING, "-command", "command", "Command",
- DEF_SPINBOX_CMD, -1, Tk_Offset(Spinbox, command),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_ENTRY_CURSOR, -1, Tk_Offset(Entry, cursor),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_BORDER, "-disabledbackground", "disabledBackground",
- "DisabledBackground", DEF_ENTRY_DISABLED_BG_COLOR, -1,
- Tk_Offset(Entry, disabledBorder), TK_OPTION_NULL_OK,
- (ClientData) DEF_ENTRY_DISABLED_BG_MONO, 0},
- {TK_OPTION_COLOR, "-disabledforeground", "disabledForeground",
- "DisabledForeground", DEF_ENTRY_DISABLED_FG, -1,
- Tk_Offset(Entry, dfgColorPtr), TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_BOOLEAN, "-exportselection", "exportSelection",
- "ExportSelection", DEF_ENTRY_EXPORT_SELECTION, -1,
- Tk_Offset(Entry, exportSelection), 0, 0, 0},
- {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
- {TK_OPTION_FONT, "-font", "font", "Font",
- DEF_ENTRY_FONT, -1, Tk_Offset(Entry, tkfont), 0, 0, 0},
- {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
- DEF_ENTRY_FG, -1, Tk_Offset(Entry, fgColorPtr), 0,
- 0, 0},
- {TK_OPTION_STRING, "-format", "format", "Format",
- DEF_SPINBOX_FORMAT, -1, Tk_Offset(Spinbox, reqFormat),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_DOUBLE, "-from", "from", "From",
- DEF_SPINBOX_FROM, -1, Tk_Offset(Spinbox, fromValue), 0, 0, 0},
- {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_ENTRY_HIGHLIGHT_BG,
- -1, Tk_Offset(Entry, highlightBgColorPtr),
- 0, 0, 0},
- {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_ENTRY_HIGHLIGHT, -1, Tk_Offset(Entry, highlightColorPtr),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness", DEF_ENTRY_HIGHLIGHT_WIDTH, -1,
- Tk_Offset(Entry, highlightWidth), 0, 0, 0},
- {TK_OPTION_DOUBLE, "-increment", "increment", "Increment",
- DEF_SPINBOX_INCREMENT, -1, Tk_Offset(Spinbox, increment), 0, 0, 0},
- {TK_OPTION_BORDER, "-insertbackground", "insertBackground", "Foreground",
- DEF_ENTRY_INSERT_BG, -1, Tk_Offset(Entry, insertBorder),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-insertborderwidth", "insertBorderWidth",
- "BorderWidth", DEF_ENTRY_INSERT_BD_COLOR, -1,
- Tk_Offset(Entry, insertBorderWidth), 0,
- (ClientData) DEF_ENTRY_INSERT_BD_MONO, 0},
- {TK_OPTION_INT, "-insertofftime", "insertOffTime", "OffTime",
- DEF_ENTRY_INSERT_OFF_TIME, -1, Tk_Offset(Entry, insertOffTime),
- 0, 0, 0},
- {TK_OPTION_INT, "-insertontime", "insertOnTime", "OnTime",
- DEF_ENTRY_INSERT_ON_TIME, -1, Tk_Offset(Entry, insertOnTime),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth",
- DEF_ENTRY_INSERT_WIDTH, -1, Tk_Offset(Entry, insertWidth),
- 0, 0, 0},
- {TK_OPTION_STRING, "-invalidcommand", "invalidCommand", "InvalidCommand",
- DEF_ENTRY_INVALIDCMD, -1, Tk_Offset(Entry, invalidCmd),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_SYNONYM, "-invcmd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-invalidcommand", 0},
- {TK_OPTION_JUSTIFY, "-justify", "justify", "Justify",
- DEF_ENTRY_JUSTIFY, -1, Tk_Offset(Entry, justify), 0, 0, 0},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_ENTRY_RELIEF, -1, Tk_Offset(Entry, relief),
- 0, 0, 0},
- {TK_OPTION_BORDER, "-readonlybackground", "readonlyBackground",
- "ReadonlyBackground", DEF_ENTRY_READONLY_BG_COLOR, -1,
- Tk_Offset(Entry, readonlyBorder), TK_OPTION_NULL_OK,
- (ClientData) DEF_ENTRY_READONLY_BG_MONO, 0},
- {TK_OPTION_INT, "-repeatdelay", "repeatDelay", "RepeatDelay",
- DEF_SPINBOX_REPEAT_DELAY, -1, Tk_Offset(Spinbox, repeatDelay),
- 0, 0, 0},
- {TK_OPTION_INT, "-repeatinterval", "repeatInterval", "RepeatInterval",
- DEF_SPINBOX_REPEAT_INTERVAL, -1, Tk_Offset(Spinbox, repeatInterval),
- 0, 0, 0},
- {TK_OPTION_BORDER, "-selectbackground", "selectBackground", "Foreground",
- DEF_ENTRY_SELECT_COLOR, -1, Tk_Offset(Entry, selBorder),
- 0, (ClientData) DEF_ENTRY_SELECT_MONO, 0},
- {TK_OPTION_PIXELS, "-selectborderwidth", "selectBorderWidth",
- "BorderWidth", DEF_ENTRY_SELECT_BD_COLOR, -1,
- Tk_Offset(Entry, selBorderWidth),
- 0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
- {TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
- DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
- {TK_OPTION_STRING_TABLE, "-state", "state", "State",
- DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
- 0, (ClientData) stateStrings, 0},
- {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
- TK_CONFIG_NULL_OK, 0, 0},
- {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
- DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
- TK_CONFIG_NULL_OK, 0, 0},
- {TK_OPTION_DOUBLE, "-to", "to", "To",
- DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0},
- {TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
- DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
- 0, (ClientData) validateStrings, 0},
- {TK_OPTION_STRING, "-validatecommand", "validateCommand", "ValidateCommand",
- (char *) NULL, -1, Tk_Offset(Entry, validateCmd),
- TK_CONFIG_NULL_OK, 0, 0},
- {TK_OPTION_STRING, "-values", "values", "Values",
- DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_SYNONYM, "-vcmd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-validatecommand", 0},
- {TK_OPTION_INT, "-width", "width", "Width",
- DEF_ENTRY_WIDTH, -1, Tk_Offset(Entry, prefWidth), 0, 0, 0},
- {TK_OPTION_BOOLEAN, "-wrap", "wrap", "Wrap",
- DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0},
- {TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
- DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
- TK_CONFIG_NULL_OK, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, 0, 0}
- };
- /*
- * The following tables define the entry widget commands (and sub-
- * commands) and map the indexes into the string tables into
- * enumerated types used to dispatch the entry widget command.
- */
- static CONST char *entryCmdNames[] = {
- "bbox", "cget", "configure", "delete", "get", "icursor", "index",
- "insert", "scan", "selection", "validate", "xview", (char *) NULL
- };
- enum entryCmd {
- COMMAND_BBOX, COMMAND_CGET, COMMAND_CONFIGURE, COMMAND_DELETE,
- COMMAND_GET, COMMAND_ICURSOR, COMMAND_INDEX, COMMAND_INSERT,
- COMMAND_SCAN, COMMAND_SELECTION, COMMAND_VALIDATE, COMMAND_XVIEW
- };
- static CONST char *selCmdNames[] = {
- "adjust", "clear", "from", "present", "range", "to", (char *) NULL
- };
- enum selCmd {
- SELECTION_ADJUST, SELECTION_CLEAR, SELECTION_FROM,
- SELECTION_PRESENT, SELECTION_RANGE, SELECTION_TO
- };
- /*
- * The following tables define the spinbox widget commands (and sub-
- * commands) and map the indexes into the string tables into
- * enumerated types used to dispatch the spinbox widget command.
- */
- static CONST char *sbCmdNames[] = {
- "bbox", "cget", "configure", "delete", "get", "icursor", "identify",
- "index", "insert", "invoke", "scan", "selection", "set",
- "validate", "xview", (char *) NULL
- };
- enum sbCmd {
- SB_CMD_BBOX, SB_CMD_CGET, SB_CMD_CONFIGURE, SB_CMD_DELETE,
- SB_CMD_GET, SB_CMD_ICURSOR, SB_CMD_IDENTIFY, SB_CMD_INDEX,
- SB_CMD_INSERT, SB_CMD_INVOKE, SB_CMD_SCAN, SB_CMD_SELECTION,
- SB_CMD_SET, SB_CMD_VALIDATE, SB_CMD_XVIEW
- };
- static CONST char *sbSelCmdNames[] = {
- "adjust", "clear", "element", "from", "present", "range", "to",
- (char *) NULL
- };
- enum sbselCmd {
- SB_SEL_ADJUST, SB_SEL_CLEAR, SB_SEL_ELEMENT, SB_SEL_FROM,
- SB_SEL_PRESENT, SB_SEL_RANGE, SB_SEL_TO
- };
- /*
- * Extra for selection of elements
- */
- /*
- * This is the string array corresponding to the enum in selelement.
- * If you modify them, you must modify the strings here.
- */
-
- static CONST char *selElementNames[] = {
- "none", "buttondown", "buttonup", (char *) NULL, "entry"
- };
- /*
- * Flags for GetEntryIndex procedure:
- */
- #define ZERO_OK 1
- #define LAST_PLUS_ONE_OK 2
- /*
- * Forward declarations for procedures defined later in this file:
- */
- static int ConfigureEntry _ANSI_ARGS_((Tcl_Interp *interp,
- Entry *entryPtr, int objc,
- Tcl_Obj *CONST objv[], int flags));
- static void DeleteChars _ANSI_ARGS_((Entry *entryPtr, int index,
- int count));
- static void DestroyEntry _ANSI_ARGS_((char *memPtr));
- static void DisplayEntry _ANSI_ARGS_((ClientData clientData));
- static void EntryBlinkProc _ANSI_ARGS_((ClientData clientData));
- static void EntryCmdDeletedProc _ANSI_ARGS_((
- ClientData clientData));
- static void EntryComputeGeometry _ANSI_ARGS_((Entry *entryPtr));
- static void EntryEventProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
- static void EntryFocusProc _ANSI_ARGS_ ((Entry *entryPtr,
- int gotFocus));
- static int EntryFetchSelection _ANSI_ARGS_((ClientData clientData,
- int offset, char *buffer, int maxBytes));
- static void EntryLostSelection _ANSI_ARGS_((
- ClientData clientData));
- static void EventuallyRedraw _ANSI_ARGS_((Entry *entryPtr));
- static void EntryScanTo _ANSI_ARGS_((Entry *entryPtr, int y));
- static void EntrySetValue _ANSI_ARGS_((Entry *entryPtr,
- CONST char *value));
- static void EntrySelectTo _ANSI_ARGS_((
- Entry *entryPtr, int index));
- static char * EntryTextVarProc _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, CONST char *name1,
- CONST char *name2, int flags));
- static void EntryUpdateScrollbar _ANSI_ARGS_((Entry *entryPtr));
- static int EntryValidate _ANSI_ARGS_((Entry *entryPtr,
- char *cmd));
- static int EntryValidateChange _ANSI_ARGS_((Entry *entryPtr,
- char *change, CONST char *new, int index,
- int type));
- static void ExpandPercents _ANSI_ARGS_((Entry *entryPtr,
- CONST char *before, char *change, CONST char *new,
- int index, int type, Tcl_DString *dsPtr));
- static void EntryValueChanged _ANSI_ARGS_((Entry *entryPtr,
- CONST char *newValue));
- static void EntryVisibleRange _ANSI_ARGS_((Entry *entryPtr,
- double *firstPtr, double *lastPtr));
- static int EntryWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
- static void EntryWorldChanged _ANSI_ARGS_((
- ClientData instanceData));
- static int GetEntryIndex _ANSI_ARGS_((Tcl_Interp *interp,
- Entry *entryPtr, char *string, int *indexPtr));
- static void InsertChars _ANSI_ARGS_((Entry *entryPtr, int index,
- char *string));
- /*
- * These forward declarations are the spinbox specific ones:
- */
- static int SpinboxWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[]));
- static int GetSpinboxElement _ANSI_ARGS_((Spinbox *sbPtr,
- int x, int y));
- static int SpinboxInvoke _ANSI_ARGS_((Tcl_Interp *interp,
- Spinbox *sbPtr, int element));
- static int ComputeFormat _ANSI_ARGS_((Spinbox *sbPtr));
- /*
- * The structure below defines widget class behavior by means of procedures
- * that can be invoked from generic window code.
- */
- static Tk_ClassProcs entryClass = {
- sizeof(Tk_ClassProcs), /* size */
- EntryWorldChanged, /* worldChangedProc */
- };
- /*
- *--------------------------------------------------------------
- *
- * Tk_EntryObjCmd --
- *
- * This procedure is invoked to process the "entry" Tcl
- * command. See the user documentation for details on what
- * it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
- int
- Tk_EntryObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* NULL. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- register Entry *entryPtr;
- Tk_OptionTable optionTable;
- Tk_Window tkwin;
- char *tmp;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
- return TCL_ERROR;
- }
- tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
- Tcl_GetString(objv[1]), (char *) NULL);
- if (tkwin == NULL) {
- return TCL_ERROR;
- }
- /*
- * Create the option table for this widget class. If it has already
- * been created, Tk will return the cached value.
- */
- optionTable = Tk_CreateOptionTable(interp, entryOptSpec);
- /*
- * Initialize the fields of the structure that won't be initialized
- * by ConfigureEntry, or that ConfigureEntry requires to be
- * initialized already (e.g. resource pointers). Only the non-NULL/0
- * data must be initialized as memset covers the rest.
- */
- entryPtr = (Entry *) ckalloc(sizeof(Entry));
- memset((VOID *) entryPtr, 0, sizeof(Entry));
- entryPtr->tkwin = tkwin;
- entryPtr->display = Tk_Display(tkwin);
- entryPtr->interp = interp;
- entryPtr->widgetCmd = Tcl_CreateObjCommand(interp,
- Tk_PathName(entryPtr->tkwin), EntryWidgetObjCmd,
- (ClientData) entryPtr, EntryCmdDeletedProc);
- entryPtr->optionTable = optionTable;
- entryPtr->type = TK_ENTRY;
- tmp = (char *) ckalloc(1);
- tmp[0] = ' ';
- entryPtr->string = tmp;
- entryPtr->selectFirst = -1;
- entryPtr->selectLast = -1;
- entryPtr->cursor = None;
- entryPtr->exportSelection = 1;
- entryPtr->justify = TK_JUSTIFY_LEFT;
- entryPtr->relief = TK_RELIEF_FLAT;
- entryPtr->state = STATE_NORMAL;
- entryPtr->displayString = entryPtr->string;
- entryPtr->inset = XPAD;
- entryPtr->textGC = None;
- entryPtr->selTextGC = None;
- entryPtr->highlightGC = None;
- entryPtr->avgWidth = 1;
- entryPtr->validate = VALIDATE_NONE;
- /*
- * Keep a hold of the associated tkwin until we destroy the listbox,
- * otherwise Tk might free it while we still need it.
- */
- Tcl_Preserve((ClientData) entryPtr->tkwin);
- Tk_SetClass(entryPtr->tkwin, "Entry");
- Tk_SetClassProcs(entryPtr->tkwin, &entryClass, (ClientData) entryPtr);
- Tk_CreateEventHandler(entryPtr->tkwin,
- ExposureMask|StructureNotifyMask|FocusChangeMask,
- EntryEventProc, (ClientData) entryPtr);
- Tk_CreateSelHandler(entryPtr->tkwin, XA_PRIMARY, XA_STRING,
- EntryFetchSelection, (ClientData) entryPtr, XA_STRING);
- if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
- != TCL_OK) ||
- (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK)) {
- Tk_DestroyWindow(entryPtr->tkwin);
- return TCL_ERROR;
- }
- Tcl_SetResult(interp, Tk_PathName(entryPtr->tkwin), TCL_STATIC);
- return TCL_OK;
- }
- /*
- *--------------------------------------------------------------
- *
- * EntryWidgetObjCmd --
- *
- * This procedure is invoked to process the Tcl command
- * that corresponds to a widget managed by this module.
- * See the user documentation for details on what it does.
- *
- * Results:
- * A standard Tcl result.
- *
- * Side effects:
- * See the user documentation.
- *
- *--------------------------------------------------------------
- */
- static int
- EntryWidgetObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Information about entry widget. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- Entry *entryPtr = (Entry *) clientData;
- int cmdIndex, selIndex, result;
- Tcl_Obj *objPtr;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
- return TCL_ERROR;
- }
- /*
- * Parse the widget command by looking up the second token in
- * the list of valid command names.
- */
- result = Tcl_GetIndexFromObj(interp, objv[1], entryCmdNames,
- "option", 0, &cmdIndex);
- if (result != TCL_OK) {
- return result;
- }
- Tcl_Preserve((ClientData) entryPtr);
- switch ((enum entryCmd) cmdIndex) {
- case COMMAND_BBOX: {
- int index, x, y, width, height;
- char buf[TCL_INTEGER_SPACE * 4];
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "index");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &index) != TCL_OK) {
- goto error;
- }
- if ((index == entryPtr->numChars) && (index > 0)) {
- index--;
- }
- Tk_CharBbox(entryPtr->textLayout, index, &x, &y,
- &width, &height);
- sprintf(buf, "%d %d %d %d", x + entryPtr->layoutX,
- y + entryPtr->layoutY, width, height);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- break;
- }
-
- case COMMAND_CGET: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "option");
- goto error;
- }
-
- objPtr = Tk_GetOptionValue(interp, (char *) entryPtr,
- entryPtr->optionTable, objv[2], entryPtr->tkwin);
- if (objPtr == NULL) {
- goto error;
- } else {
- Tcl_SetObjResult(interp, objPtr);
- }
- break;
- }
- case COMMAND_CONFIGURE: {
- if (objc <= 3) {
- objPtr = Tk_GetOptionInfo(interp, (char *) entryPtr,
- entryPtr->optionTable,
- (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
- entryPtr->tkwin);
- if (objPtr == NULL) {
- goto error;
- } else {
- Tcl_SetObjResult(interp, objPtr);
- }
- } else {
- result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
- }
- break;
- }
- case COMMAND_DELETE: {
- int first, last;
- if ((objc < 3) || (objc > 4)) {
- Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &first) != TCL_OK) {
- goto error;
- }
- if (objc == 3) {
- last = first + 1;
- } else {
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[3]),
- &last) != TCL_OK) {
- goto error;
- }
- }
- if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
- DeleteChars(entryPtr, first, last - first);
- }
- break;
- }
- case COMMAND_GET: {
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
- goto error;
- }
- Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1);
- break;
- }
- case COMMAND_ICURSOR: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "pos");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &entryPtr->insertPos) != TCL_OK) {
- goto error;
- }
- EventuallyRedraw(entryPtr);
- break;
- }
-
- case COMMAND_INDEX: {
- int index;
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "string");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &index) != TCL_OK) {
- goto error;
- }
- Tcl_SetObjResult(interp, Tcl_NewIntObj(index));
- break;
- }
- case COMMAND_INSERT: {
- int index;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "index text");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &index) != TCL_OK) {
- goto error;
- }
- if (entryPtr->state == STATE_NORMAL) {
- InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
- }
- break;
- }
- case COMMAND_SCAN: {
- int x;
- char *minorCmd;
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 2, objv, "mark|dragto x");
- goto error;
- }
- if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
- goto error;
- }
- minorCmd = Tcl_GetString(objv[2]);
- if (minorCmd[0] == 'm'
- && (strncmp(minorCmd, "mark", strlen(minorCmd)) == 0)) {
- entryPtr->scanMarkX = x;
- entryPtr->scanMarkIndex = entryPtr->leftIndex;
- } else if ((minorCmd[0] == 'd')
- && (strncmp(minorCmd, "dragto", strlen(minorCmd)) == 0)) {
- EntryScanTo(entryPtr, x);
- } else {
- Tcl_AppendResult(interp, "bad scan option "",
- Tcl_GetString(objv[2]), "": must be mark or dragto",
- (char *) NULL);
- goto error;
- }
- break;
- }
-
- case COMMAND_SELECTION: {
- int index, index2;
- if (objc < 3) {
- Tcl_WrongNumArgs(interp, 2, objv, "option ?index?");
- goto error;
- }
-
- /*
- * Parse the selection sub-command, using the command
- * table "selCmdNames" defined above.
- */
-
- result = Tcl_GetIndexFromObj(interp, objv[2], selCmdNames,
- "selection option", 0, &selIndex);
- if (result != TCL_OK) {
- goto error;
- }
- /*
- * Disabled entries don't allow the selection to be modified,
- * but 'selection present' must return a boolean.
- */
- if ((entryPtr->state == STATE_DISABLED)
- && (selIndex != SELECTION_PRESENT)) {
- goto done;
- }
- switch (selIndex) {
- case SELECTION_ADJUST: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "index");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr,
- Tcl_GetString(objv[3]), &index) != TCL_OK) {
- goto error;
- }
- if (entryPtr->selectFirst >= 0) {
- int half1, half2;
-
- half1 = (entryPtr->selectFirst
- + entryPtr->selectLast)/2;
- half2 = (entryPtr->selectFirst
- + entryPtr->selectLast + 1)/2;
- if (index < half1) {
- entryPtr->selectAnchor = entryPtr->selectLast;
- } else if (index > half2) {
- entryPtr->selectAnchor = entryPtr->selectFirst;
- } else {
- /*
- * We're at about the halfway point in the
- * selection; just keep the existing anchor.
- */
- }
- }
- EntrySelectTo(entryPtr, index);
- break;
- }
- case SELECTION_CLEAR: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL);
- goto error;
- }
- if (entryPtr->selectFirst >= 0) {
- entryPtr->selectFirst = -1;
- entryPtr->selectLast = -1;
- EventuallyRedraw(entryPtr);
- }
- goto done;
- }
- case SELECTION_FROM: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "index");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr,
- Tcl_GetString(objv[3]), &index) != TCL_OK) {
- goto error;
- }
- entryPtr->selectAnchor = index;
- break;
- }
- case SELECTION_PRESENT: {
- if (objc != 3) {
- Tcl_WrongNumArgs(interp, 3, objv, (char *) NULL);
- goto error;
- }
- Tcl_SetObjResult(interp,
- Tcl_NewBooleanObj((entryPtr->selectFirst >= 0)));
- goto done;
- }
- case SELECTION_RANGE: {
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 3, objv, "start end");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr,
- Tcl_GetString(objv[3]), &index) != TCL_OK) {
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr,
- Tcl_GetString(objv[4]),& index2) != TCL_OK) {
- goto error;
- }
- if (index >= index2) {
- entryPtr->selectFirst = -1;
- entryPtr->selectLast = -1;
- } else {
- entryPtr->selectFirst = index;
- entryPtr->selectLast = index2;
- }
- if (!(entryPtr->flags & GOT_SELECTION)
- && (entryPtr->exportSelection)) {
- Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY,
- EntryLostSelection, (ClientData) entryPtr);
- entryPtr->flags |= GOT_SELECTION;
- }
- EventuallyRedraw(entryPtr);
- break;
- }
-
- case SELECTION_TO: {
- if (objc != 4) {
- Tcl_WrongNumArgs(interp, 3, objv, "index");
- goto error;
- }
- if (GetEntryIndex(interp, entryPtr,
- Tcl_GetString(objv[3]), &index) != TCL_OK) {
- goto error;
- }
- EntrySelectTo(entryPtr, index);
- break;
- }
- }
- break;
- }
- case COMMAND_VALIDATE: {
- int code;
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);
- goto error;
- }
- selIndex = entryPtr->validate;
- entryPtr->validate = VALIDATE_ALL;
- code = EntryValidateChange(entryPtr, (char *) NULL,
- entryPtr->string, -1, VALIDATE_FORCED);
- if (entryPtr->validate != VALIDATE_NONE) {
- entryPtr->validate = selIndex;
- }
- Tcl_SetObjResult(interp, Tcl_NewBooleanObj((code == TCL_OK)));
- break;
- }
- case COMMAND_XVIEW: {
- int index;
- if (objc == 2) {
- double first, last;
- char buf[TCL_DOUBLE_SPACE * 2];
-
- EntryVisibleRange(entryPtr, &first, &last);
- sprintf(buf, "%g %g", first, last);
- Tcl_SetResult(interp, buf, TCL_VOLATILE);
- goto done;
- } else if (objc == 3) {
- if (GetEntryIndex(interp, entryPtr, Tcl_GetString(objv[2]),
- &index) != TCL_OK) {
- goto error;
- }
- } else {
- double fraction;
- int count;
- index = entryPtr->leftIndex;
- switch (Tk_GetScrollInfoObj(interp, objc, objv, &fraction,
- &count)) {
- case TK_SCROLL_ERROR: {
- goto error;
- }
- case TK_SCROLL_MOVETO: {
- index = (int) ((fraction * entryPtr->numChars) + 0.5);
- break;
- }
- case TK_SCROLL_PAGES: {
- int charsPerPage;
-
- charsPerPage = ((Tk_Width(entryPtr->tkwin)
- - 2 * entryPtr->inset)
- / entryPtr->avgWidth) - 2;
- if (charsPerPage < 1) {
- charsPerPage = 1;
- }
- index += count * charsPerPage;
- break;
- }
- case TK_SCROLL_UNITS: {
- index += count;
- break;
- }
- }
- }
- if (index >= entryPtr->numChars) {
- index = entryPtr->numChars - 1;
- }
- if (index < 0) {
- index = 0;
- }
- entryPtr->leftIndex = index;
- entryPtr->flags |= UPDATE_SCROLLBAR;
- EntryComputeGeometry(entryPtr);
- EventuallyRedraw(entryPtr);
- break;
- }
- }
- done:
- Tcl_Release((ClientData) entryPtr);
- return result;
- error:
- Tcl_Release((ClientData) entryPtr);
- return TCL_ERROR;
- }
- /*
- *----------------------------------------------------------------------
- *
- * DestroyEntry --
- *
- * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
- * to clean up the internal structure of an entry at a safe time
- * (when no-one is using it anymore).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Everything associated with the entry is freed up.
- *
- *----------------------------------------------------------------------
- */
- static void
- DestroyEntry(memPtr)
- char *memPtr; /* Info about entry widget. */
- {
- Entry *entryPtr = (Entry *) memPtr;
- /*
- * Free up all the stuff that requires special handling, then
- * let Tk_FreeOptions handle all the standard option-related
- * stuff.
- */
- ckfree((char *)entryPtr->string);
- if (entryPtr->textVarName != NULL) {
- Tcl_UntraceVar(entryPtr->interp, entryPtr->textVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- EntryTextVarProc, (ClientData) entryPtr);
- entryPtr->flags &= ~ENTRY_VAR_TRACED;
- }
- if (entryPtr->textGC != None) {
- Tk_FreeGC(entryPtr->display, entryPtr->textGC);
- }
- if (entryPtr->selTextGC != None) {
- Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
- }
- Tcl_DeleteTimerHandler(entryPtr->insertBlinkHandler);
- if (entryPtr->displayString != entryPtr->string) {
- ckfree((char *)entryPtr->displayString);
- }
- if (entryPtr->type == TK_SPINBOX) {
- Spinbox *sbPtr = (Spinbox *) entryPtr;
- if (sbPtr->listObj != NULL) {
- Tcl_DecrRefCount(sbPtr->listObj);
- sbPtr->listObj = NULL;
- }
- if (sbPtr->formatBuf) {
- ckfree(sbPtr->formatBuf);
- }
- }
- Tk_FreeTextLayout(entryPtr->textLayout);
- Tk_FreeConfigOptions((char *) entryPtr, entryPtr->optionTable,
- entryPtr->tkwin);
- Tcl_Release((ClientData) entryPtr->tkwin);
- entryPtr->tkwin = NULL;
- ckfree((char *) entryPtr);
- }
- /*
- *----------------------------------------------------------------------
- *
- * ConfigureEntry --
- *
- * This procedure is called to process an argv/argc list, plus
- * the Tk option database, in order to configure (or reconfigure)
- * an entry widget.
- *
- * Results:
- * The return value is a standard Tcl result. If TCL_ERROR is
- * returned, then the interp's result contains an error message.
- *
- * Side effects:
- * Configuration information, such as colors, border width,
- * etc. get set for entryPtr; old resources get freed,
- * if there were any.
- *
- *----------------------------------------------------------------------
- */
- static int
- ConfigureEntry(interp, entryPtr, objc, objv, flags)
- Tcl_Interp *interp; /* Used for error reporting. */
- Entry *entryPtr; /* Information about widget; may or may not
- * already have values for some fields. */
- int objc; /* Number of valid entries in argv. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- int flags; /* Flags to pass to Tk_ConfigureWidget. */
- {
- Tk_SavedOptions savedOptions;
- Tk_3DBorder border;
- Tcl_Obj *errorResult = NULL;
- Spinbox *sbPtr = (Spinbox *) entryPtr; /* Only used when this widget
- * is of type TK_SPINBOX */
- char *oldValues = NULL; /* lint initialization */
- char *oldFormat = NULL; /* lint initialization */
- int error;
- int oldExport = 0; /* lint initialization */
- int valuesChanged = 0; /* lint initialization */
- double oldFrom = 0.0; /* lint initialization */
- double oldTo = 0.0; /* lint initialization */
- /*
- * Eliminate any existing trace on a variable monitored by the entry.
- */
- if ((entryPtr->textVarName != NULL)
- && (entryPtr->flags & ENTRY_VAR_TRACED)) {
- Tcl_UntraceVar(interp, entryPtr->textVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- EntryTextVarProc, (ClientData) entryPtr);
- entryPtr->flags &= ~ENTRY_VAR_TRACED;
- }
- /*
- * Store old values that we need to effect certain behavior if
- * they change value
- */
- oldExport = entryPtr->exportSelection;
- if (entryPtr->type == TK_SPINBOX) {
- oldValues = sbPtr->valueStr;
- oldFormat = sbPtr->reqFormat;
- oldFrom = sbPtr->fromValue;
- oldTo = sbPtr->toValue;
- }
- for (error = 0; error <= 1; error++) {
- if (!error) {
- /*
- * First pass: set options to new values.
- */
- if (Tk_SetOptions(interp, (char *) entryPtr,
- entryPtr->optionTable, objc, objv,
- entryPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
- continue;
- }
- } else {
- /*
- * Second pass: restore options to old values.
- */
- errorResult = Tcl_GetObjResult(interp);
- Tcl_IncrRefCount(errorResult);
- Tk_RestoreSavedOptions(&savedOptions);
- }
- /*
- * A few other options also need special processing, such as parsing
- * the geometry and setting the background from a 3-D border.
- */
- if ((entryPtr->state == STATE_DISABLED) &&
- (entryPtr->disabledBorder != NULL)) {
- border = entryPtr->disabledBorder;
- } else if ((entryPtr->state == STATE_READONLY) &&
- (entryPtr->readonlyBorder != NULL)) {
- border = entryPtr->readonlyBorder;
- } else {
- border = entryPtr->normalBorder;
- }
- Tk_SetBackgroundFromBorder(entryPtr->tkwin, border);
- if (entryPtr->insertWidth <= 0) {
- entryPtr->insertWidth = 2;
- }
- if (entryPtr->insertBorderWidth > entryPtr->insertWidth/2) {
- entryPtr->insertBorderWidth = entryPtr->insertWidth/2;
- }
- if (entryPtr->type == TK_SPINBOX) {
- if (sbPtr->fromValue > sbPtr->toValue) {
- Tcl_SetResult(interp,
- "-to value must be greater than -from value",
- TCL_VOLATILE);
- continue;
- }
- if (sbPtr->reqFormat && (oldFormat != sbPtr->reqFormat)) {
- /*
- * Make sure that the given format is somewhat correct, and
- * calculate the minimum space we'll need for the values as
- * strings.
- */
- int min, max;
- size_t formatLen, formatSpace = TCL_DOUBLE_SPACE;
- char fbuf[4], *fmt = sbPtr->reqFormat;
- formatLen = strlen(fmt);
- if ((fmt[0] != '%') || (fmt[formatLen-1] != 'f')) {
- badFormatOpt:
- Tcl_AppendResult(interp, "bad spinbox format specifier "",
- sbPtr->reqFormat, """, (char *) NULL);
- continue;
- }
- if ((sscanf(fmt, "%%%d.%d%[f]", &min, &max, fbuf) == 3)
- && (max >= 0)) {
- formatSpace = min + max + 1;
- } else if (((sscanf(fmt, "%%.%d%[f]", &min, fbuf) == 2)
- || (sscanf(fmt, "%%%d%[f]", &min, fbuf) == 2)
- || (sscanf(fmt, "%%%d.%[f]", &min, fbuf) == 2))
- && (min >= 0)) {
- formatSpace = min + 1;
- } else {
- goto badFormatOpt;
- }
- if (formatSpace < TCL_DOUBLE_SPACE) {
- formatSpace = TCL_DOUBLE_SPACE;
- }
- sbPtr->formatBuf = ckrealloc(sbPtr->formatBuf, formatSpace);
- /*
- * We perturb the value of oldFrom to allow us to go into
- * the branch below that will reformat the displayed value.
- */
- oldFrom = sbPtr->fromValue - 1;
- }
- /*
- * See if we have to rearrange our listObj data
- */
- if (oldValues != sbPtr->valueStr) {
- if (sbPtr->listObj != NULL) {
- Tcl_DecrRefCount(sbPtr->listObj);
- }
- sbPtr->listObj = NULL;
- if (sbPtr->valueStr != NULL) {
- Tcl_Obj *newObjPtr;
- int nelems;
- newObjPtr = Tcl_NewStringObj(sbPtr->valueStr, -1);
- if (Tcl_ListObjLength(interp, newObjPtr, &nelems)
- != TCL_OK) {
- valuesChanged = -1;
- continue;
- }
- sbPtr->listObj = newObjPtr;
- Tcl_IncrRefCount(sbPtr->listObj);
- sbPtr->nElements = nelems;
- sbPtr->eIndex = 0;
- valuesChanged++;
- }
- }
- }
- /*
- * Restart the cursor timing sequence in case the on-time or
- * off-time just changed. Set validate temporarily to none,
- * so the configure doesn't cause it to be triggered.
- */
- if (entryPtr->flags & GOT_FOCUS) {
- int validate = entryPtr->validate;
- entryPtr->validate = VALIDATE_NONE;
- EntryFocusProc(entryPtr, 1);
- entryPtr->validate = validate;
- }
- /*
- * Claim the selection if we've suddenly started exporting it.
- */
- if (entryPtr->exportSelection && (!oldExport)
- && (entryPtr->selectFirst != -1)
- && !(entryPtr->flags & GOT_SELECTION)) {
- Tk_OwnSelection(entryPtr->tkwin, XA_PRIMARY, EntryLostSelection,
- (ClientData) entryPtr);
- entryPtr->flags |= GOT_SELECTION;
- }
- /*
- * Recompute the window's geometry and arrange for it to be
- * redisplayed.
- */
- Tk_SetInternalBorder(entryPtr->tkwin,
- entryPtr->borderWidth + entryPtr->highlightWidth);
- if (entryPtr->highlightWidth <= 0) {
- entryPtr->highlightWidth = 0;
- }
- entryPtr->inset = entryPtr->highlightWidth
- + entryPtr->borderWidth + XPAD;
- break;
- }
- if (!error) {
- Tk_FreeSavedOptions(&savedOptions);
- }
- /*
- * If the entry is tied to the value of a variable, create the variable if
- * it doesn't exist, and set the entry's value from the variable's value.
- */
- if (entryPtr->textVarName != NULL) {
- CONST char *value;
- value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY);
- if (value == NULL) {
- EntryValueChanged(entryPtr, NULL);
- } else {
- EntrySetValue(entryPtr, value);
- }
- }
- if (entryPtr->type == TK_SPINBOX) {
- ComputeFormat(sbPtr);
- if (valuesChanged > 0) {
- Tcl_Obj *objPtr;
- /*
- * No check for error return, because there shouldn't be one
- * given the check for valid list above
- */
- Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);
- EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
- } else if ((sbPtr->valueStr == NULL)
- && !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)
- && (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)
- || !DOUBLES_EQ(sbPtr->toValue, oldTo))) {
- /*
- * If the valueStr is empty and -from && -to are specified, check
- * to see if the current string is within the range. If not,
- * it will be constrained to the nearest edge. If the current
- * string isn't a double value, we set it to -from.
- */
- int code;
- double dvalue;
- code = Tcl_GetDouble(NULL, entryPtr->string, &dvalue);
- if (code != TCL_OK) {
- dvalue = sbPtr->fromValue;
- } else {
- if (dvalue > sbPtr->toValue) {
- dvalue = sbPtr->toValue;
- } else if (dvalue < sbPtr->fromValue) {
- dvalue = sbPtr->fromValue;
- }
- }
- sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
- EntryValueChanged(entryPtr, sbPtr->formatBuf);
- }
- }
- /*
- * Set up a trace on the variable's value after we've possibly
- * constrained the value according to new -from/-to values.
- */
- if ((entryPtr->textVarName != NULL)
- && !(entryPtr->flags & ENTRY_VAR_TRACED)) {
- Tcl_TraceVar(interp, entryPtr->textVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- EntryTextVarProc, (ClientData) entryPtr);
- entryPtr->flags |= ENTRY_VAR_TRACED;
- }
- EntryWorldChanged((ClientData) entryPtr);
- if (error) {
- Tcl_SetObjResult(interp, errorResult);
- Tcl_DecrRefCount(errorResult);
- return TCL_ERROR;
- } else {
- return TCL_OK;
- }
- }
- /*
- *---------------------------------------------------------------------------
- *
- * EntryWorldChanged --
- *
- * This procedure is called when the world has changed in some
- * way and the widget needs to recompute all its graphics contexts
- * and determine its new geometry.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Entry will be relayed out and redisplayed.
- *
- *---------------------------------------------------------------------------
- */
-
- static void
- EntryWorldChanged(instanceData)
- ClientData instanceData; /* Information about widget. */
- {
- XGCValues gcValues;
- GC gc = None;
- unsigned long mask;
- Tk_3DBorder border;
- XColor *colorPtr;
- Entry *entryPtr = (Entry *) instanceData;
- entryPtr->avgWidth = Tk_TextWidth(entryPtr->tkfont, "0", 1);
- if (entryPtr->avgWidth == 0) {
- entryPtr->avgWidth = 1;
- }
- if (entryPtr->type == TK_SPINBOX) {
- /*
- * Compute the button width for a spinbox
- */
- entryPtr->xWidth = entryPtr->avgWidth + 2 * (1+XPAD);
- if (entryPtr->xWidth < 11) {
- entryPtr->xWidth = 11; /* we want a min visible size */
- }
- }
- /*
- * Default background and foreground are from the normal state.
- * In a disabled state, both of those may be overridden; in the readonly
- * state, the background may be overridden.
- */
- border = entryPtr->normalBorder;
- colorPtr = entryPtr->fgColorPtr;
- switch (entryPtr->state) {
- case STATE_DISABLED:
- if (entryPtr->disabledBorder != NULL) {
- border = entryPtr->disabledBorder;
- }
- if (entryPtr->dfgColorPtr != NULL) {
- colorPtr = entryPtr->dfgColorPtr;
- }
- break;
- case STATE_READONLY:
- if (entryPtr->readonlyBorder != NULL) {
- border = entryPtr->readonlyBorder;
- }
- break;
- }
- Tk_SetBackgroundFromBorder(entryPtr->tkwin, border);
- gcValues.foreground = colorPtr->pixel;
- gcValues.font = Tk_FontId(entryPtr->tkfont);
- gcValues.graphics_exposures = False;
- mask = GCForeground | GCFont | GCGraphicsExposures;
- gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
- if (entryPtr->textGC != None) {
- Tk_FreeGC(entryPtr->display, entryPtr->textGC);
- }
- entryPtr->textGC = gc;
- if (entryPtr->selFgColorPtr != NULL) {
- gcValues.foreground = entryPtr->selFgColorPtr->pixel;
- }
- gcValues.font = Tk_FontId(entryPtr->tkfont);
- mask = GCForeground | GCFont;
- gc = Tk_GetGC(entryPtr->tkwin, mask, &gcValues);
- if (entryPtr->selTextGC != None) {
- Tk_FreeGC(entryPtr->display, entryPtr->selTextGC);
- }
- entryPtr->selTextGC = gc;
- /*
- * Recompute the window's geometry and arrange for it to be
- * redisplayed.
- */
- EntryComputeGeometry(entryPtr);
- entryPtr->flags |= UPDATE_SCROLLBAR;
- EventuallyRedraw(entryPtr);
- }
- #ifndef MAC_OSX_TK
- /*
- *--------------------------------------------------------------
- *
- * TkpDrawEntryBorderAndFocus --
- *
- * This procedure redraws the border of an entry widget.
- * It overrides the generic border drawing code if the
- * entry widget parameters are such that the native widget
- * drawing is a good fit.
- * This version just returns o, so platforms that don't
- * do special native drawing don't have to implement it.
- *
- * Results:
- * 1 if it has drawn the border, 0 if not.
- *
- * Side effects:
- * May draw the entry border into pixmap.
- *
- *--------------------------------------------------------------
- */
- int
- TkpDrawEntryBorderAndFocus(entryPtr, pixmap, isSpinbox)
- Entry *entryPtr;
- Drawable pixmap;
- int isSpinbox;
- {
- return 0;
- }
- /*
- *--------------------------------------------------------------
- *
- * TkpDrawSpinboxButtons --
- *
- * This procedure redraws the buttons of an spinbox widget.
- * It overrides the generic button drawing code if the
- * spinbox widget parameters are such that the native widget
- * drawing is a good fit.
- * This version just returns 0, so platforms that don't
- * do special native drawing don't have to implement it.
- *
- * Results:
- * 1 if it has drawn the border, 0 if not.
- *
- * Side effects:
- * May draw the entry border into pixmap.
- *
- *--------------------------------------------------------------
- */
- int
- TkpDrawSpinboxButtons(sbPtr, pixmap)
- Spinbox *sbPtr;
- Pixmap pixmap;
- {
- return 0;
- }
- #endif /* Not MAC_OSX_TK */
- /*
- *--------------------------------------------------------------
- *
- * DisplayEntry --
- *
- * This procedure redraws the contents of an entry window.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Information appears on the screen.
- *
- *--------------------------------------------------------------
- */
- static void
- DisplayEntry(clientData)
- ClientData clientData; /* Information about window. */
- {
- Entry *entryPtr = (Entry *) clientData;
- Tk_Window tkwin = entryPtr->tkwin;
- int baseY, selStartX, selEndX, cursorX;
- int showSelection, xBound;
- Tk_FontMetrics fm;
- Pixmap pixmap;
- Tk_3DBorder border;
- entryPtr->flags &= ~REDRAW_PENDING;
- if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {
- return;
- }
- Tk_GetFontMetrics(entryPtr->tkfont, &fm);
- /*
- * Update the scrollbar if that's needed.
- */
- if (entryPtr->flags & UPDATE_SCROLLBAR) {
- entryPtr->flags &= ~UPDATE_SCROLLBAR;
- /*
- * Preserve/Release because updating the scrollbar can have
- * the side-effect of destroying or unmapping the entry widget.
- */
- Tcl_Preserve((ClientData) entryPtr);
- EntryUpdateScrollbar(entryPtr);
- if ((entryPtr->flags & ENTRY_DELETED) || !Tk_IsMapped(tkwin)) {
- Tcl_Release((ClientData) entryPtr);
- return;
- }
- Tcl_Release((ClientData) entryPtr);
- }
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * In order to avoid screen flashes, this procedure redraws the
- * textual area of the entry into off-screen memory, then copies
- * it back on-screen in a single operation. This means there's
- * no point in time where the on-screen image has been cleared.
- */
- pixmap = Tk_GetPixmap(entryPtr->display, Tk_WindowId(tkwin),
- Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
- #else
- pixmap = Tk_WindowId(tkwin);
- #endif /* TK_NO_DOUBLE_BUFFERING */
- /*
- * Compute x-coordinate of the pixel just after last visible
- * one, plus vertical position of baseline of text.
- */
- xBound = Tk_Width(tkwin) - entryPtr->inset - entryPtr->xWidth;
- baseY = (Tk_Height(tkwin) + fm.ascent - fm.descent) / 2;
- /*
- * On Windows and Mac, we need to hide the selection whenever we
- * don't have the focus.
- */
- if (TkpAlwaysShowSelection(entryPtr->tkwin)) {
- showSelection = 1;
- } else {
- showSelection = (entryPtr->flags & GOT_FOCUS);
- }
- /*
- * Draw the background in three layers. From bottom to top the
- * layers are: normal background, selection background, and
- * insertion cursor background.
- */
- if ((entryPtr->state == STATE_DISABLED) &&
- (entryPtr->disabledBorder != NULL)) {
- border = entryPtr->disabledBorder;
- } else if ((entryPtr->state == STATE_READONLY) &&
- (entryPtr->readonlyBorder != NULL)) {
- border = entryPtr->readonlyBorder;
- } else {
- border = entryPtr->normalBorder;
- }
- Tk_Fill3DRectangle(tkwin, pixmap, border,
- 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
- if (showSelection && (entryPtr->state != STATE_DISABLED)
- && (entryPtr->selectLast > entryPtr->leftIndex)) {
- if (entryPtr->selectFirst <= entryPtr->leftIndex) {
- selStartX = entryPtr->leftX;
- } else {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->selectFirst,
- &selStartX, NULL, NULL, NULL);
- selStartX += entryPtr->layoutX;
- }
- if ((selStartX - entryPtr->selBorderWidth) < xBound) {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->selectLast,
- &selEndX, NULL, NULL, NULL);
- selEndX += entryPtr->layoutX;
- Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->selBorder,
- selStartX - entryPtr->selBorderWidth,
- baseY - fm.ascent - entryPtr->selBorderWidth,
- (selEndX - selStartX) + 2*entryPtr->selBorderWidth,
- (fm.ascent + fm.descent) + 2*entryPtr->selBorderWidth,
- entryPtr->selBorderWidth,
- #ifndef MAC_OSX_TK
- TK_RELIEF_RAISED
- #else
- MAC_OSX_ENTRY_SELECT_RELIEF
- #endif
- );
- }
- }
- /*
- * Draw a special background for the insertion cursor, overriding
- * even the selection background. As a special hack to keep the
- * cursor visible when the insertion cursor color is the same as
- * the color for selected text (e.g., on mono displays), write
- * background in the cursor area (instead of nothing) when the
- * cursor isn't on. Otherwise the selection would hide the cursor.
- */
- if ((entryPtr->state == STATE_NORMAL) && (entryPtr->flags & GOT_FOCUS)) {
- Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,
- NULL, NULL);
- cursorX += entryPtr->layoutX;
- cursorX -= (entryPtr->insertWidth)/2;
- Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,
- fm.ascent + fm.descent);
- if (entryPtr->insertPos >= entryPtr->leftIndex) {
- if (cursorX < xBound) {
- if (entryPtr->flags & CURSOR_ON) {
- Tk_Fill3DRectangle(tkwin, pixmap, entryPtr->insertBorder,
- cursorX, baseY - fm.ascent, entryPtr->insertWidth,
- fm.ascent + fm.descent,
- entryPtr->insertBorderWidth,
- TK_RELIEF_RAISED);
- } else if (entryPtr->insertBorder == entryPtr->selBorder) {
- Tk_Fill3DRectangle(tkwin, pixmap, border,
- cursorX, baseY - fm.ascent, entryPtr->insertWidth,
- fm.ascent + fm.descent, 0, TK_RELIEF_FLAT);
- }
- }
- }
- }
- /*
- * Draw the text in two pieces: first the unselected portion, then the
- * selected portion on top of it.
- */
- Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->textGC,
- entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
- entryPtr->leftIndex, entryPtr->numChars);
- if (showSelection && (entryPtr->state != STATE_DISABLED)
- && (entryPtr->selTextGC != entryPtr->textGC)
- && (entryPtr->selectFirst < entryPtr->selectLast)) {
- int selFirst;
- if (entryPtr->selectFirst < entryPtr->leftIndex) {
- selFirst = entryPtr->leftIndex;
- } else {
- selFirst = entryPtr->selectFirst;
- }
- Tk_DrawTextLayout(entryPtr->display, pixmap, entryPtr->selTextGC,
- entryPtr->textLayout, entryPtr->layoutX, entryPtr->layoutY,
- selFirst, entryPtr->selectLast);
- }
- if (entryPtr->type == TK_SPINBOX) {
- int startx, height, inset, pad, tHeight, xWidth;
- Spinbox *sbPtr = (Spinbox *) entryPtr;
- /*
- * Draw the spin button controls.
- */
- if (TkpDrawSpinboxButtons(sbPtr, pixmap) == 0) {
- xWidth = entryPtr->xWidth;
- pad = XPAD + 1;
- inset = entryPtr->inset - XPAD;
- startx = Tk_Width(tkwin) - (xWidth + inset);
- height = (Tk_Height(tkwin) - 2*inset)/2;
- #if 0
- Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
- startx, inset, xWidth, height, 1, sbPtr->buRelief);
- Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
- startx, inset+height, xWidth, height, 1, sbPtr->bdRelief);
- #else
- Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
- startx, inset, xWidth, height, 1,
- (sbPtr->selElement == SEL_BUTTONUP) ?
- TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
- Tk_Fill3DRectangle(tkwin, pixmap, sbPtr->buttonBorder,
- startx, inset+height, xWidth, height, 1,
- (sbPtr->selElement == SEL_BUTTONDOWN) ?
- TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
- #endif
-
- xWidth -= 2*pad;
- /*
- * Only draw the triangles if we have enough display space
- */
- if ((xWidth > 1)) {
- XPoint points[3];
- int starty, space, offset;
- space = height - 2*pad;
- /*
- * Ensure width of triangle is odd to guarantee a sharp tip
- */
- if (!(xWidth % 2)) {
- xWidth++;
- }
- tHeight = (xWidth + 1) / 2;
- if (tHeight > space) {
- tHeight = space;
- }
- space = (space - tHeight) / 2;
- startx += pad;
- starty = inset + height - pad - space;
- offset = (sbPtr->selElement == SEL_BUTTONUP);
- /*
- * The points are slightly different for the up and down arrows
- * because (for *.x), we need to account for a bug in the way
- * XFillPolygon draws triangles, and we want to shift
- * the arrows differently when allowing for depressed behavior.
- */
- points[0].x = startx + offset;
- points[0].y = starty + (offset ? 0 : -1);
- points[1].x = startx + xWidth/2 + offset;
- points[1].y = starty - tHeight + (offset ? 0 : -1);
- points[2].x = startx + xWidth + offset;
- points[2].y = points[0].y;
- XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,
- points, 3, Convex, CoordModeOrigin);
- starty = inset + height + pad + space;
- offset = (sbPtr->selElement == SEL_BUTTONDOWN);
- points[0].x = startx + 1 + offset;
- points[0].y = starty + (offset ? 1 : 0);
- points[1].x = startx + xWidth/2 + offset;
- points[1].y = starty + tHeight + (offset ? 0 : -1);
- points[2].x = startx - 1 + xWidth + offset;
- points[2].y = points[0].y;
- XFillPolygon(entryPtr->display, pixmap, entryPtr->textGC,
- points, 3, Convex, CoordModeOrigin);
- }
- }
- }
- /*
- * Draw the border and focus highlight last, so they will overwrite
- * any text that extends past the viewable part of the window.
- */
- if (!TkpDrawEntryBorderAndFocus(entryPtr, pixmap,
- (entryPtr->type == TK_SPINBOX))) {
- xBound = entryPtr->highlightWidth;
- if (entryPtr->relief != TK_RELIEF_FLAT) {
- Tk_Draw3DRectangle(tkwin, pixmap, border, xBound, xBound,
- Tk_Width(tkwin) - 2 * xBound,
- Tk_Height(tkwin) - 2 * xBound,
- entryPtr->borderWidth, entryPtr->relief);
- }
- if (xBound > 0) {
- GC fgGC, bgGC;
- bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, pixmap);
- if (entryPtr->flags & GOT_FOCUS) {
- fgGC = Tk_GCForColor(entryPtr->highlightColorPtr, pixmap);
- TkpDrawHighlightBorder(tkwin, fgGC, bgGC, xBound, pixmap);
- } else {
- TkpDrawHighlightBorder(tkwin, bgGC, bgGC, xBound, pixmap);
- }
- }
- }
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * Everything's been redisplayed; now copy the pixmap onto the screen
- * and free up the pixmap.
- */
- XCopyArea(entryPtr->display, pixmap, Tk_WindowId(tkwin), entryPtr->textGC,
- 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin),
- 0, 0);
- Tk_FreePixmap(entryPtr->display, pixmap);
- #endif /* TK_NO_DOUBLE_BUFFERING */
- entryPtr->flags &= ~BORDER_NEEDED;
- }
- /*
- *----------------------------------------------------------------------
- *
- * EntryComputeGeometry --
- *
- * This procedure is invoked to recompute information about where
- * in its window an entry's string will be displayed. It also
- * computes the requested size for the window.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The leftX and tabOrigin fields are recomputed for entryPtr,
- * and leftIndex may be adjusted. Tk_GeometryRequest is called
- * to register the desired dimensions for the window.
- *
- *----------------------------------------------------------------------
- */
- static void
- EntryComputeGeometry(entryPtr)
- Entry *entryPtr; /* Widget record for entry. */
- {
- int totalLength, overflow, maxOffScreen, rightX;
- int height, width, i;
- Tk_FontMetrics fm;
- char *p;
- if (entryPtr->displayString != entryPtr->string) {
- ckfree((char *)entryPtr->displayString);
- entryPtr->displayString = entryPtr->string;
- entryPtr->numDisplayBytes = entryPtr->numBytes;
- }
- /*
- * If we're displaying a special character instead of the value of
- * the entry, recompute the displayString.
- */
- if (entryPtr->showChar != NULL) {
- Tcl_UniChar ch;
- char buf[TCL_UTF_MAX];
- int size;
- /*
- * Normalize the special character so we can safely duplicate it
- * in the display string. If we didn't do this, then two malformed
- * characters might end up looking like one valid UTF character in
- * the resulting string.
- */
- Tcl_UtfToUniChar(entryPtr->showChar, &ch);
- size = Tcl_UniCharToUtf(ch, buf);
- entryPtr->numDisplayBytes = entryPtr->numChars * size;
- p = (char *) ckalloc((unsigned) (entryPtr->numDisplayBytes + 1));
- entryPtr->displayString = p;
- for (i = entryPtr->numChars; --i >= 0; ) {
- p += Tcl_UniCharToUtf(ch, p);
- }
- *p = ' ';
- }
- Tk_FreeTextLayout(entryPtr->textLayout);
- entryPtr->textLayout = Tk_ComputeTextLayout(entryPtr->tkfont,
- entryPtr->displayString, entryPtr->numChars, 0,
- entryPtr->justify, TK_IGNORE_NEWLINES, &totalLength, &height);
- entryPtr->layoutY = (Tk_Height(entryPtr->tkwin) - height) / 2;
- /*
- * Recompute where the leftmost character on the display will
- * be drawn (entryPtr->leftX) and adjust leftIndex if necessary
- * so that we don't let characters hang off the edge of the
- * window unless the entire window is full.
- */
- overflow = totalLength -
- (Tk_Width(entryPtr->tkwin) - 2*entryPtr->inset - entryPtr->xWidth);
- if (overflow <= 0) {
- entryPtr->leftIndex = 0;
- if (entryPtr->justify == TK_JUSTIFY_LEFT) {
- entryPtr->leftX = entryPtr->inset;
- } else if (entryPtr->justify == TK_JUSTIFY_RIGHT) {
- entryPtr->leftX = Tk_Width(entryPtr->tkwin) - entryPtr->inset
- - entryPtr->xWidth - totalLength;
- } else {
- entryPtr->leftX = (Tk_Width(entryPtr->tkwin)
- - entryPtr->xWidth - totalLength)/2;
- }
- entryPtr->layoutX = entryPtr->leftX;
- } else {
- /*
- * The whole string can't fit in the window. Compute the
- * maximum number of characters that may be off-screen to
- * the left without leaving empty space on the right of the
- * window, then don't let leftIndex be any greater than that.
- */
- maxOffScreen = Tk_PointToChar(entryPtr->textLayout, overflow, 0);
- Tk_CharBbox(entryPtr->textLayout, maxOffScreen,
- &rightX, NULL, NULL, NULL);
- if (rightX < overflow) {
- maxOffScreen++;
- }
- if (entryPtr->leftIndex > maxOffScreen) {
- entryPtr->leftIndex = maxOffScreen;
- }
- Tk_CharBbox(entryPtr->textLayout, entryPtr->leftIndex, &rightX,
- NULL, NULL, NULL);
- entryPtr->leftX = entryPtr->inset;
- entryPtr->layoutX = entryPtr->leftX - rightX;
- }
- Tk_GetFontMetrics(entryPtr->tkfont, &fm);
- height = fm.linespace + 2*entryPtr->inset + 2*(YPAD-XPAD);
- if (entryPtr->prefWidth > 0) {
- width = entryPtr->prefWidth*entryPtr->avgWidth + 2*entryPtr->inset;
- } else {
- if (totalLength == 0) {
- width = entryPtr->avgWidth + 2*entryPtr->inset;
- } else {
- width = totalLength + 2*entryPtr->inset;
- }
- }
- /*
- * Add one extra length for the spin buttons
- */
- width += entryPtr->xWidth;
- Tk_GeometryRequest(entryPtr->tkwin, width, height);
- }
- /*
- *----------------------------------------------------------------------
- *
- * InsertChars --
- *
- * Add new characters to an entry widget.
- *
- * Results:
- * None.
- *
- * Side effects:
- * New information gets added to entryPtr; it will be redisplayed
- * soon, but not necessarily immediately.
- *
- *----------------------------------------------------------------------
- */
- static void
- InsertChars(entryPtr, index, value)
- Entry *entryPtr; /* Entry that is to get the new elements. */
- int index; /* Add the new elements before this
- * character index. */
- char *value; /* New characters to add (NULL-terminated
- * string). */
- {
- int byteIndex, byteCount, oldChars, charsAdded, newByteCount;
- CONST char *string;
- char *new;
- string = entryPtr->string;
- byteIndex = Tcl_UtfAtIndex(string, index) - string;
- byteCount = strlen(value);
- if (byteCount == 0) {
- return;
- }
- newByteCount = entryPtr->numBytes + byteCount + 1;
- new = (char *) ckalloc((unsigned) newByteCount);
- memcpy(new, string, (size_t) byteIndex);
- strcpy(new + byteIndex, value);
- strcpy(new + byteIndex + byteCount, string + byteIndex);
- if ((entryPtr->validate == VALIDATE_KEY ||
- entryPtr->validate == VALIDATE_ALL) &&
- EntryValidateChange(entryPtr, value, new, index,
- VALIDATE_INSERT) != TCL_OK) {
- ckfree(new);
- return;
- }
- ckfree((char *)string);
- entryPtr->string = new;
- /*
- * The following construction is used because inserting improperly
- * formed UTF-8 sequences between other improperly formed UTF-8
- * sequences could result in actually forming valid UTF-8 sequences;
- * the number of characters added may not be Tcl_NumUtfChars(string, -1),
- * because of context. The actual number of characters added is how
- * many characters are in the string now minus the number that
- * used to be there.
- */
- oldChars = entryPtr->numChars;
- entryPtr->numChars = Tcl_NumUtfChars(new, -1);
- charsAdded = entryPtr->numChars - oldChars;
- entryPtr->numBytes += byteCount;
- if (entryPtr->displayString == string) {
- entryPtr->displayString = new;
- entryPtr->numDisplayBytes = entryPtr->numBytes;
- }
- /*
- * Inserting characters invalidates all indexes into the string.
- * Touch up the indexes so that they still refer to the same
- * characters (at new positions). When updating the selection
- * end-points, don't include the new text in the selection unless
- * it was completely surrounded by the selection.
- */
- if (entryPtr->selectFirst >= index) {
- entryPtr->selectFirst += charsAdded;
- }
- if (entryPtr->selectLast > index) {
- entryPtr->selectLast += charsAdded;
- }
- if ((entryPtr->selectAnchor > index)
- || (entryPtr->selectFirst >= index)) {
- entryPtr->selectAnchor += charsAdded;
- }
- if (entryPtr->leftIndex > index) {
- entryPtr->leftIndex += charsAdded;
- }
- if (entryPtr->insertPos >= index) {
- entryPtr->insertPos += charsAdded;
- }
- EntryValueChanged(entryPtr, NULL);
- }
- /*
- *----------------------------------------------------------------------
- *
- * DeleteChars --
- *
- * Remove one or more characters from an entry widget.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory gets freed, the entry gets modified and (eventually)
- * redisplayed.
- *
- *----------------------------------------------------------------------
- */
- static void
- DeleteChars(entryPtr, index, count)
- Entry *entryPtr; /* Entry widget to modify. */
- int index; /* Index of first character to delete. */
- int count; /* How many characters to delete. */
- {
- int byteIndex, byteCount, newByteCount;
- CONST char *string;
- char *new, *todelete;
- if ((index + count) > entryPtr->numChars) {
- count = entryPtr->numChars - index;
- }
- if (count <= 0) {
- return;
- }
- string = entryPtr->string;
- byteIndex = Tcl_UtfAtIndex(string, index) - string;
- byteCount = Tcl_UtfAtIndex(string + byteIndex, count) - (string + byteIndex);
- newByteCount = entryPtr->numBytes + 1 - byteCount;
- new = (char *) ckalloc((unsigned) newByteCount);
- memcpy(new, string, (size_t) byteIndex);
- strcpy(new + byteIndex, string + byteIndex + byteCount);
- todelete = (char *) ckalloc((unsigned) (byteCount + 1));
- memcpy(todelete, string + byteIndex, (size_t) byteCount);
- todelete[byteCount] = ' ';
- if ((entryPtr->validate == VALIDATE_KEY ||
- entryPtr->validate == VALIDATE_ALL) &&
- EntryValidateChange(entryPtr, todelete, new, index,
- VALIDATE_DELETE) != TCL_OK) {
- ckfree(new);
- ckfree(todelete);
- return;
- }
- ckfree(todelete);
- ckfree((char *)entryPtr->string);
- entryPtr->string = new;
- entryPtr->numChars -= count;
- entryPtr->numBytes -= byteCount;
- if (entryPtr->displayString == string) {
- entryPtr->displayString = new;
- entryPtr->numDisplayBytes = entryPtr->numBytes;
- }
- /*
- * Deleting characters results in the remaining characters being
- * renumbered. Update the various indexes into the string to reflect
- * this change.
- */
- if (entryPtr->selectFirst >= index) {
- if (entryPtr->selectFirst >= (index + count)) {
- entryPtr->selectFirst -= count;
- } else {
- entryPtr->selectFirst = index;
- }
- }
- if (entryPtr->selectLast >= index) {
- if (entryPtr->selectLast >= (index + count)) {
- entryPtr->selectLast -= count;
- } else {
- entryPtr->selectLast = index;
- }
- }
- if (entryPtr->selectLast <= entryPtr->selectFirst) {
- entryPtr->selectFirst = -1;
- entryPtr->selectLast = -1;
- }
- if (entryPtr->selectAnchor >= index) {
- if (entryPtr->selectAnchor >= (index+count)) {
- entryPtr->selectAnchor -= count;
- } else {
- entryPtr->selectAnchor = index;
- }