[175] | 1 | /*
|
---|
| 2 | Remember row,column where string was acquired.
|
---|
| 3 | postcombobox x y
|
---|
| 4 | icon?, text, row, column position, fg, bg button?
|
---|
| 5 | based upon style.
|
---|
| 6 | grab set
|
---|
| 7 | SetIcon
|
---|
| 8 | SetText
|
---|
| 9 | SetBg
|
---|
| 10 | SetFg
|
---|
| 11 | SetFont
|
---|
| 12 | SetButton
|
---|
| 13 | */
|
---|
| 14 |
|
---|
| 15 | /*
|
---|
| 16 | * bltTreeViewEdit.c --
|
---|
| 17 | *
|
---|
| 18 | * This module implements an hierarchy widget for the BLT toolkit.
|
---|
| 19 | *
|
---|
| 20 | * Copyright 1998-1999 Lucent Technologies, Inc.
|
---|
| 21 | *
|
---|
| 22 | * Permission to use, copy, modify, and distribute this software and
|
---|
| 23 | * its documentation for any purpose and without fee is hereby
|
---|
| 24 | * granted, provided that the above copyright notice appear in all
|
---|
| 25 | * copies and that both that the copyright notice and warranty
|
---|
| 26 | * disclaimer appear in supporting documentation, and that the names
|
---|
| 27 | * of Lucent Technologies or any of their entities not be used in
|
---|
| 28 | * advertising or publicity pertaining to distribution of the software
|
---|
| 29 | * without specific, written prior permission.
|
---|
| 30 | *
|
---|
| 31 | * Lucent Technologies disclaims all warranties with regard to this
|
---|
| 32 | * software, including all implied warranties of merchantability and
|
---|
| 33 | * fitness. In no event shall Lucent Technologies be liable for any
|
---|
| 34 | * special, indirect or consequential damages or any damages
|
---|
| 35 | * whatsoever resulting from loss of use, data or profits, whether in
|
---|
| 36 | * an action of contract, negligence or other tortuous action, arising
|
---|
| 37 | * out of or in connection with the use or performance of this
|
---|
| 38 | * software.
|
---|
| 39 | *
|
---|
| 40 | * The "treeview" widget was created by George A. Howlett.
|
---|
| 41 | */
|
---|
| 42 |
|
---|
| 43 | #include "bltInt.h"
|
---|
| 44 |
|
---|
| 45 | #ifndef NO_TREEVIEW
|
---|
| 46 |
|
---|
| 47 | #include "bltTreeView.h"
|
---|
| 48 | #include <X11/Xutil.h>
|
---|
| 49 | #include <X11/Xatom.h>
|
---|
| 50 |
|
---|
| 51 | #define TEXTBOX_FOCUS (1<<0)
|
---|
| 52 | #define TEXTBOX_REDRAW (1<<1)
|
---|
| 53 |
|
---|
| 54 | static Tcl_IdleProc DisplayTextbox;
|
---|
| 55 | static Tcl_FreeProc DestroyTextbox;
|
---|
| 56 | static Tcl_TimerProc BlinkCursorProc;
|
---|
| 57 | static Tcl_ObjCmdProc TextboxCmd;
|
---|
| 58 |
|
---|
| 59 | /*
|
---|
| 60 | * Textbox --
|
---|
| 61 | *
|
---|
| 62 | * This structure is shared by entries when their labels are
|
---|
| 63 | * edited via the keyboard. It maintains the location of the
|
---|
| 64 | * insertion cursor and the text selection for the editted entry.
|
---|
| 65 | * The structure is shared since we need only one. The "focus"
|
---|
| 66 | * entry should be the only entry receiving KeyPress/KeyRelease
|
---|
| 67 | * events at any time. Information from the previously editted
|
---|
| 68 | * entry is overwritten.
|
---|
| 69 | *
|
---|
| 70 | * Note that all the indices internally are in terms of bytes,
|
---|
| 71 | * not characters. This is because UTF-8 strings may encode a
|
---|
| 72 | * single character into a multi-byte sequence. To find the
|
---|
| 73 | * respective character position
|
---|
| 74 | *
|
---|
| 75 | * n = Tcl_NumUtfChars(string, index);
|
---|
| 76 | *
|
---|
| 77 | * where n is the resulting character number.
|
---|
| 78 | */
|
---|
| 79 | typedef struct {
|
---|
| 80 |
|
---|
| 81 | /*
|
---|
| 82 | * This is a SNAFU in the Tk API. It assumes that only an official
|
---|
| 83 | * Tk "toplevel" widget will ever become a toplevel window (i.e. a
|
---|
| 84 | * window whose parent is the root window). Because under Win32,
|
---|
| 85 | * Tk tries to use the widget record associated with the TopLevel
|
---|
| 86 | * as a Tk frame widget, to read its menu name. What this means
|
---|
| 87 | * is that any widget that's going to be a toplevel, must also look
|
---|
| 88 | * like a frame. Therefore we've copied the frame widget structure
|
---|
| 89 | * fields into the token.
|
---|
| 90 | */
|
---|
| 91 |
|
---|
| 92 | Tk_Window tkwin; /* Window that embodies the frame. NULL
|
---|
| 93 | * means that the window has been destroyed
|
---|
| 94 | * but the data structures haven't yet been
|
---|
| 95 | * cleaned up. */
|
---|
| 96 | Display *display; /* Display containing widget. Used, among
|
---|
| 97 | * other things, so that resources can be
|
---|
| 98 | * freed even after tkwin has gone away. */
|
---|
| 99 | Tcl_Interp *interp; /* Interpreter associated with widget. Used
|
---|
| 100 | * to delete widget command. */
|
---|
| 101 | Tcl_Command widgetCmd; /* Token for frame's widget command. */
|
---|
| 102 | char *className; /* Class name for widget (from configuration
|
---|
| 103 | * option). Malloc-ed. */
|
---|
| 104 | int mask; /* Either FRAME or TOPLEVEL; used to select
|
---|
| 105 | * which configuration options are valid for
|
---|
| 106 | * widget. */
|
---|
| 107 | char *screenName; /* Screen on which widget is created. Non-null
|
---|
| 108 | * only for top-levels. Malloc-ed, may be
|
---|
| 109 | * NULL. */
|
---|
| 110 | char *visualName; /* Textual description of visual for window,
|
---|
| 111 | * from -visual option. Malloc-ed, may be
|
---|
| 112 | * NULL. */
|
---|
| 113 | char *colormapName; /* Textual description of colormap for window,
|
---|
| 114 | * from -colormap option. Malloc-ed, may be
|
---|
| 115 | * NULL. */
|
---|
| 116 | char *menuName; /* Textual description of menu to use for
|
---|
| 117 | * menubar. Malloc-ed, may be NULL. */
|
---|
| 118 | Colormap colormap; /* If not None, identifies a colormap
|
---|
| 119 | * allocated for this window, which must be
|
---|
| 120 | * freed when the window is deleted. */
|
---|
| 121 | Tk_3DBorder border; /* Structure used to draw 3-D border and
|
---|
| 122 | * background. NULL means no background
|
---|
| 123 | * or border. */
|
---|
| 124 | int borderWidth; /* Width of 3-D border (if any). */
|
---|
| 125 | int relief; /* 3-d effect: TK_RELIEF_RAISED etc. */
|
---|
| 126 | int highlightWidth; /* Width in pixels of highlight to draw
|
---|
| 127 | * around widget when it has the focus.
|
---|
| 128 | * 0 means don't draw a highlight. */
|
---|
| 129 | XColor *highlightBgColorPtr;
|
---|
| 130 | /* Color for drawing traversal highlight
|
---|
| 131 | * area when highlight is off. */
|
---|
| 132 | XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
|
---|
| 133 | int width; /* Width to request for window. <= 0 means
|
---|
| 134 | * don't request any size. */
|
---|
| 135 | int height; /* Height to request for window. <= 0 means
|
---|
| 136 | * don't request any size. */
|
---|
| 137 | Tk_Cursor cursor; /* Current cursor for window, or None. */
|
---|
| 138 | char *takeFocus; /* Value of -takefocus option; not used in
|
---|
| 139 | * the C code, but used by keyboard traversal
|
---|
| 140 | * scripts. Malloc'ed, but may be NULL. */
|
---|
| 141 | int isContainer; /* 1 means this window is a container, 0 means
|
---|
| 142 | * that it isn't. */
|
---|
| 143 | char *useThis; /* If the window is embedded, this points to
|
---|
| 144 | * the name of the window in which it is
|
---|
| 145 | * embedded (malloc'ed). For non-embedded
|
---|
| 146 | * windows this is NULL. */
|
---|
| 147 | int flags; /* Various flags; see below for
|
---|
| 148 | * definitions. */
|
---|
| 149 |
|
---|
| 150 | /* Textbox-specific fields */
|
---|
| 151 | TreeView *tvPtr;
|
---|
| 152 | int x, y; /* Position of window. */
|
---|
| 153 |
|
---|
| 154 | int active; /* Indicates that the frame is active. */
|
---|
| 155 | int exportSelection;
|
---|
| 156 |
|
---|
| 157 | int insertPos; /* Position of the cursor within the
|
---|
| 158 | * array of bytes of the entry's label. */
|
---|
| 159 |
|
---|
| 160 | int cursorX, cursorY; /* Position of the insertion cursor in the
|
---|
| 161 | * textbox window. */
|
---|
| 162 | short int cursorWidth; /* Size of the insertion cursor symbol. */
|
---|
| 163 | short int cursorHeight;
|
---|
| 164 |
|
---|
| 165 | int selAnchor; /* Fixed end of selection. Used to extend
|
---|
| 166 | * the selection while maintaining the
|
---|
| 167 | * other end of the selection. */
|
---|
| 168 | int selFirst; /* Position of the first character in the
|
---|
| 169 | * selection. */
|
---|
| 170 | int selLast; /* Position of the last character in the
|
---|
| 171 | * selection. */
|
---|
| 172 |
|
---|
| 173 | int cursorOn; /* Indicates if the cursor is displayed. */
|
---|
| 174 | int onTime, offTime; /* Time in milliseconds to wait before
|
---|
| 175 | * changing the cursor from off-to-on
|
---|
| 176 | * and on-to-off. Setting offTime to 0 makes
|
---|
| 177 | * the cursor steady. */
|
---|
| 178 | Tcl_TimerToken timerToken; /* Handle for a timer event called periodically
|
---|
| 179 | * to blink the cursor. */
|
---|
| 180 | /* Data-specific fields. */
|
---|
| 181 | TreeViewEntry *entryPtr; /* Selected entry */
|
---|
| 182 | TreeViewColumn *columnPtr; /* Column of entry to be edited */
|
---|
| 183 | TreeViewStyle *stylePtr;
|
---|
| 184 | TreeViewIcon icon;
|
---|
| 185 | int gap;
|
---|
| 186 | char *string;
|
---|
| 187 | TextLayout *textPtr;
|
---|
| 188 | Tk_Font font;
|
---|
| 189 | GC gc;
|
---|
| 190 |
|
---|
| 191 | Tk_3DBorder selBorder;
|
---|
| 192 | int selRelief;
|
---|
| 193 | int selBorderWidth;
|
---|
| 194 | XColor *selFgColor; /* Text color of a selected entry. */
|
---|
| 195 | int buttonBorderWidth;
|
---|
| 196 | Tk_3DBorder buttonBorder;
|
---|
| 197 | int buttonRelief;
|
---|
| 198 | } Textbox;
|
---|
| 199 |
|
---|
| 200 | #define DEF_TEXTBOX_BACKGROUND RGB_WHITE
|
---|
| 201 | #define DEF_TEXTBOX_BORDERWIDTH STD_BORDERWIDTH
|
---|
| 202 | #ifdef WIN32
|
---|
| 203 | #define DEF_TEXTBOX_BUTTON_BACKGROUND RGB_GREY85
|
---|
| 204 | #else
|
---|
| 205 | #define DEF_TEXTBOX_BUTTON_BACKGROUND RGB_GREY90
|
---|
| 206 | #endif
|
---|
| 207 | #define DEF_TEXTBOX_BUTTON_BORDERWIDTH "2"
|
---|
| 208 | #define DEF_TEXTBOX_BUTTON_RELIEF "raised"
|
---|
| 209 | #define DEF_TEXTBOX_CURSOR (char *)NULL
|
---|
| 210 | #define DEF_TEXTBOX_EXPORT_SELECTION "no"
|
---|
| 211 | #define DEF_TEXTBOX_NORMAL_BACKGROUND STD_NORMAL_BACKGROUND
|
---|
| 212 | #define DEF_TEXTBOX_NORMAL_FG_MONO STD_ACTIVE_FG_MONO
|
---|
| 213 | #define DEF_TEXTBOX_RELIEF "sunken"
|
---|
| 214 | #define DEF_TEXTBOX_SELECT_BACKGROUND RGB_LIGHTBLUE0
|
---|
| 215 | #define DEF_TEXTBOX_SELECT_BG_MONO STD_SELECT_BG_MONO
|
---|
| 216 | #define DEF_TEXTBOX_SELECT_BORDERWIDTH "1"
|
---|
| 217 | #define DEF_TEXTBOX_SELECT_FOREGROUND STD_SELECT_FOREGROUND
|
---|
| 218 | #define DEF_TEXTBOX_SELECT_FG_MONO STD_SELECT_FG_MONO
|
---|
| 219 | #define DEF_TEXTBOX_SELECT_RELIEF "flat"
|
---|
| 220 |
|
---|
| 221 | /* Textbox Procedures */
|
---|
| 222 | static Blt_ConfigSpec textboxConfigSpecs[] =
|
---|
| 223 | {
|
---|
| 224 | {BLT_CONFIG_BORDER, "-background", "background", "Background",
|
---|
| 225 | DEF_TEXTBOX_BACKGROUND, Blt_Offset(Textbox, border), 0},
|
---|
| 226 | {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0,0},
|
---|
| 227 | {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0,0},
|
---|
| 228 | {BLT_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
|
---|
| 229 | DEF_TEXTBOX_CURSOR, Blt_Offset(Textbox, cursor),
|
---|
| 230 | BLT_CONFIG_NULL_OK},
|
---|
| 231 | {BLT_CONFIG_DISTANCE, "-borderwidth", "borderWidth", "BorderWidth",
|
---|
| 232 | DEF_TEXTBOX_BORDERWIDTH, Blt_Offset(Textbox, borderWidth),
|
---|
| 233 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 234 | {BLT_CONFIG_BORDER, "-buttonbackground", "buttonBackground",
|
---|
| 235 | "ButtonBackground", DEF_TEXTBOX_BUTTON_BACKGROUND,
|
---|
| 236 | Blt_Offset(Textbox, buttonBorder), 0},
|
---|
| 237 | {BLT_CONFIG_RELIEF, "-buttonrelief", "buttonRelief", "ButtonRelief",
|
---|
| 238 | DEF_TEXTBOX_BUTTON_RELIEF, Blt_Offset(Textbox, buttonRelief),
|
---|
| 239 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 240 | {BLT_CONFIG_DISTANCE, "-buttonborderwidth", "buttonBorderWidth",
|
---|
| 241 | "ButtonBorderWidth", DEF_TEXTBOX_BUTTON_BORDERWIDTH,
|
---|
| 242 | Blt_Offset(Textbox, buttonBorderWidth),
|
---|
| 243 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 244 | {BLT_CONFIG_BOOLEAN, "-exportselection", "exportSelection",
|
---|
| 245 | "ExportSelection", DEF_TEXTBOX_EXPORT_SELECTION,
|
---|
| 246 | Blt_Offset(Textbox, exportSelection),
|
---|
| 247 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 248 | {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief",
|
---|
| 249 | DEF_TEXTBOX_RELIEF, Blt_Offset(Textbox, relief), 0},
|
---|
| 250 | {BLT_CONFIG_BORDER, "-selectbackground", "selectBackground", "Background",
|
---|
| 251 | DEF_TEXTBOX_SELECT_BG_MONO, Blt_Offset(Textbox, selBorder),
|
---|
| 252 | BLT_CONFIG_MONO_ONLY},
|
---|
| 253 | {BLT_CONFIG_BORDER, "-selectbackground", "selectBackground", "Background",
|
---|
| 254 | DEF_TEXTBOX_SELECT_BACKGROUND, Blt_Offset(Textbox, selBorder),
|
---|
| 255 | BLT_CONFIG_COLOR_ONLY},
|
---|
| 256 | {BLT_CONFIG_DISTANCE, "-selectborderwidth", "selectBorderWidth",
|
---|
| 257 | "BorderWidth", DEF_TEXTBOX_SELECT_BORDERWIDTH,
|
---|
| 258 | Blt_Offset(Textbox, selBorderWidth),
|
---|
| 259 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 260 | {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
|
---|
| 261 |
|
---|
| 262 | DEF_TEXTBOX_SELECT_FG_MONO, Blt_Offset(Textbox, selFgColor),
|
---|
| 263 | BLT_CONFIG_MONO_ONLY},
|
---|
| 264 | {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
|
---|
| 265 | DEF_TEXTBOX_SELECT_FOREGROUND, Blt_Offset(Textbox, selFgColor),
|
---|
| 266 | BLT_CONFIG_COLOR_ONLY},
|
---|
| 267 | {BLT_CONFIG_RELIEF, "-selectrelief", "selectRelief", "Relief",
|
---|
| 268 | DEF_TEXTBOX_SELECT_RELIEF, Blt_Offset(Textbox, selRelief),
|
---|
| 269 | BLT_CONFIG_DONT_SET_DEFAULT},
|
---|
| 270 | {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL,
|
---|
| 271 | 0, 0}
|
---|
| 272 | };
|
---|
| 273 |
|
---|
| 274 | static Tk_LostSelProc TextboxLostSelectionProc;
|
---|
| 275 | static Tk_SelectionProc TextboxSelectionProc;
|
---|
| 276 | static Tk_EventProc TextboxEventProc;
|
---|
| 277 |
|
---|
| 278 | /*
|
---|
| 279 | *----------------------------------------------------------------------
|
---|
| 280 | *
|
---|
| 281 | * EventuallyRedraw --
|
---|
| 282 | *
|
---|
| 283 | * Queues a request to redraw the widget at the next idle point.
|
---|
| 284 | *
|
---|
| 285 | * Results:
|
---|
| 286 | * None.
|
---|
| 287 | *
|
---|
| 288 | * Side effects:
|
---|
| 289 | * Information gets redisplayed. Right now we don't do selective
|
---|
| 290 | * redisplays: the whole window will be redrawn.
|
---|
| 291 | *
|
---|
| 292 | *----------------------------------------------------------------------
|
---|
| 293 | */
|
---|
| 294 | static void
|
---|
| 295 | EventuallyRedraw(tbPtr)
|
---|
| 296 | Textbox *tbPtr;
|
---|
| 297 | {
|
---|
| 298 | if ((tbPtr->tkwin != NULL) &&
|
---|
| 299 | ((tbPtr->flags & TEXTBOX_REDRAW) == 0)) {
|
---|
| 300 | tbPtr->flags |= TEXTBOX_REDRAW;
|
---|
| 301 | Tcl_DoWhenIdle(DisplayTextbox, tbPtr);
|
---|
| 302 | }
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 | /*
|
---|
| 306 | *----------------------------------------------------------------------
|
---|
| 307 | *
|
---|
| 308 | * BlinkCursorProc --
|
---|
| 309 | *
|
---|
| 310 | * This procedure is called as a timer handler to blink the
|
---|
| 311 | * insertion cursor off and on.
|
---|
| 312 | *
|
---|
| 313 | * Results:
|
---|
| 314 | * None.
|
---|
| 315 | *
|
---|
| 316 | * Side effects:
|
---|
| 317 | * The cursor gets turned on or off, redisplay gets invoked,
|
---|
| 318 | * and this procedure reschedules itself.
|
---|
| 319 | *
|
---|
| 320 | *----------------------------------------------------------------------
|
---|
| 321 | */
|
---|
| 322 | static void
|
---|
| 323 | BlinkCursorProc(clientData)
|
---|
| 324 | ClientData clientData; /* Pointer to record describing entry. */
|
---|
| 325 | {
|
---|
| 326 | Textbox *tbPtr = clientData;
|
---|
| 327 | int interval;
|
---|
| 328 |
|
---|
| 329 | if (!(tbPtr->flags & TEXTBOX_FOCUS) || (tbPtr->offTime == 0)) {
|
---|
| 330 | return;
|
---|
| 331 | }
|
---|
| 332 | if (tbPtr->active) {
|
---|
| 333 | tbPtr->cursorOn ^= 1;
|
---|
| 334 | interval = (tbPtr->cursorOn) ? tbPtr->onTime : tbPtr->offTime;
|
---|
| 335 | tbPtr->timerToken =
|
---|
| 336 | Tcl_CreateTimerHandler(interval, BlinkCursorProc, tbPtr);
|
---|
| 337 | EventuallyRedraw(tbPtr);
|
---|
| 338 | }
|
---|
| 339 | }
|
---|
| 340 |
|
---|
| 341 | /*
|
---|
| 342 | * --------------------------------------------------------------
|
---|
| 343 | *
|
---|
| 344 | * TextboxEventProc --
|
---|
| 345 | *
|
---|
| 346 | * This procedure is invoked by the Tk dispatcher for various
|
---|
| 347 | * events on treeview widgets.
|
---|
| 348 | *
|
---|
| 349 | * Results:
|
---|
| 350 | * None.
|
---|
| 351 | *
|
---|
| 352 | * Side effects:
|
---|
| 353 | * When the window gets deleted, internal structures get
|
---|
| 354 | * cleaned up. When it gets exposed, it is redisplayed.
|
---|
| 355 | *
|
---|
| 356 | * --------------------------------------------------------------
|
---|
| 357 | */
|
---|
| 358 | static void
|
---|
| 359 | TextboxEventProc(clientData, eventPtr)
|
---|
| 360 | ClientData clientData; /* Information about window. */
|
---|
| 361 | XEvent *eventPtr; /* Information about event. */
|
---|
| 362 | {
|
---|
| 363 | Textbox *tbPtr = clientData;
|
---|
| 364 |
|
---|
| 365 | if (eventPtr->type == Expose) {
|
---|
| 366 | if (eventPtr->xexpose.count == 0) {
|
---|
| 367 | EventuallyRedraw(tbPtr);
|
---|
| 368 | }
|
---|
| 369 | } else if (eventPtr->type == ConfigureNotify) {
|
---|
| 370 | EventuallyRedraw(tbPtr);
|
---|
| 371 | } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
|
---|
| 372 | if (eventPtr->xfocus.detail == NotifyInferior) {
|
---|
| 373 | return;
|
---|
| 374 | }
|
---|
| 375 | if (eventPtr->type == FocusIn) {
|
---|
| 376 | tbPtr->flags |= TEXTBOX_FOCUS;
|
---|
| 377 | } else {
|
---|
| 378 | tbPtr->flags &= ~TEXTBOX_FOCUS;
|
---|
| 379 | }
|
---|
| 380 | Tcl_DeleteTimerHandler(tbPtr->timerToken);
|
---|
| 381 | if ((tbPtr->active) && (tbPtr->flags & TEXTBOX_FOCUS)) {
|
---|
| 382 | tbPtr->cursorOn = TRUE;
|
---|
| 383 | if (tbPtr->offTime != 0) {
|
---|
| 384 | tbPtr->timerToken = Tcl_CreateTimerHandler(tbPtr->onTime,
|
---|
| 385 | BlinkCursorProc, tbPtr);
|
---|
| 386 | }
|
---|
| 387 | } else {
|
---|
| 388 | tbPtr->cursorOn = FALSE;
|
---|
| 389 | tbPtr->timerToken = (Tcl_TimerToken) NULL;
|
---|
| 390 | }
|
---|
| 391 | EventuallyRedraw(tbPtr);
|
---|
| 392 | } else if (eventPtr->type == DestroyNotify) {
|
---|
| 393 | if (tbPtr->tkwin != NULL) {
|
---|
| 394 | tbPtr->tkwin = NULL;
|
---|
| 395 | }
|
---|
| 396 | if (tbPtr->flags & TEXTBOX_REDRAW) {
|
---|
| 397 | Tcl_CancelIdleCall(DisplayTextbox, tbPtr);
|
---|
| 398 | }
|
---|
| 399 | if (tbPtr->timerToken != NULL) {
|
---|
| 400 | Tcl_DeleteTimerHandler(tbPtr->timerToken);
|
---|
| 401 | }
|
---|
| 402 | tbPtr->tvPtr->comboWin = NULL;
|
---|
| 403 | Tcl_EventuallyFree(tbPtr, DestroyTextbox);
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | /*
|
---|
| 408 | *----------------------------------------------------------------------
|
---|
| 409 | *
|
---|
| 410 | * TextboxLostSelectionProc --
|
---|
| 411 | *
|
---|
| 412 | * This procedure is called back by Tk when the selection is
|
---|
| 413 | * grabbed away from a Text widget.
|
---|
| 414 | *
|
---|
| 415 | * Results:
|
---|
| 416 | * None.
|
---|
| 417 | *
|
---|
| 418 | * Side effects:
|
---|
| 419 | * The existing selection is unhighlighted, and the window is
|
---|
| 420 | * marked as not containing a selection.
|
---|
| 421 | *
|
---|
| 422 | *----------------------------------------------------------------------
|
---|
| 423 | */
|
---|
| 424 | static void
|
---|
| 425 | TextboxLostSelectionProc(clientData)
|
---|
| 426 | ClientData clientData; /* Information about Text widget. */
|
---|
| 427 | {
|
---|
| 428 | Textbox *tbPtr = clientData;
|
---|
| 429 |
|
---|
| 430 | if ((tbPtr->selFirst >= 0) && (tbPtr->exportSelection)) {
|
---|
| 431 | tbPtr->selFirst = tbPtr->selLast = -1;
|
---|
| 432 | EventuallyRedraw(tbPtr);
|
---|
| 433 | }
|
---|
| 434 | }
|
---|
| 435 |
|
---|
| 436 | static int
|
---|
| 437 | PointerToIndex(tbPtr, x, y)
|
---|
| 438 | Textbox *tbPtr;
|
---|
| 439 | int x, y;
|
---|
| 440 | {
|
---|
| 441 | TextLayout *textPtr;
|
---|
| 442 | Tk_FontMetrics fontMetrics;
|
---|
| 443 | TextFragment *fragPtr;
|
---|
| 444 | int nBytes;
|
---|
| 445 | register int i;
|
---|
| 446 | int total;
|
---|
| 447 |
|
---|
| 448 | if ((tbPtr->string == NULL) || (tbPtr->string[0] == '\0')) {
|
---|
| 449 | return 0;
|
---|
| 450 | }
|
---|
| 451 | x -= tbPtr->selBorderWidth;
|
---|
| 452 | y -= tbPtr->selBorderWidth;
|
---|
| 453 |
|
---|
| 454 | textPtr = tbPtr->textPtr;
|
---|
| 455 |
|
---|
| 456 | /* Bound the y-coordinate within the window. */
|
---|
| 457 | if (y < 0) {
|
---|
| 458 | y = 0;
|
---|
| 459 | } else if (y >= textPtr->height) {
|
---|
| 460 | y = textPtr->height - 1;
|
---|
| 461 | }
|
---|
| 462 | /*
|
---|
| 463 | * Compute the line that contains the y-coordinate.
|
---|
| 464 | *
|
---|
| 465 | * FIXME: This assumes that segments are distributed
|
---|
| 466 | * line-by-line. This may change in the future.
|
---|
| 467 | */
|
---|
| 468 | Tk_GetFontMetrics(tbPtr->font, &fontMetrics);
|
---|
| 469 | fragPtr = textPtr->fragArr;
|
---|
| 470 | total = 0;
|
---|
| 471 | for (i = (y / fontMetrics.linespace); i > 0; i--) {
|
---|
| 472 | total += fragPtr->count;
|
---|
| 473 | fragPtr++;
|
---|
| 474 | }
|
---|
| 475 | if (x < 0) {
|
---|
| 476 | nBytes = 0;
|
---|
| 477 | } else if (x >= textPtr->width) {
|
---|
| 478 | nBytes = fragPtr->count;
|
---|
| 479 | } else {
|
---|
| 480 | int newX;
|
---|
| 481 |
|
---|
| 482 | /* Find the character underneath the pointer. */
|
---|
| 483 | nBytes = Tk_MeasureChars(tbPtr->font, fragPtr->text, fragPtr->count,
|
---|
| 484 | x, 0, &newX);
|
---|
| 485 | if ((newX < x) && (nBytes < fragPtr->count)) {
|
---|
| 486 | double fract;
|
---|
| 487 | int length, charSize;
|
---|
| 488 | char *next;
|
---|
| 489 |
|
---|
| 490 | next = fragPtr->text + nBytes;
|
---|
| 491 | #if HAVE_UTF
|
---|
| 492 | {
|
---|
| 493 | Tcl_UniChar dummy;
|
---|
| 494 |
|
---|
| 495 | length = Tcl_UtfToUniChar(next, &dummy);
|
---|
| 496 | }
|
---|
| 497 | #else
|
---|
| 498 | length = 1;
|
---|
| 499 | #endif
|
---|
| 500 | charSize = Tk_TextWidth(tbPtr->font, next, length);
|
---|
| 501 | fract = ((double)(x - newX) / (double)charSize);
|
---|
| 502 | if (ROUND(fract)) {
|
---|
| 503 | nBytes += length;
|
---|
| 504 | }
|
---|
| 505 | }
|
---|
| 506 | }
|
---|
| 507 | return nBytes + total;
|
---|
| 508 | }
|
---|
| 509 |
|
---|
| 510 | static int
|
---|
| 511 | IndexToPointer(tbPtr)
|
---|
| 512 | Textbox *tbPtr;
|
---|
| 513 | {
|
---|
| 514 | int x, y;
|
---|
| 515 | int maxLines;
|
---|
| 516 | TextLayout *textPtr;
|
---|
| 517 | Tk_FontMetrics fontMetrics;
|
---|
| 518 | int nBytes;
|
---|
| 519 | int sum;
|
---|
| 520 | TextFragment *fragPtr;
|
---|
| 521 | register int i;
|
---|
| 522 |
|
---|
| 523 | textPtr = tbPtr->textPtr;
|
---|
| 524 | Tk_GetFontMetrics(tbPtr->font, &fontMetrics);
|
---|
| 525 | maxLines = (textPtr->height / fontMetrics.linespace) - 1;
|
---|
| 526 |
|
---|
| 527 | sum = 0;
|
---|
| 528 | x = y = tbPtr->borderWidth;
|
---|
| 529 | if (tbPtr->icon != NULL) {
|
---|
| 530 | x += TreeViewIconWidth(tbPtr->icon) + 2 * tbPtr->gap;
|
---|
| 531 | }
|
---|
| 532 | fragPtr = textPtr->fragArr;
|
---|
| 533 | for (i = 0; i <= maxLines; i++) {
|
---|
| 534 | /* Total the number of bytes on each line. Include newlines. */
|
---|
| 535 | nBytes = fragPtr->count + 1;
|
---|
| 536 | if ((sum + nBytes) > tbPtr->insertPos) {
|
---|
| 537 | x += Tk_TextWidth(tbPtr->font, fragPtr->text,
|
---|
| 538 | tbPtr->insertPos - sum);
|
---|
| 539 | break;
|
---|
| 540 | }
|
---|
| 541 | y += fontMetrics.linespace;
|
---|
| 542 | sum += nBytes;
|
---|
| 543 | fragPtr++;
|
---|
| 544 | }
|
---|
| 545 | tbPtr->cursorX = x;
|
---|
| 546 | tbPtr->cursorY = y;
|
---|
| 547 | tbPtr->cursorHeight = fontMetrics.linespace;
|
---|
| 548 | tbPtr->cursorWidth = 3;
|
---|
| 549 | return TCL_OK;
|
---|
| 550 | }
|
---|
| 551 |
|
---|
| 552 | static void
|
---|
| 553 | UpdateLayout(tbPtr)
|
---|
| 554 | Textbox *tbPtr;
|
---|
| 555 | {
|
---|
| 556 | TextStyle ts;
|
---|
| 557 | int width, height;
|
---|
| 558 | TextLayout *textPtr;
|
---|
| 559 | int gap;
|
---|
| 560 | int iconWidth, iconHeight;
|
---|
| 561 |
|
---|
| 562 | gap = iconWidth = iconHeight = 0;
|
---|
| 563 | if (tbPtr->icon != NULL) {
|
---|
| 564 | iconWidth = TreeViewIconWidth(tbPtr->icon) + 4;
|
---|
| 565 | iconHeight = TreeViewIconHeight(tbPtr->icon);
|
---|
| 566 | gap = tbPtr->gap;
|
---|
| 567 | }
|
---|
| 568 |
|
---|
| 569 | /* The layout is based upon the current font. */
|
---|
| 570 | Blt_InitTextStyle(&ts);
|
---|
| 571 | ts.anchor = TK_ANCHOR_NW;
|
---|
| 572 | ts.justify = TK_JUSTIFY_LEFT;
|
---|
| 573 | ts.font = tbPtr->font;
|
---|
| 574 | textPtr = Blt_GetTextLayout(tbPtr->string, &ts);
|
---|
| 575 | if (tbPtr->textPtr != NULL) {
|
---|
| 576 | Blt_Free(tbPtr->textPtr);
|
---|
| 577 | }
|
---|
| 578 | tbPtr->textPtr = textPtr;
|
---|
| 579 |
|
---|
| 580 | width = iconWidth + textPtr->width + gap * 2;
|
---|
| 581 | height = MAX(iconHeight, textPtr->height);
|
---|
| 582 |
|
---|
| 583 | if (width <= tbPtr->columnPtr->width) {
|
---|
| 584 | width = tbPtr->columnPtr->width;
|
---|
| 585 | }
|
---|
| 586 | if (height < tbPtr->entryPtr->height) {
|
---|
| 587 | height = tbPtr->entryPtr->height;
|
---|
| 588 | }
|
---|
| 589 | tbPtr->width = width + (2 * tbPtr->borderWidth);
|
---|
| 590 | tbPtr->height = height + (2 * tbPtr->borderWidth);
|
---|
| 591 | IndexToPointer(tbPtr);
|
---|
| 592 | Tk_MoveResizeWindow(tbPtr->tkwin, tbPtr->x, tbPtr->y,
|
---|
| 593 | tbPtr->width, tbPtr->height);
|
---|
| 594 | Tk_MapWindow(tbPtr->tkwin);
|
---|
| 595 | XRaiseWindow(tbPtr->display, Tk_WindowId(tbPtr->tkwin));
|
---|
| 596 | }
|
---|
| 597 |
|
---|
| 598 | static void
|
---|
| 599 | InsertText(tbPtr, insertText, insertPos, nBytes)
|
---|
| 600 | Textbox *tbPtr;
|
---|
| 601 | char *insertText;
|
---|
| 602 | int insertPos;
|
---|
| 603 | int nBytes;
|
---|
| 604 | {
|
---|
| 605 | int oldSize, newSize;
|
---|
| 606 | char *oldText, *newText;
|
---|
| 607 |
|
---|
| 608 | oldText = tbPtr->string;
|
---|
| 609 | oldSize = strlen(oldText);
|
---|
| 610 | newSize = oldSize + nBytes;
|
---|
| 611 | newText = Blt_Malloc(sizeof(char) * (newSize + 1));
|
---|
| 612 | if (insertPos == oldSize) { /* Append */
|
---|
| 613 | strcpy(newText, oldText);
|
---|
| 614 | strcat(newText, insertText);
|
---|
| 615 | } else if (insertPos == 0) {/* Prepend */
|
---|
| 616 | strcpy(newText, insertText);
|
---|
| 617 | strcat(newText, oldText);
|
---|
| 618 | } else { /* Insert into existing. */
|
---|
| 619 | char *p;
|
---|
| 620 |
|
---|
| 621 | p = newText;
|
---|
| 622 | strncpy(p, oldText, insertPos);
|
---|
| 623 | p += insertPos;
|
---|
| 624 | strcpy(p, insertText);
|
---|
| 625 | p += nBytes;
|
---|
| 626 | strcpy(p, oldText + insertPos);
|
---|
| 627 | }
|
---|
| 628 |
|
---|
| 629 | /*
|
---|
| 630 | * All indices from the start of the insertion to the end of the
|
---|
| 631 | * string need to be updated. Simply move the indices down by the
|
---|
| 632 | * number of characters added.
|
---|
| 633 | */
|
---|
| 634 | if (tbPtr->selFirst >= insertPos) {
|
---|
| 635 | tbPtr->selFirst += nBytes;
|
---|
| 636 | }
|
---|
| 637 | if (tbPtr->selLast > insertPos) {
|
---|
| 638 | tbPtr->selLast += nBytes;
|
---|
| 639 | }
|
---|
| 640 | if ((tbPtr->selAnchor > insertPos) || (tbPtr->selFirst >= insertPos)) {
|
---|
| 641 | tbPtr->selAnchor += nBytes;
|
---|
| 642 | }
|
---|
| 643 | if (tbPtr->string != NULL) {
|
---|
| 644 | Blt_Free(tbPtr->string);
|
---|
| 645 | }
|
---|
| 646 | tbPtr->string = newText;
|
---|
| 647 | tbPtr->insertPos = insertPos + nBytes;
|
---|
| 648 | UpdateLayout(tbPtr);
|
---|
| 649 | }
|
---|
| 650 |
|
---|
| 651 | static int
|
---|
| 652 | DeleteText(tbPtr, firstPos, lastPos)
|
---|
| 653 | Textbox *tbPtr;
|
---|
| 654 | int firstPos, lastPos;
|
---|
| 655 | {
|
---|
| 656 | char *oldText, *newText;
|
---|
| 657 | int oldSize, newSize;
|
---|
| 658 | int nBytes;
|
---|
| 659 | char *p;
|
---|
| 660 |
|
---|
| 661 | oldText = tbPtr->string;
|
---|
| 662 | if (firstPos > lastPos) {
|
---|
| 663 | return TCL_OK;
|
---|
| 664 | }
|
---|
| 665 | lastPos++; /* Now is the position after the last
|
---|
| 666 | * character. */
|
---|
| 667 |
|
---|
| 668 | nBytes = lastPos - firstPos;
|
---|
| 669 |
|
---|
| 670 | oldSize = strlen(oldText) + 1;
|
---|
| 671 | newSize = oldSize - nBytes + 1;
|
---|
| 672 | newText = Blt_Malloc(sizeof(char) * newSize);
|
---|
| 673 | p = newText;
|
---|
| 674 | if (firstPos > 0) {
|
---|
| 675 | strncpy(p, oldText, firstPos);
|
---|
| 676 | p += firstPos;
|
---|
| 677 | }
|
---|
| 678 | *p = '\0';
|
---|
| 679 | if (lastPos < oldSize) {
|
---|
| 680 | strcpy(p, oldText + lastPos);
|
---|
| 681 | }
|
---|
| 682 | Blt_Free(oldText);
|
---|
| 683 |
|
---|
| 684 | /*
|
---|
| 685 | * Since deleting characters compacts the character array, we need to
|
---|
| 686 | * update the various character indices according. It depends where
|
---|
| 687 | * the index occurs in relation to range of deleted characters:
|
---|
| 688 | *
|
---|
| 689 | * before Ignore.
|
---|
| 690 | * within Move the index back to the start of the deletion.
|
---|
| 691 | * after Subtract off the deleted number of characters,
|
---|
| 692 | * since the array has been compressed by that
|
---|
| 693 | * many characters.
|
---|
| 694 | *
|
---|
| 695 | */
|
---|
| 696 | if (tbPtr->selFirst >= firstPos) {
|
---|
| 697 | if (tbPtr->selFirst >= lastPos) {
|
---|
| 698 | tbPtr->selFirst -= nBytes;
|
---|
| 699 | } else {
|
---|
| 700 | tbPtr->selFirst = firstPos;
|
---|
| 701 | }
|
---|
| 702 | }
|
---|
| 703 | if (tbPtr->selLast >= firstPos) {
|
---|
| 704 | if (tbPtr->selLast >= lastPos) {
|
---|
| 705 | tbPtr->selLast -= nBytes;
|
---|
| 706 | } else {
|
---|
| 707 | tbPtr->selLast = firstPos;
|
---|
| 708 | }
|
---|
| 709 | }
|
---|
| 710 | if (tbPtr->selLast <= tbPtr->selFirst) {
|
---|
| 711 | tbPtr->selFirst = tbPtr->selLast = -1; /* Cut away the entire
|
---|
| 712 | * selection. */
|
---|
| 713 | }
|
---|
| 714 | if (tbPtr->selAnchor >= firstPos) {
|
---|
| 715 | if (tbPtr->selAnchor >= lastPos) {
|
---|
| 716 | tbPtr->selAnchor -= nBytes;
|
---|
| 717 | } else {
|
---|
| 718 | tbPtr->selAnchor = firstPos;
|
---|
| 719 | }
|
---|
| 720 | }
|
---|
| 721 | if (tbPtr->insertPos >= firstPos) {
|
---|
| 722 | if (tbPtr->insertPos >= lastPos) {
|
---|
| 723 | tbPtr->insertPos -= nBytes;
|
---|
| 724 | } else {
|
---|
| 725 | tbPtr->insertPos = firstPos;
|
---|
| 726 | }
|
---|
| 727 | }
|
---|
| 728 | tbPtr->string = newText;
|
---|
| 729 | UpdateLayout(tbPtr);
|
---|
| 730 | EventuallyRedraw(tbPtr);
|
---|
| 731 | return TCL_OK;
|
---|
| 732 | }
|
---|
| 733 |
|
---|
| 734 | static int
|
---|
| 735 | AcquireText(tvPtr, tbPtr, entryPtr, columnPtr)
|
---|
| 736 | TreeView *tvPtr;
|
---|
| 737 | Textbox *tbPtr;
|
---|
| 738 | TreeViewEntry *entryPtr;
|
---|
| 739 | TreeViewColumn *columnPtr;
|
---|
| 740 | {
|
---|
| 741 | TreeViewStyle *stylePtr;
|
---|
| 742 | int x, y;
|
---|
| 743 | char *string;
|
---|
| 744 | TreeViewIcon icon;
|
---|
| 745 |
|
---|
| 746 | if (columnPtr == &tvPtr->treeColumn) {
|
---|
| 747 | int level;
|
---|
| 748 |
|
---|
| 749 | level = DEPTH(tvPtr, entryPtr->node);
|
---|
| 750 | x = SCREENX(tvPtr, entryPtr->worldX);
|
---|
| 751 | y = SCREENY(tvPtr, entryPtr->worldY);
|
---|
| 752 | x += ICONWIDTH(level) + ICONWIDTH(level + 1) + 4;
|
---|
| 753 | string = GETLABEL(entryPtr);
|
---|
| 754 | stylePtr = columnPtr->stylePtr;
|
---|
| 755 | icon = Blt_TreeViewGetEntryIcon(tvPtr, entryPtr);
|
---|
| 756 | } else {
|
---|
| 757 | TreeViewValue *valuePtr;
|
---|
| 758 |
|
---|
| 759 | x = SCREENX(tvPtr, columnPtr->worldX);
|
---|
| 760 | y = SCREENY(tvPtr, entryPtr->worldY);
|
---|
| 761 | stylePtr = columnPtr->stylePtr;
|
---|
| 762 | valuePtr = Blt_TreeViewFindValue(entryPtr, columnPtr);
|
---|
| 763 | string = valuePtr->string;
|
---|
| 764 | if (valuePtr->stylePtr != NULL) {
|
---|
| 765 | stylePtr = valuePtr->stylePtr;
|
---|
| 766 | }
|
---|
| 767 | icon = stylePtr->icon;
|
---|
| 768 | }
|
---|
| 769 | if (tbPtr->textPtr != NULL) {
|
---|
| 770 | Blt_Free(tbPtr->textPtr);
|
---|
| 771 | tbPtr->textPtr = NULL;
|
---|
| 772 | }
|
---|
| 773 | if (tbPtr->string != NULL) {
|
---|
| 774 | Blt_Free(tbPtr->string);
|
---|
| 775 | }
|
---|
| 776 | if (string == NULL) {
|
---|
| 777 | string = "";
|
---|
| 778 | }
|
---|
| 779 | tbPtr->icon = icon;
|
---|
| 780 | tbPtr->entryPtr = entryPtr;
|
---|
| 781 | tbPtr->columnPtr = columnPtr;
|
---|
| 782 | tbPtr->x = x - tbPtr->borderWidth;
|
---|
| 783 | tbPtr->y = y - tbPtr->borderWidth;
|
---|
| 784 |
|
---|
| 785 | tbPtr->gap = stylePtr->gap;
|
---|
| 786 | tbPtr->string = Blt_Strdup(string);
|
---|
| 787 | tbPtr->gc = Blt_TreeViewGetStyleGC(stylePtr);
|
---|
| 788 | tbPtr->font = Blt_TreeViewGetStyleFont(tvPtr, stylePtr);
|
---|
| 789 | tbPtr->selFirst = tbPtr->selLast = -1;
|
---|
| 790 | UpdateLayout(tbPtr);
|
---|
| 791 | Tk_MapWindow(tbPtr->tkwin);
|
---|
| 792 | EventuallyRedraw(tbPtr);
|
---|
| 793 | return TCL_OK;
|
---|
| 794 | }
|
---|
| 795 |
|
---|
| 796 |
|
---|
| 797 | /*
|
---|
| 798 | *---------------------------------------------------------------------------
|
---|
| 799 | *
|
---|
| 800 | * GetIndexFromObj --
|
---|
| 801 | *
|
---|
| 802 | * Parse an index into an entry and return either its value
|
---|
| 803 | * or an error.
|
---|
| 804 | *
|
---|
| 805 | * Results:
|
---|
| 806 | * A standard Tcl result. If all went well, then *indexPtr is
|
---|
| 807 | * filled in with the character index (into entryPtr) corresponding to
|
---|
| 808 | * string. The index value is guaranteed to lie between 0 and
|
---|
| 809 | * the number of characters in the string, inclusive. If an
|
---|
| 810 | * error occurs then an error message is left in the interp's result.
|
---|
| 811 | *
|
---|
| 812 | * Side effects:
|
---|
| 813 | * None.
|
---|
| 814 | *
|
---|
| 815 | *---------------------------------------------------------------------------
|
---|
| 816 | */
|
---|
| 817 | static int
|
---|
| 818 | GetIndexFromObj(interp, tbPtr, objPtr, indexPtr)
|
---|
| 819 | Tcl_Interp *interp;
|
---|
| 820 | Textbox *tbPtr;
|
---|
| 821 | Tcl_Obj *objPtr;
|
---|
| 822 | int *indexPtr;
|
---|
| 823 | {
|
---|
| 824 | int textPos;
|
---|
| 825 | char c;
|
---|
| 826 | char *string;
|
---|
| 827 |
|
---|
| 828 | string = Tcl_GetString(objPtr);
|
---|
| 829 | if ((tbPtr->string == NULL) || (tbPtr->string[0] == '\0')) {
|
---|
| 830 | *indexPtr = 0;
|
---|
| 831 | return TCL_OK;
|
---|
| 832 | }
|
---|
| 833 | c = string[0];
|
---|
| 834 | if ((c == 'a') && (strcmp(string, "anchor") == 0)) {
|
---|
| 835 | textPos = tbPtr->selAnchor;
|
---|
| 836 | } else if ((c == 'e') && (strcmp(string, "end") == 0)) {
|
---|
| 837 | textPos = strlen(tbPtr->string);
|
---|
| 838 | } else if ((c == 'i') && (strcmp(string, "insert") == 0)) {
|
---|
| 839 | textPos = tbPtr->insertPos;
|
---|
| 840 | } else if ((c == 'n') && (strcmp(string, "next") == 0)) {
|
---|
| 841 | textPos = tbPtr->insertPos;
|
---|
| 842 | if (textPos < (int)strlen(tbPtr->string)) {
|
---|
| 843 | textPos++;
|
---|
| 844 | }
|
---|
| 845 | } else if ((c == 'l') && (strcmp(string, "last") == 0)) {
|
---|
| 846 | textPos = tbPtr->insertPos;
|
---|
| 847 | if (textPos > 0) {
|
---|
| 848 | textPos--;
|
---|
| 849 | }
|
---|
| 850 | } else if ((c == 's') && (strcmp(string, "sel.first") == 0)) {
|
---|
| 851 | if (tbPtr->selFirst < 0) {
|
---|
| 852 | textPos = -1;
|
---|
| 853 | } else {
|
---|
| 854 | textPos = tbPtr->selFirst;
|
---|
| 855 | }
|
---|
| 856 | } else if ((c == 's') && (strcmp(string, "sel.last") == 0)) {
|
---|
| 857 | if (tbPtr->selLast < 0) {
|
---|
| 858 | textPos = -1;
|
---|
| 859 | } else {
|
---|
| 860 | textPos = tbPtr->selLast;
|
---|
| 861 | }
|
---|
| 862 | } else if (c == '@') {
|
---|
| 863 | int x, y;
|
---|
| 864 |
|
---|
| 865 | if (Blt_GetXY(interp, tbPtr->tkwin, string, &x, &y) != TCL_OK) {
|
---|
| 866 | return TCL_ERROR;
|
---|
| 867 | }
|
---|
| 868 | textPos = PointerToIndex(tbPtr, x, y);
|
---|
| 869 | } else if (isdigit((int)c)) {
|
---|
| 870 | int number;
|
---|
| 871 | int maxChars;
|
---|
| 872 |
|
---|
| 873 | if (Tcl_GetIntFromObj(interp, objPtr, &number) != TCL_OK) {
|
---|
| 874 | return TCL_ERROR;
|
---|
| 875 | }
|
---|
| 876 | /* Don't allow the index to point outside the label. */
|
---|
| 877 | maxChars = Tcl_NumUtfChars(tbPtr->string, -1);
|
---|
| 878 | if (number < 0) {
|
---|
| 879 | textPos = 0;
|
---|
| 880 | } else if (number > maxChars) {
|
---|
| 881 | textPos = strlen(tbPtr->string);
|
---|
| 882 | } else {
|
---|
| 883 | textPos = Tcl_UtfAtIndex(tbPtr->string, number) -
|
---|
| 884 | tbPtr->string;
|
---|
| 885 | }
|
---|
| 886 | } else {
|
---|
| 887 | if (interp != NULL) {
|
---|
| 888 | Tcl_AppendResult(interp, "bad label index \"", string, "\"",
|
---|
| 889 | (char *)NULL);
|
---|
| 890 | }
|
---|
| 891 | return TCL_ERROR;
|
---|
| 892 | }
|
---|
| 893 | *indexPtr = textPos;
|
---|
| 894 | return TCL_OK;
|
---|
| 895 | }
|
---|
| 896 |
|
---|
| 897 | /*
|
---|
| 898 | *----------------------------------------------------------------------
|
---|
| 899 | *
|
---|
| 900 | * SelectText --
|
---|
| 901 | *
|
---|
| 902 | * Modify the selection by moving its un-anchored end. This
|
---|
| 903 | * could make the selection either larger or smaller.
|
---|
| 904 | *
|
---|
| 905 | * Results:
|
---|
| 906 | * None.
|
---|
| 907 | *
|
---|
| 908 | * Side effects:
|
---|
| 909 | * The selection changes.
|
---|
| 910 | *
|
---|
| 911 | *----------------------------------------------------------------------
|
---|
| 912 | */
|
---|
| 913 | static int
|
---|
| 914 | SelectText(tbPtr, textPos)
|
---|
| 915 | Textbox *tbPtr; /* Information about textbox. */
|
---|
| 916 | int textPos; /* Index of element that is to
|
---|
| 917 | * become the "other" end of the
|
---|
| 918 | * selection. */
|
---|
| 919 | {
|
---|
| 920 | int selFirst, selLast;
|
---|
| 921 |
|
---|
| 922 | /*
|
---|
| 923 | * Grab the selection if we don't own it already.
|
---|
| 924 | */
|
---|
| 925 | if ((tbPtr->exportSelection) && (tbPtr->selFirst == -1)) {
|
---|
| 926 | Tk_OwnSelection(tbPtr->tkwin, XA_PRIMARY,
|
---|
| 927 | TextboxLostSelectionProc, tbPtr);
|
---|
| 928 | }
|
---|
| 929 | /* If the anchor hasn't been set yet, assume the beginning of the text*/
|
---|
| 930 | if (tbPtr->selAnchor < 0) {
|
---|
| 931 | tbPtr->selAnchor = 0;
|
---|
| 932 | }
|
---|
| 933 | if (tbPtr->selAnchor <= textPos) {
|
---|
| 934 | selFirst = tbPtr->selAnchor;
|
---|
| 935 | selLast = textPos;
|
---|
| 936 | } else {
|
---|
| 937 | selFirst = textPos;
|
---|
| 938 | selLast = tbPtr->selAnchor;
|
---|
| 939 | }
|
---|
| 940 | if ((tbPtr->selFirst != selFirst) || (tbPtr->selLast != selLast)) {
|
---|
| 941 | tbPtr->selFirst = selFirst;
|
---|
| 942 | tbPtr->selLast = selLast;
|
---|
| 943 | EventuallyRedraw(tbPtr);
|
---|
| 944 | }
|
---|
| 945 | return TCL_OK;
|
---|
| 946 | }
|
---|
| 947 |
|
---|
| 948 | /*
|
---|
| 949 | *----------------------------------------------------------------------
|
---|
| 950 | *
|
---|
| 951 | * TextboxSelectionProc --
|
---|
| 952 | *
|
---|
| 953 | * This procedure is called back by Tk when the selection is
|
---|
| 954 | * requested by someone. It returns part or all of the selection
|
---|
| 955 | * in a buffer provided by the caller.
|
---|
| 956 | *
|
---|
| 957 | * Results:
|
---|
| 958 | * The return value is the number of non-NULL bytes stored at
|
---|
| 959 | * buffer. Buffer is filled (or partially filled) with a
|
---|
| 960 | * NUL-terminated string containing part or all of the
|
---|
| 961 | * selection, as given by offset and maxBytes.
|
---|
| 962 | *
|
---|
| 963 | * Side effects:
|
---|
| 964 | * None.
|
---|
| 965 | *
|
---|
| 966 | *----------------------------------------------------------------------
|
---|
| 967 | */
|
---|
| 968 | static int
|
---|
| 969 | TextboxSelectionProc(clientData, offset, buffer, maxBytes)
|
---|
| 970 | ClientData clientData; /* Information about the widget. */
|
---|
| 971 | int offset; /* Offset within selection of first
|
---|
| 972 | * character to be returned. */
|
---|
| 973 | char *buffer; /* Location in which to place
|
---|
| 974 | * selection. */
|
---|
| 975 | int maxBytes; /* Maximum number of bytes to place
|
---|
| 976 | * at buffer, not including terminating
|
---|
| 977 | * NULL character. */
|
---|
| 978 | {
|
---|
| 979 | Textbox *tbPtr = clientData;
|
---|
| 980 | int size;
|
---|
| 981 |
|
---|
| 982 | size = strlen(tbPtr->string + offset);
|
---|
| 983 | /*
|
---|
| 984 | * Return the string currently in the textbox.
|
---|
| 985 | */
|
---|
| 986 | strncpy(buffer, tbPtr->string + offset, maxBytes);
|
---|
| 987 | buffer[maxBytes] = '\0';
|
---|
| 988 | return (size > maxBytes) ? maxBytes : size;
|
---|
| 989 | }
|
---|
| 990 |
|
---|
| 991 |
|
---|
| 992 | static void
|
---|
| 993 | DestroyTextbox(data)
|
---|
| 994 | DestroyData data;
|
---|
| 995 | {
|
---|
| 996 | Textbox *tbPtr = (Textbox *)data;
|
---|
| 997 |
|
---|
| 998 | Blt_FreeObjOptions(textboxConfigSpecs, (char *)tbPtr,
|
---|
| 999 | tbPtr->display, 0);
|
---|
| 1000 |
|
---|
| 1001 | if (tbPtr->string != NULL) {
|
---|
| 1002 | Blt_Free(tbPtr->string);
|
---|
| 1003 | }
|
---|
| 1004 | if (tbPtr->textPtr != NULL) {
|
---|
| 1005 | Blt_Free(tbPtr->textPtr);
|
---|
| 1006 | }
|
---|
| 1007 | if (tbPtr->timerToken != NULL) {
|
---|
| 1008 | Tcl_DeleteTimerHandler(tbPtr->timerToken);
|
---|
| 1009 | }
|
---|
| 1010 | if (tbPtr->tkwin != NULL) {
|
---|
| 1011 | Tk_DeleteSelHandler(tbPtr->tkwin, XA_PRIMARY, XA_STRING);
|
---|
| 1012 | }
|
---|
| 1013 | Blt_Free(tbPtr);
|
---|
| 1014 | }
|
---|
| 1015 |
|
---|
| 1016 | static void
|
---|
| 1017 | ConfigureTextbox(tbPtr)
|
---|
| 1018 | Textbox *tbPtr;
|
---|
| 1019 | {
|
---|
| 1020 | #ifdef notdef
|
---|
| 1021 | GC newGC;
|
---|
| 1022 | Textbox *tbPtr = tvPtr->tbPtr;
|
---|
| 1023 | XGCValues gcValues;
|
---|
| 1024 | unsigned long gcMask;
|
---|
| 1025 |
|
---|
| 1026 | /*
|
---|
| 1027 | * GC for edit window.
|
---|
| 1028 | */
|
---|
| 1029 | gcMask = 0;
|
---|
| 1030 | newGC = Tk_GetGC(tbPtr->tkwin, gcMask, &gcValues);
|
---|
| 1031 | if (tbPtr->gc != NULL) {
|
---|
| 1032 | Tk_FreeGC(tbPtr->display, tbPtr->gc);
|
---|
| 1033 | }
|
---|
| 1034 | tbPtr->gc = newGC;
|
---|
| 1035 | tbPtr->width = tbPtr->textPtr->width +
|
---|
| 1036 | 2 * (tbPtr->borderWidth + tbPtr->highlightWidth);
|
---|
| 1037 | tbPtr->height = tbPtr->textPtr->height +
|
---|
| 1038 | 2 * (tbPtr->borderWidth + tbPtr->highlightWidth);
|
---|
| 1039 |
|
---|
| 1040 | if (Tk_IsMapped(tbPtr->tkwin)) {
|
---|
| 1041 | if ((tbPtr->height != Tk_Height(tbPtr->tkwin)) ||
|
---|
| 1042 | (tbPtr->width != Tk_Width(tbPtr->tkwin))) {
|
---|
| 1043 | Tk_ResizeWindow(tbPtr->tkwin, tbPtr->width, tbPtr->height);
|
---|
| 1044 | }
|
---|
| 1045 | }
|
---|
| 1046 | #endif
|
---|
| 1047 | }
|
---|
| 1048 |
|
---|
| 1049 | int
|
---|
| 1050 | Blt_TreeViewTextbox(tvPtr, entryPtr, columnPtr)
|
---|
| 1051 | TreeView *tvPtr;
|
---|
| 1052 | TreeViewEntry *entryPtr;
|
---|
| 1053 | TreeViewColumn *columnPtr;
|
---|
| 1054 | {
|
---|
| 1055 | Tk_Window tkwin;
|
---|
| 1056 | Textbox *tbPtr;
|
---|
| 1057 | char editClass[20];
|
---|
| 1058 |
|
---|
| 1059 | if (tvPtr->comboWin != NULL) {
|
---|
| 1060 | Tk_DestroyWindow(tvPtr->comboWin);
|
---|
| 1061 | }
|
---|
| 1062 | tkwin = Tk_CreateWindow(tvPtr->interp, tvPtr->tkwin, "edit", (char *)NULL);
|
---|
| 1063 | if (tkwin == NULL) {
|
---|
| 1064 | return TCL_ERROR;
|
---|
| 1065 | }
|
---|
| 1066 |
|
---|
| 1067 | Tk_MakeWindowExist(tkwin);
|
---|
| 1068 |
|
---|
| 1069 | sprintf(editClass, "%sEditor", Tk_Class(tvPtr->tkwin));
|
---|
| 1070 | Tk_SetClass(tkwin, editClass);
|
---|
| 1071 |
|
---|
| 1072 | tbPtr = Blt_Calloc(1, sizeof(Textbox));
|
---|
| 1073 | assert(tbPtr);
|
---|
| 1074 |
|
---|
| 1075 | tbPtr->interp = tvPtr->interp;
|
---|
| 1076 | tbPtr->display = Tk_Display(tkwin);
|
---|
| 1077 | tbPtr->tkwin = tkwin;
|
---|
| 1078 | tbPtr->borderWidth = 1;
|
---|
| 1079 | tbPtr->relief = TK_RELIEF_SOLID;
|
---|
| 1080 | tbPtr->selRelief = TK_RELIEF_FLAT;
|
---|
| 1081 | tbPtr->selBorderWidth = 1;
|
---|
| 1082 | tbPtr->selAnchor = -1;
|
---|
| 1083 | tbPtr->selFirst = tbPtr->selLast = -1;
|
---|
| 1084 | tbPtr->onTime = 600;
|
---|
| 1085 | tbPtr->active = TRUE;
|
---|
| 1086 | tbPtr->offTime = 300;
|
---|
| 1087 | tbPtr->tvPtr = tvPtr;
|
---|
| 1088 | tbPtr->buttonRelief = TK_RELIEF_SUNKEN;
|
---|
| 1089 | tbPtr->buttonBorderWidth = 1;
|
---|
| 1090 | tvPtr->comboWin = tkwin;
|
---|
| 1091 | #if (TK_MAJOR_VERSION > 4)
|
---|
| 1092 | Blt_SetWindowInstanceData(tkwin, tbPtr);
|
---|
| 1093 | #endif
|
---|
| 1094 | Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING,
|
---|
| 1095 | TextboxSelectionProc, tbPtr, XA_STRING);
|
---|
| 1096 | Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask |
|
---|
| 1097 | FocusChangeMask, TextboxEventProc, tbPtr);
|
---|
| 1098 | Tcl_CreateObjCommand(tvPtr->interp, Tk_PathName(tkwin),
|
---|
| 1099 | TextboxCmd, tbPtr, NULL);
|
---|
| 1100 | if (Blt_ConfigureWidgetFromObj(tvPtr->interp, tkwin, textboxConfigSpecs, 0,
|
---|
| 1101 | (Tcl_Obj **)NULL, (char *)tbPtr, 0) != TCL_OK) {
|
---|
| 1102 | Tk_DestroyWindow(tkwin);
|
---|
| 1103 | return TCL_ERROR;
|
---|
| 1104 | }
|
---|
| 1105 | AcquireText(tvPtr, tbPtr, entryPtr, columnPtr);
|
---|
| 1106 | tbPtr->insertPos = strlen(tbPtr->string);
|
---|
| 1107 |
|
---|
| 1108 | Tk_MoveResizeWindow(tkwin, tbPtr->x, tbPtr->y, tbPtr->width,
|
---|
| 1109 | tbPtr->height);
|
---|
| 1110 | Tk_MapWindow(tkwin);
|
---|
| 1111 | Tk_MakeWindowExist(tkwin);
|
---|
| 1112 | XRaiseWindow(tbPtr->display, Tk_WindowId(tkwin));
|
---|
| 1113 | EventuallyRedraw(tbPtr);
|
---|
| 1114 | return TCL_OK;
|
---|
| 1115 | }
|
---|
| 1116 |
|
---|
| 1117 | static void
|
---|
| 1118 | DisplayTextbox(clientData)
|
---|
| 1119 | ClientData clientData;
|
---|
| 1120 | {
|
---|
| 1121 | Textbox *tbPtr = clientData;
|
---|
| 1122 | Pixmap drawable;
|
---|
| 1123 | register int i;
|
---|
| 1124 | int x1, x2;
|
---|
| 1125 | int count, nChars;
|
---|
| 1126 | int leftPos, rightPos;
|
---|
| 1127 | int selStart, selEnd, selLength;
|
---|
| 1128 | int x, y;
|
---|
| 1129 | TextFragment *fragPtr;
|
---|
| 1130 | Tk_FontMetrics fontMetrics;
|
---|
| 1131 | #ifdef notdef
|
---|
| 1132 | int buttonX, buttonY, buttonWidth, buttonHeight;
|
---|
| 1133 | #endif
|
---|
| 1134 | tbPtr->flags &= ~TEXTBOX_REDRAW;
|
---|
| 1135 | if (!Tk_IsMapped(tbPtr->tkwin)) {
|
---|
| 1136 | return;
|
---|
| 1137 | }
|
---|
| 1138 | if (tbPtr->columnPtr == NULL) {
|
---|
| 1139 | return;
|
---|
| 1140 | }
|
---|
| 1141 | drawable = Tk_GetPixmap(tbPtr->display, Tk_WindowId(tbPtr->tkwin),
|
---|
| 1142 | Tk_Width(tbPtr->tkwin), Tk_Height(tbPtr->tkwin),
|
---|
| 1143 | Tk_Depth(tbPtr->tkwin));
|
---|
| 1144 |
|
---|
| 1145 | Blt_Fill3DRectangle(tbPtr->tkwin, drawable, tbPtr->border, 0, 0,
|
---|
| 1146 | Tk_Width(tbPtr->tkwin), Tk_Height(tbPtr->tkwin),
|
---|
| 1147 | tbPtr->borderWidth, tbPtr->relief);
|
---|
| 1148 |
|
---|
| 1149 | x = tbPtr->borderWidth + tbPtr->gap;
|
---|
| 1150 | y = tbPtr->borderWidth;
|
---|
| 1151 |
|
---|
| 1152 | #ifdef notdef
|
---|
| 1153 | buttonX = Tk_Width(tbPtr->tkwin) -
|
---|
| 1154 | (tbPtr->borderWidth + tbPtr->gap + 1);
|
---|
| 1155 | buttonY = tbPtr->borderWidth + 1;
|
---|
| 1156 | #endif
|
---|
| 1157 |
|
---|
| 1158 | if (tbPtr->icon != NULL) {
|
---|
| 1159 | y += (tbPtr->height - TreeViewIconHeight(tbPtr->icon)) / 2;
|
---|
| 1160 | Tk_RedrawImage(TreeViewIconBits(tbPtr->icon), 0, 0,
|
---|
| 1161 | TreeViewIconWidth(tbPtr->icon),
|
---|
| 1162 | TreeViewIconHeight(tbPtr->icon),
|
---|
| 1163 | drawable, x, y);
|
---|
| 1164 | x += TreeViewIconWidth(tbPtr->icon) + tbPtr->gap;
|
---|
| 1165 | }
|
---|
| 1166 |
|
---|
| 1167 | Tk_GetFontMetrics(tbPtr->font, &fontMetrics);
|
---|
| 1168 | fragPtr = tbPtr->textPtr->fragArr;
|
---|
| 1169 | count = 0;
|
---|
| 1170 | y = tbPtr->borderWidth;
|
---|
| 1171 | if (tbPtr->height > fontMetrics.linespace) {
|
---|
| 1172 | y += (tbPtr->height - fontMetrics.linespace) / 2;
|
---|
| 1173 | }
|
---|
| 1174 | for (i = 0; i < tbPtr->textPtr->nFrags; i++, fragPtr++) {
|
---|
| 1175 | leftPos = count;
|
---|
| 1176 | count += fragPtr->count;
|
---|
| 1177 | rightPos = count;
|
---|
| 1178 | if ((rightPos < tbPtr->selFirst) || (leftPos > tbPtr->selLast)) {
|
---|
| 1179 | /* No part of the text fragment is selected. */
|
---|
| 1180 | Tk_DrawChars(tbPtr->display, drawable, tbPtr->gc,
|
---|
| 1181 | tbPtr->font, fragPtr->text, fragPtr->count,
|
---|
| 1182 | x + fragPtr->x, y + fragPtr->y);
|
---|
| 1183 | continue;
|
---|
| 1184 | }
|
---|
| 1185 |
|
---|
| 1186 | /*
|
---|
| 1187 | * A text fragment can have up to 3 regions:
|
---|
| 1188 | *
|
---|
| 1189 | * 1. Text before the start the selection
|
---|
| 1190 | * 2. Selected text itself (drawn in a raised border)
|
---|
| 1191 | * 3. Text following the selection.
|
---|
| 1192 | */
|
---|
| 1193 |
|
---|
| 1194 | selStart = leftPos;
|
---|
| 1195 | selEnd = rightPos;
|
---|
| 1196 | /* First adjust selected region for current line. */
|
---|
| 1197 | if (tbPtr->selFirst > leftPos) {
|
---|
| 1198 | selStart = tbPtr->selFirst;
|
---|
| 1199 | }
|
---|
| 1200 | if (tbPtr->selLast < rightPos) {
|
---|
| 1201 | selEnd = tbPtr->selLast;
|
---|
| 1202 | }
|
---|
| 1203 | selLength = (selEnd - selStart);
|
---|
| 1204 | x1 = x;
|
---|
| 1205 |
|
---|
| 1206 | if (selStart > leftPos) { /* Normal text preceding the selection */
|
---|
| 1207 | nChars = (selStart - leftPos);
|
---|
| 1208 | Tk_MeasureChars(tbPtr->font, tbPtr->string + leftPos,
|
---|
| 1209 | nChars, 10000, DEF_TEXT_FLAGS, &x1);
|
---|
| 1210 | x1 += x;
|
---|
| 1211 | }
|
---|
| 1212 | if (selLength > 0) { /* The selection itself */
|
---|
| 1213 | int width;
|
---|
| 1214 |
|
---|
| 1215 | Tk_MeasureChars(tbPtr->font, fragPtr->text + selStart, selLength,
|
---|
| 1216 | 10000, DEF_TEXT_FLAGS, &x2);
|
---|
| 1217 | x2 += x;
|
---|
| 1218 | width = (x2 - x1) + 1;
|
---|
| 1219 | Blt_Fill3DRectangle(tbPtr->tkwin, drawable, tbPtr->selBorder,
|
---|
| 1220 | x1, y + fragPtr->y - fontMetrics.ascent,
|
---|
| 1221 | width, fontMetrics.linespace,
|
---|
| 1222 | tbPtr->selBorderWidth, tbPtr->selRelief);
|
---|
| 1223 | }
|
---|
| 1224 | Tk_DrawChars(Tk_Display(tbPtr->tkwin), drawable, tbPtr->gc,
|
---|
| 1225 | tbPtr->font, fragPtr->text, fragPtr->count,
|
---|
| 1226 | fragPtr->x + x, fragPtr->y + y);
|
---|
| 1227 | }
|
---|
| 1228 | if ((tbPtr->flags & TEXTBOX_FOCUS) && (tbPtr->cursorOn)) {
|
---|
| 1229 | int left, top, right, bottom;
|
---|
| 1230 |
|
---|
| 1231 | IndexToPointer(tbPtr);
|
---|
| 1232 | left = tbPtr->cursorX + 1;
|
---|
| 1233 | right = left + 1;
|
---|
| 1234 | top = tbPtr->cursorY;
|
---|
| 1235 | if (tbPtr->height > fontMetrics.linespace) {
|
---|
| 1236 | top += (tbPtr->height - fontMetrics.linespace) / 2;
|
---|
| 1237 | }
|
---|
| 1238 | bottom = top + tbPtr->cursorHeight - 1;
|
---|
| 1239 | XDrawLine(tbPtr->display, drawable, tbPtr->gc, left, top, left,
|
---|
| 1240 | bottom);
|
---|
| 1241 | XDrawLine(tbPtr->display, drawable, tbPtr->gc, left - 1, top, right,
|
---|
| 1242 | top);
|
---|
| 1243 | XDrawLine(tbPtr->display, drawable, tbPtr->gc, left - 1, bottom,
|
---|
| 1244 | right, bottom);
|
---|
| 1245 | }
|
---|
| 1246 | #ifdef notdef
|
---|
| 1247 | buttonWidth = STD_ARROW_WIDTH + 6 + 2 * tbPtr->buttonBorderWidth;
|
---|
| 1248 | buttonX -= buttonWidth;
|
---|
| 1249 | buttonHeight = Tk_Height(tbPtr->tkwin) - 4;
|
---|
| 1250 | Blt_Fill3DRectangle(tbPtr->tkwin, drawable, tbPtr->buttonBorder,
|
---|
| 1251 | buttonX, buttonY, buttonWidth, buttonHeight,
|
---|
| 1252 | tbPtr->buttonBorderWidth, tbPtr->buttonRelief);
|
---|
| 1253 |
|
---|
| 1254 | buttonX += buttonWidth / 2;
|
---|
| 1255 | buttonY = tbPtr->height / 2;
|
---|
| 1256 | Blt_DrawArrow(tbPtr->display, drawable, tbPtr->gc, buttonX,
|
---|
| 1257 | buttonY, STD_ARROW_HEIGHT, ARROW_DOWN);
|
---|
| 1258 | #endif
|
---|
| 1259 | Blt_Draw3DRectangle(tbPtr->tkwin, drawable, tbPtr->border, 0, 0,
|
---|
| 1260 | Tk_Width(tbPtr->tkwin), Tk_Height(tbPtr->tkwin),
|
---|
| 1261 | tbPtr->borderWidth, tbPtr->relief);
|
---|
| 1262 | XCopyArea(tbPtr->display, drawable, Tk_WindowId(tbPtr->tkwin),
|
---|
| 1263 | tbPtr->gc, 0, 0, Tk_Width(tbPtr->tkwin),
|
---|
| 1264 | Tk_Height(tbPtr->tkwin), 0, 0);
|
---|
| 1265 | Tk_FreePixmap(tbPtr->display, drawable);
|
---|
| 1266 | }
|
---|
| 1267 |
|
---|
| 1268 | /*ARGSUSED*/
|
---|
| 1269 | static int
|
---|
| 1270 | ApplyOp(tbPtr, interp, objc, objv)
|
---|
| 1271 | Textbox *tbPtr;
|
---|
| 1272 | Tcl_Interp *interp;
|
---|
| 1273 | int objc; /* Not used. */
|
---|
| 1274 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1275 | {
|
---|
| 1276 | TreeViewEntry *entryPtr;
|
---|
| 1277 | TreeView *tvPtr = tbPtr->tvPtr;
|
---|
| 1278 |
|
---|
| 1279 | entryPtr = tbPtr->entryPtr;
|
---|
| 1280 | if (tbPtr->columnPtr == &tvPtr->treeColumn) {
|
---|
| 1281 | if (entryPtr->labelUid != NULL) {
|
---|
| 1282 | Blt_TreeViewFreeUid(tvPtr, entryPtr->labelUid);
|
---|
| 1283 | }
|
---|
| 1284 | if (tbPtr->string == NULL) {
|
---|
| 1285 | entryPtr->labelUid = Blt_TreeViewGetUid(tvPtr, "");
|
---|
| 1286 | } else {
|
---|
| 1287 | entryPtr->labelUid = Blt_TreeViewGetUid(tvPtr, tbPtr->string);
|
---|
| 1288 | }
|
---|
| 1289 | } else {
|
---|
| 1290 | TreeViewColumn *columnPtr;
|
---|
| 1291 | Tcl_Obj *objPtr;
|
---|
| 1292 |
|
---|
| 1293 | columnPtr = tbPtr->columnPtr;
|
---|
| 1294 | objPtr = Tcl_NewStringObj(tbPtr->string, -1);
|
---|
| 1295 | if (Blt_TreeSetValueByKey(interp, tvPtr->tree, entryPtr->node,
|
---|
| 1296 | columnPtr->key, objPtr) != TCL_OK) {
|
---|
| 1297 | Tcl_DecrRefCount(objPtr);
|
---|
| 1298 | return TCL_ERROR;
|
---|
| 1299 | }
|
---|
| 1300 | entryPtr->flags |= ENTRY_DIRTY;
|
---|
| 1301 | }
|
---|
| 1302 | if (tvPtr != NULL) {
|
---|
| 1303 | Blt_TreeViewConfigureEntry(tvPtr, entryPtr, 0, NULL,
|
---|
| 1304 | BLT_CONFIG_OBJV_ONLY);
|
---|
| 1305 | tvPtr->flags |= (TV_LAYOUT | TV_DIRTY | TV_RESORT);
|
---|
| 1306 | Blt_TreeViewEventuallyRedraw(tvPtr);
|
---|
| 1307 | }
|
---|
| 1308 | Tk_DestroyWindow(tbPtr->tkwin);
|
---|
| 1309 | return TCL_OK;
|
---|
| 1310 | }
|
---|
| 1311 |
|
---|
| 1312 | /*ARGSUSED*/
|
---|
| 1313 | static int
|
---|
| 1314 | CancelOp(tbPtr, interp, objc, objv)
|
---|
| 1315 | Textbox *tbPtr;
|
---|
| 1316 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1317 | int objc; /* Not used. */
|
---|
| 1318 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1319 | {
|
---|
| 1320 | Tk_DestroyWindow(tbPtr->tkwin);
|
---|
| 1321 | return TCL_OK;
|
---|
| 1322 | }
|
---|
| 1323 |
|
---|
| 1324 | /*
|
---|
| 1325 | *----------------------------------------------------------------------
|
---|
| 1326 | *
|
---|
| 1327 | * CgetOp --
|
---|
| 1328 | *
|
---|
| 1329 | *----------------------------------------------------------------------
|
---|
| 1330 | */
|
---|
| 1331 | /*ARGSUSED*/
|
---|
| 1332 | static int
|
---|
| 1333 | CgetOp(tbPtr, interp, objc, objv)
|
---|
| 1334 | Textbox *tbPtr;
|
---|
| 1335 | Tcl_Interp *interp;
|
---|
| 1336 | int objc; /* Not used. */
|
---|
| 1337 | Tcl_Obj *CONST *objv;
|
---|
| 1338 | {
|
---|
| 1339 | return Blt_ConfigureValueFromObj(interp, tbPtr->tkwin,
|
---|
| 1340 | textboxConfigSpecs, (char *)tbPtr, objv[2], 0);
|
---|
| 1341 | }
|
---|
| 1342 |
|
---|
| 1343 | /*
|
---|
| 1344 | *----------------------------------------------------------------------
|
---|
| 1345 | *
|
---|
| 1346 | * ConfigureOp --
|
---|
| 1347 | *
|
---|
| 1348 | * This procedure is called to process a list of configuration
|
---|
| 1349 | * options database, in order to reconfigure the one of more
|
---|
| 1350 | * entries in the widget.
|
---|
| 1351 | *
|
---|
| 1352 | * .c configure option value
|
---|
| 1353 | *
|
---|
| 1354 | * Results:
|
---|
| 1355 | * A standard Tcl result. If TCL_ERROR is returned, then
|
---|
| 1356 | * interp->result contains an error message.
|
---|
| 1357 | *
|
---|
| 1358 | * Side effects:
|
---|
| 1359 | * Configuration information, such as text string, colors, font,
|
---|
| 1360 | * etc. get set for tvPtr; old resources get freed, if there
|
---|
| 1361 | * were any. The hypertext is redisplayed.
|
---|
| 1362 | *
|
---|
| 1363 | *----------------------------------------------------------------------
|
---|
| 1364 | */
|
---|
| 1365 | static int
|
---|
| 1366 | ConfigureOp(tbPtr, interp, objc, objv)
|
---|
| 1367 | Textbox *tbPtr;
|
---|
| 1368 | Tcl_Interp *interp;
|
---|
| 1369 | int objc;
|
---|
| 1370 | Tcl_Obj *CONST *objv;
|
---|
| 1371 | {
|
---|
| 1372 | if (objc == 2) {
|
---|
| 1373 | return Blt_ConfigureInfoFromObj(interp, tbPtr->tkwin,
|
---|
| 1374 | textboxConfigSpecs, (char *)tbPtr, (Tcl_Obj *)NULL, 0);
|
---|
| 1375 | } else if (objc == 3) {
|
---|
| 1376 | return Blt_ConfigureInfoFromObj(interp, tbPtr->tkwin,
|
---|
| 1377 | textboxConfigSpecs, (char *)tbPtr, objv[3], 0);
|
---|
| 1378 | }
|
---|
| 1379 | if (Blt_ConfigureWidgetFromObj(interp, tbPtr->tkwin,
|
---|
| 1380 | textboxConfigSpecs, objc - 2, objv + 2, (char *)tbPtr,
|
---|
| 1381 | BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
|
---|
| 1382 | return TCL_ERROR;
|
---|
| 1383 | }
|
---|
| 1384 | ConfigureTextbox(tbPtr);
|
---|
| 1385 | EventuallyRedraw(tbPtr);
|
---|
| 1386 | return TCL_OK;
|
---|
| 1387 | }
|
---|
| 1388 |
|
---|
| 1389 | /*
|
---|
| 1390 | *----------------------------------------------------------------------
|
---|
| 1391 | *
|
---|
| 1392 | * DeleteOp --
|
---|
| 1393 | *
|
---|
| 1394 | * Remove one or more characters from the label of an entry.
|
---|
| 1395 | *
|
---|
| 1396 | * Results:
|
---|
| 1397 | * None.
|
---|
| 1398 | *
|
---|
| 1399 | * Side effects:
|
---|
| 1400 | * Memory gets freed, the entry gets modified and (eventually)
|
---|
| 1401 | * redisplayed.
|
---|
| 1402 | *
|
---|
| 1403 | *----------------------------------------------------------------------
|
---|
| 1404 | */
|
---|
| 1405 | /*ARGSUSED*/
|
---|
| 1406 | static int
|
---|
| 1407 | DeleteOp(tbPtr, interp, objc, objv)
|
---|
| 1408 | Textbox *tbPtr;
|
---|
| 1409 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1410 | int objc;
|
---|
| 1411 | Tcl_Obj *CONST *objv;
|
---|
| 1412 | {
|
---|
| 1413 | int firstPos, lastPos;
|
---|
| 1414 |
|
---|
| 1415 | if (tbPtr->entryPtr == NULL) {
|
---|
| 1416 | return TCL_OK;
|
---|
| 1417 | }
|
---|
| 1418 | if (GetIndexFromObj(interp, tbPtr, objv[2], &firstPos) != TCL_OK) {
|
---|
| 1419 | return TCL_ERROR;
|
---|
| 1420 | }
|
---|
| 1421 | lastPos = firstPos;
|
---|
| 1422 | if ((objc == 4) &&
|
---|
| 1423 | (GetIndexFromObj(interp, tbPtr, objv[3], &lastPos) != TCL_OK)) {
|
---|
| 1424 | return TCL_ERROR;
|
---|
| 1425 | }
|
---|
| 1426 | if (firstPos > lastPos) {
|
---|
| 1427 | return TCL_OK;
|
---|
| 1428 | }
|
---|
| 1429 | return DeleteText(tbPtr, firstPos, lastPos);
|
---|
| 1430 | }
|
---|
| 1431 |
|
---|
| 1432 |
|
---|
| 1433 | /*
|
---|
| 1434 | *----------------------------------------------------------------------
|
---|
| 1435 | *
|
---|
| 1436 | * IcursorOp --
|
---|
| 1437 | *
|
---|
| 1438 | * Returns the numeric index of the given string. Indices can be
|
---|
| 1439 | * one of the following:
|
---|
| 1440 | *
|
---|
| 1441 | * "anchor" Selection anchor.
|
---|
| 1442 | * "end" End of the label.
|
---|
| 1443 | * "insert" Insertion cursor.
|
---|
| 1444 | * "sel.first" First character selected.
|
---|
| 1445 | * "sel.last" Last character selected.
|
---|
| 1446 | * @x,y Index at X-Y screen coordinate.
|
---|
| 1447 | * number Returns the same number.
|
---|
| 1448 | *
|
---|
| 1449 | * Results:
|
---|
| 1450 | * A standard Tcl result. If the argument does not represent a
|
---|
| 1451 | * valid label index, then TCL_ERROR is returned and the interpreter
|
---|
| 1452 | * result will contain an error message.
|
---|
| 1453 | *
|
---|
| 1454 | *----------------------------------------------------------------------
|
---|
| 1455 | */
|
---|
| 1456 | /*ARGSUSED*/
|
---|
| 1457 | static int
|
---|
| 1458 | IcursorOp(tbPtr, interp, objc, objv)
|
---|
| 1459 | Textbox *tbPtr;
|
---|
| 1460 | Tcl_Interp *interp;
|
---|
| 1461 | int objc; /* Not used. */
|
---|
| 1462 | Tcl_Obj *CONST *objv;
|
---|
| 1463 | {
|
---|
| 1464 | int textPos;
|
---|
| 1465 |
|
---|
| 1466 | if (GetIndexFromObj(interp, tbPtr, objv[2], &textPos) != TCL_OK) {
|
---|
| 1467 | return TCL_ERROR;
|
---|
| 1468 | }
|
---|
| 1469 | if (tbPtr->columnPtr != NULL) {
|
---|
| 1470 | tbPtr->insertPos = textPos;
|
---|
| 1471 | IndexToPointer(tbPtr);
|
---|
| 1472 | EventuallyRedraw(tbPtr);
|
---|
| 1473 | }
|
---|
| 1474 | return TCL_OK;
|
---|
| 1475 | }
|
---|
| 1476 |
|
---|
| 1477 |
|
---|
| 1478 | /*
|
---|
| 1479 | *----------------------------------------------------------------------
|
---|
| 1480 | *
|
---|
| 1481 | * IndexOp --
|
---|
| 1482 | *
|
---|
| 1483 | * Returns the numeric index of the given string. Indices can be
|
---|
| 1484 | * one of the following:
|
---|
| 1485 | *
|
---|
| 1486 | * "anchor" Selection anchor.
|
---|
| 1487 | * "end" End of the label.
|
---|
| 1488 | * "insert" Insertion cursor.
|
---|
| 1489 | * "sel.first" First character selected.
|
---|
| 1490 | * "sel.last" Last character selected.
|
---|
| 1491 | * @x,y Index at X-Y screen coordinate.
|
---|
| 1492 | * number Returns the same number.
|
---|
| 1493 | *
|
---|
| 1494 | * Results:
|
---|
| 1495 | * A standard Tcl result. If the argument does not represent a
|
---|
| 1496 | * valid label index, then TCL_ERROR is returned and the interpreter
|
---|
| 1497 | * result will contain an error message.
|
---|
| 1498 | *
|
---|
| 1499 | *----------------------------------------------------------------------
|
---|
| 1500 | */
|
---|
| 1501 | /*ARGSUSED*/
|
---|
| 1502 | static int
|
---|
| 1503 | IndexOp(tbPtr, interp, objc, objv)
|
---|
| 1504 | Textbox *tbPtr;
|
---|
| 1505 | Tcl_Interp *interp;
|
---|
| 1506 | int objc; /* Not used. */
|
---|
| 1507 | Tcl_Obj *CONST *objv;
|
---|
| 1508 | {
|
---|
| 1509 | int textPos;
|
---|
| 1510 |
|
---|
| 1511 | if (GetIndexFromObj(interp, tbPtr, objv[2], &textPos) != TCL_OK) {
|
---|
| 1512 | return TCL_ERROR;
|
---|
| 1513 | }
|
---|
| 1514 | if ((tbPtr->columnPtr != NULL) && (tbPtr->string != NULL)) {
|
---|
| 1515 | int nChars;
|
---|
| 1516 |
|
---|
| 1517 | nChars = Tcl_NumUtfChars(tbPtr->string, textPos);
|
---|
| 1518 | Tcl_SetObjResult(interp, Tcl_NewIntObj(nChars));
|
---|
| 1519 | }
|
---|
| 1520 | return TCL_OK;
|
---|
| 1521 | }
|
---|
| 1522 |
|
---|
| 1523 | /*
|
---|
| 1524 | *----------------------------------------------------------------------
|
---|
| 1525 | *
|
---|
| 1526 | * InsertOp --
|
---|
| 1527 | *
|
---|
| 1528 | * Add new characters to the label of an entry.
|
---|
| 1529 | *
|
---|
| 1530 | * Results:
|
---|
| 1531 | * None.
|
---|
| 1532 | *
|
---|
| 1533 | * Side effects:
|
---|
| 1534 | * New information gets added to tbPtr; it will be redisplayed
|
---|
| 1535 | * soon, but not necessarily immediately.
|
---|
| 1536 | *
|
---|
| 1537 | *----------------------------------------------------------------------
|
---|
| 1538 | */
|
---|
| 1539 | /*ARGSUSED*/
|
---|
| 1540 | static int
|
---|
| 1541 | InsertOp(tbPtr, interp, objc, objv)
|
---|
| 1542 | Textbox *tbPtr;
|
---|
| 1543 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1544 | int objc;
|
---|
| 1545 | Tcl_Obj *CONST *objv;
|
---|
| 1546 | {
|
---|
| 1547 | int extra;
|
---|
| 1548 | int insertPos;
|
---|
| 1549 | char *string;
|
---|
| 1550 |
|
---|
| 1551 | if (tbPtr->entryPtr == NULL) {
|
---|
| 1552 | return TCL_ERROR;
|
---|
| 1553 | }
|
---|
| 1554 | if (GetIndexFromObj(interp, tbPtr, objv[2], &insertPos) != TCL_OK) {
|
---|
| 1555 | return TCL_ERROR;
|
---|
| 1556 | }
|
---|
| 1557 | string = Tcl_GetStringFromObj(objv[3], &extra);
|
---|
| 1558 | if (extra == 0) { /* Nothing to insert. Move the cursor anyways. */
|
---|
| 1559 | tbPtr->insertPos = insertPos;
|
---|
| 1560 | } else {
|
---|
| 1561 | InsertText(tbPtr, string, insertPos, extra);
|
---|
| 1562 | }
|
---|
| 1563 | return TCL_OK;
|
---|
| 1564 | }
|
---|
| 1565 |
|
---|
| 1566 | /*ARGSUSED*/
|
---|
| 1567 | static int
|
---|
| 1568 | SelectionAdjustOp(tbPtr, interp, objc, objv)
|
---|
| 1569 | Textbox *tbPtr;
|
---|
| 1570 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1571 | int objc;
|
---|
| 1572 | Tcl_Obj *CONST *objv;
|
---|
| 1573 | {
|
---|
| 1574 | int textPos;
|
---|
| 1575 | int half1, half2;
|
---|
| 1576 |
|
---|
| 1577 | if (GetIndexFromObj(interp, tbPtr, objv[3], &textPos) != TCL_OK) {
|
---|
| 1578 | return TCL_ERROR;
|
---|
| 1579 | }
|
---|
| 1580 | half1 = (tbPtr->selFirst + tbPtr->selLast) / 2;
|
---|
| 1581 | half2 = (tbPtr->selFirst + tbPtr->selLast + 1) / 2;
|
---|
| 1582 | if (textPos < half1) {
|
---|
| 1583 | tbPtr->selAnchor = tbPtr->selLast;
|
---|
| 1584 | } else if (textPos > half2) {
|
---|
| 1585 | tbPtr->selAnchor = tbPtr->selFirst;
|
---|
| 1586 | }
|
---|
| 1587 | return SelectText(tbPtr, textPos);
|
---|
| 1588 | }
|
---|
| 1589 |
|
---|
| 1590 | /*ARGSUSED*/
|
---|
| 1591 | static int
|
---|
| 1592 | SelectionClearOp(tbPtr, interp, objc, objv)
|
---|
| 1593 | Textbox *tbPtr;
|
---|
| 1594 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1595 | int objc; /* Not used. */
|
---|
| 1596 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1597 | {
|
---|
| 1598 | if (tbPtr->selFirst != -1) {
|
---|
| 1599 | tbPtr->selFirst = tbPtr->selLast = -1;
|
---|
| 1600 | EventuallyRedraw(tbPtr);
|
---|
| 1601 | }
|
---|
| 1602 | return TCL_OK;
|
---|
| 1603 | }
|
---|
| 1604 |
|
---|
| 1605 | /*ARGSUSED*/
|
---|
| 1606 | static int
|
---|
| 1607 | SelectionFromOp(tbPtr, interp, objc, objv)
|
---|
| 1608 | Textbox *tbPtr;
|
---|
| 1609 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1610 | int objc;
|
---|
| 1611 | Tcl_Obj *CONST *objv;
|
---|
| 1612 | {
|
---|
| 1613 | int textPos;
|
---|
| 1614 |
|
---|
| 1615 | if (GetIndexFromObj(interp, tbPtr, objv[3], &textPos) != TCL_OK) {
|
---|
| 1616 | return TCL_ERROR;
|
---|
| 1617 | }
|
---|
| 1618 | tbPtr->selAnchor = textPos;
|
---|
| 1619 | return TCL_OK;
|
---|
| 1620 | }
|
---|
| 1621 |
|
---|
| 1622 | /*ARGSUSED*/
|
---|
| 1623 | static int
|
---|
| 1624 | SelectionPresentOp(tbPtr, interp, objc, objv)
|
---|
| 1625 | Textbox *tbPtr;
|
---|
| 1626 | Tcl_Interp *interp;
|
---|
| 1627 | int objc; /* Not used. */
|
---|
| 1628 | Tcl_Obj *CONST *objv; /* Not used. */
|
---|
| 1629 | {
|
---|
| 1630 | int bool;
|
---|
| 1631 |
|
---|
| 1632 | bool = (tbPtr->selFirst != -1);
|
---|
| 1633 | Tcl_SetObjResult(interp, Tcl_NewBooleanObj(bool));
|
---|
| 1634 | return TCL_OK;
|
---|
| 1635 | }
|
---|
| 1636 |
|
---|
| 1637 | /*ARGSUSED*/
|
---|
| 1638 | static int
|
---|
| 1639 | SelectionRangeOp(tbPtr, interp, objc, objv)
|
---|
| 1640 | Textbox *tbPtr;
|
---|
| 1641 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1642 | int objc;
|
---|
| 1643 | Tcl_Obj *CONST *objv;
|
---|
| 1644 | {
|
---|
| 1645 | int selFirst, selLast;
|
---|
| 1646 |
|
---|
| 1647 | if (GetIndexFromObj(interp, tbPtr, objv[3], &selFirst) != TCL_OK) {
|
---|
| 1648 | return TCL_ERROR;
|
---|
| 1649 | }
|
---|
| 1650 | if (GetIndexFromObj(interp, tbPtr, objv[4], &selLast) != TCL_OK) {
|
---|
| 1651 | return TCL_ERROR;
|
---|
| 1652 | }
|
---|
| 1653 | tbPtr->selAnchor = selFirst;
|
---|
| 1654 | return SelectText(tbPtr, selLast);
|
---|
| 1655 | }
|
---|
| 1656 |
|
---|
| 1657 | /*ARGSUSED*/
|
---|
| 1658 | static int
|
---|
| 1659 | SelectionToOp(tbPtr, interp, objc, objv)
|
---|
| 1660 | Textbox *tbPtr;
|
---|
| 1661 | Tcl_Interp *interp; /* Not used. */
|
---|
| 1662 | int objc;
|
---|
| 1663 | Tcl_Obj *CONST *objv;
|
---|
| 1664 | {
|
---|
| 1665 | int textPos;
|
---|
| 1666 |
|
---|
| 1667 | if (GetIndexFromObj(interp, tbPtr, objv[3], &textPos) != TCL_OK) {
|
---|
| 1668 | return TCL_ERROR;
|
---|
| 1669 | }
|
---|
| 1670 | return SelectText(tbPtr, textPos);
|
---|
| 1671 | }
|
---|
| 1672 |
|
---|
| 1673 |
|
---|
| 1674 | static Blt_OpSpec selectionOps[] =
|
---|
| 1675 | {
|
---|
| 1676 | {"adjust", 1, (Blt_Op)SelectionAdjustOp, 4, 4, "index",},
|
---|
| 1677 | {"clear", 1, (Blt_Op)SelectionClearOp, 3, 3, "",},
|
---|
| 1678 | {"from", 1, (Blt_Op)SelectionFromOp, 4, 4, "index"},
|
---|
| 1679 | {"present", 1, (Blt_Op)SelectionPresentOp, 3, 3, ""},
|
---|
| 1680 | {"range", 1, (Blt_Op)SelectionRangeOp, 5, 5, "start end",},
|
---|
| 1681 | {"to", 1, (Blt_Op)SelectionToOp, 4, 4, "index"},
|
---|
| 1682 | };
|
---|
| 1683 |
|
---|
| 1684 | static int nSelectionOps = sizeof(selectionOps) / sizeof(Blt_OpSpec);
|
---|
| 1685 |
|
---|
| 1686 | /*
|
---|
| 1687 | * This procedure handles the individual options for text
|
---|
| 1688 | * selections. The selected text is designated by start and end
|
---|
| 1689 | * indices into the text pool. The selected segment has both a
|
---|
| 1690 | * anchored and unanchored ends. The following selection
|
---|
| 1691 | * operations are implemented:
|
---|
| 1692 | *
|
---|
| 1693 | * "adjust" - resets either the first or last index
|
---|
| 1694 | * of the selection.
|
---|
| 1695 | * "clear" - clears the selection. Sets first/last
|
---|
| 1696 | * indices to -1.
|
---|
| 1697 | * "from" - sets the index of the selection anchor.
|
---|
| 1698 | * "present" - return "1" if a selection is available,
|
---|
| 1699 | * "0" otherwise.
|
---|
| 1700 | * "range" - sets the first and last indices.
|
---|
| 1701 | * "to" - sets the index of the un-anchored end.
|
---|
| 1702 | */
|
---|
| 1703 | static int
|
---|
| 1704 | SelectionOp(tbPtr, interp, objc, objv)
|
---|
| 1705 | Textbox *tbPtr;
|
---|
| 1706 | Tcl_Interp *interp;
|
---|
| 1707 | int objc;
|
---|
| 1708 | Tcl_Obj *CONST *objv;
|
---|
| 1709 | {
|
---|
| 1710 | Blt_Op proc;
|
---|
| 1711 | int result;
|
---|
| 1712 |
|
---|
| 1713 | proc = Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG2,
|
---|
| 1714 | objc, objv, 0);
|
---|
| 1715 | if (proc == NULL) {
|
---|
| 1716 | return TCL_ERROR;
|
---|
| 1717 | }
|
---|
| 1718 | result = (*proc) (tbPtr, interp, objc, objv);
|
---|
| 1719 | return result;
|
---|
| 1720 | }
|
---|
| 1721 |
|
---|
| 1722 | /*
|
---|
| 1723 | *----------------------------------------------------------------------
|
---|
| 1724 | *
|
---|
| 1725 | * TextboxCmd --
|
---|
| 1726 | *
|
---|
| 1727 | * This procedure handles entry operations.
|
---|
| 1728 | *
|
---|
| 1729 | * Results:
|
---|
| 1730 | * A standard Tcl result.
|
---|
| 1731 | *
|
---|
| 1732 | *----------------------------------------------------------------------
|
---|
| 1733 | */
|
---|
| 1734 | static Blt_OpSpec comboOps[] =
|
---|
| 1735 | {
|
---|
| 1736 | {"apply", 1, (Blt_Op)ApplyOp, 2, 2, "",},
|
---|
| 1737 | {"cancel", 2, (Blt_Op)CancelOp, 2, 2, "",},
|
---|
| 1738 | {"cget", 2, (Blt_Op)CgetOp, 3, 3, "value",},
|
---|
| 1739 | {"configure", 2, (Blt_Op)ConfigureOp, 2, 0, "?option value...?",},
|
---|
| 1740 | {"delete", 1, (Blt_Op)DeleteOp, 3, 4, "first ?last?"},
|
---|
| 1741 | {"icursor", 2, (Blt_Op)IcursorOp, 3, 3, "index"},
|
---|
| 1742 | {"index", 3, (Blt_Op)IndexOp, 3, 3, "index"},
|
---|
| 1743 | {"insert", 3, (Blt_Op)InsertOp, 4, 4, "index string"},
|
---|
| 1744 | {"selection", 1, (Blt_Op)SelectionOp, 2, 0, "args"},
|
---|
| 1745 | };
|
---|
| 1746 | static int nComboOps = sizeof(comboOps) / sizeof(Blt_OpSpec);
|
---|
| 1747 |
|
---|
| 1748 | static int
|
---|
| 1749 | TextboxCmd(clientData, interp, objc, objv)
|
---|
| 1750 | ClientData clientData;
|
---|
| 1751 | Tcl_Interp *interp;
|
---|
| 1752 | int objc;
|
---|
| 1753 | Tcl_Obj *CONST *objv;
|
---|
| 1754 | {
|
---|
| 1755 | Textbox *tbPtr = clientData;
|
---|
| 1756 | Blt_Op proc;
|
---|
| 1757 | int result;
|
---|
| 1758 |
|
---|
| 1759 | proc = Blt_GetOpFromObj(interp, nComboOps, comboOps, BLT_OP_ARG1, objc,
|
---|
| 1760 | objv, 0);
|
---|
| 1761 | if (proc == NULL) {
|
---|
| 1762 | return TCL_ERROR;
|
---|
| 1763 | }
|
---|
| 1764 | result = (*proc) (tbPtr, interp, objc, objv);
|
---|
| 1765 | return result;
|
---|
| 1766 | }
|
---|
| 1767 |
|
---|
| 1768 | #endif
|
---|
| 1769 |
|
---|