1 /*
2 * bltTed.c --
3 *
4 * This module implements an editor for the table geometry
5 * manager in the BLT toolkit.
6 *
7 * Copyright 1995 by AT&T Bell Laboratories.
8 * Permission to use, copy, modify, and distribute this software
9 * and its documentation for any purpose and without fee is hereby
10 * granted, provided that the above copyright notice appear in all
11 * copies and that both that the copyright notice and warranty
12 * disclaimer appear in supporting documentation, and that the
13 * names of AT&T Bell Laboratories any of their entities not be used
14 * in advertising or publicity pertaining to distribution of the
15 * software without specific, written prior permission.
16 *
17 * AT&T disclaims all warranties with regard to this software, including
18 * all implied warranties of merchantability and fitness. In no event
19 * shall AT&T be liable for any special, indirect or consequential
20 * damages or any damages whatsoever resulting from loss of use, data
21 * or profits, whether in an action of contract, negligence or other
22 * tortuous action, arising out of or in connection with the use or
23 * performance of this software.
24 *
25 * Table editor was created by George Howlett.
26 */
27
28 #include "bltInt.h"
29
30 #include "bltTable.h"
31
32 extern Tk_CustomOption bltDistanceOption;
33 extern Tk_CustomOption bltDashesOption;
34
35 typedef struct TedStruct Ted;
36
37 #define TABLE_THREAD_KEY "BLT Table Data"
38
39 typedef struct {
40 Blt_HashTable tableTable; /* Hash table of table structures keyed by
41 * the address of the reference Tk window */
42 } TableData;
43
44
45 typedef struct {
46 int flags;
47 Tcl_Interp *interp;
48 Tk_Window tkwin; /* Entry window */
49 Entry *entryPtr; /* Entry it represents */
50 Table *tablePtr; /* Table where it can be found */
51 Ted *tedPtr; /* Table editor */
52 int mapped; /* Indicates if the debugging windows are
53 * mapped */
54 } EntryRep;
55
56
57 typedef struct {
58 Tk_Font font;
59 XColor *widgetColor;
60 XColor *cntlColor;
61 XColor *normalFg, *normalBg;
62 XColor *activeFg, *activeBg;
63
64 Tk_Cursor cursor; /* Cursor to display inside of this window */
65 Pixmap stipple;
66
67 GC drawGC; /* GC to draw grid, outlines */
68 GC fillGC; /* GC to fill entry area */
69 GC widgetFillGC; /* GC to fill widget area */
70 GC cntlGC; /* GC to fill rectangles */
71
72 } EntryAttributes;
73
74 typedef struct {
75 int count;
76 XRectangle *array;
77 } Rectangles;
78
79 struct TedStruct {
80 int gridLineWidth; /* Width of grid lines */
81 int buttonHeight; /* Height of row/column buttons */
82 int cavityPad; /* Extra padding to add to entry cavity */
83 int minSize; /* Minimum size for partitions */
84
85 EditorDrawProc *drawProc;
86 EditorDestroyProc *destroyProc;
87
88 Display *display;
89 Tk_Font font;
90 Table *tablePtr; /* Pointer to table being debugged */
91 Tcl_Interp *interp;
92 int flags;
93 Tk_Window tkwin; /* Grid window */
94 Tk_Window input; /* InputOnly window to receive events */
95 int inputIsSibling;
96
97 /* Form the grid */
98 XSegment *segArr;
99 int nSegs;
100 XRectangle *padRectArr;
101 int nPadRects;
102 XRectangle *widgetPadRectArr;
103 int nWidgetPadRects;
104
105 XRectangle *cntlRectArr;
106 int nCntlRects;
107
108 XRectangle *rectArr;
109 int nRects;
110
111 XRectangle activeRectArr[5];
112 int spanActive;
113
114 GC rectGC; /* GC to fill rectangles */
115 GC drawGC; /* GC to draw grid, outlines */
116 GC fillGC; /* GC to fill window */
117 GC spanGC; /* GC to fill spans */
118 GC padRectGC; /* GC to draw padding */
119
120 Tk_3DBorder border; /* Border to use with buttons */
121 int relief;
122 int borderWidth; /* Border width of buttons */
123 XColor *normalBg;
124 XColor *padColor;
125 XColor *gridColor;
126 XColor *buttonColor;
127 XColor *spanColor;
128
129 Pixmap padStipple;
130 Pixmap spanStipple;
131 Blt_Dashes dashes;
132 char *fileName; /* If non-NULL, indicates name of file
133 * to write final table output to */
134 int mapped; /* Indicates if the debugging windows are
135 * mapped */
136 int gripSize;
137 int doubleBuffer;
138 Tk_Cursor cursor;
139 Blt_Chain *chainPtr;
140 int nextWindowId;
141
142 EntryAttributes attributes; /* Entry attributes */
143 };
144
145 #define REDRAW_PENDING (1<<0) /* A DoWhenIdle handler has already
146 * been queued to redraw the window */
147 #define LAYOUT_PENDING (1<<1)
148
149 /*
150 *
151 *
152 * |Cavity|1|2|
153 *
154 *
155 */
156 #define DEF_ENTRY_ACTIVE_BG_MONO RGB_BLACK
157 #define DEF_ENTRY_ACTIVE_FG_MONO RGB_WHITE
158 #define DEF_ENTRY_ACTIVE_BACKGROUND RGB_BLACK
159 #define DEF_ENTRY_ACTIVE_FOREGROUND RGB_WHITE
160 #define DEF_ENTRY_CURSOR (char *)NULL
161 #define DEF_ENTRY_FONT "*-Courier-Bold-R-Normal-*-100-*"
162 #define DEF_ENTRY_NORMAL_BACKGROUND RGB_BLUE
163 #define DEF_ENTRY_NORMAL_BG_MONO RGB_BLACK
164 #define DEF_ENTRY_NORMAL_FOREGROUND RGB_WHITE
165 #define DEF_ENTRY_NORMAL_FG_MONO RGB_WHITE
166 #define DEF_ENTRY_WIDGET_BACKGROUND RGB_GREEN
167 #define DEF_ENTRY_CONTROL_BACKGROUND RGB_YELLOW
168 #define DEF_ENTRY_WIDGET_BG_MONO RGB_BLACK
169 #define DEF_ENTRY_STIPPLE "gray50"
170 #define DEF_GRID_BACKGROUND RGB_WHITE
171 #define DEF_GRID_BG_MONO RGB_WHITE
172 #define DEF_GRID_CURSOR "crosshair"
173 #define DEF_GRID_DASHES (char *)NULL
174 #define DEF_GRID_FOREGROUND RGB_BLACK
175 #define DEF_GRID_FG_MONO RGB_BLACK
176 #define DEF_GRID_FONT "*-Courier-Bold-R-Normal-*-100-*"
177 #define DEF_GRID_LINE_WIDTH "1"
178 #define DEF_GRID_PAD_COLOR RGB_RED
179 #define DEF_GRID_PAD_MONO RGB_BLACK
180 #define DEF_GRID_PAD_STIPPLE "gray25"
181 #define DEF_GRID_PAD_CAVITY "0"
182 #define DEF_GRID_PAD_MIN "8"
183 #define DEF_ROWCOL_BACKGROUND RGB_RED
184 #define DEF_ROWCOL_BG_MONO RGB_BLACK
185 #define DEF_ROWCOL_BORDER_COLOR RGB_RED
186 #define DEF_ROWCOL_BORDER_MONO RGB_BLACK
187 #define DEF_ROWCOL_BORDERWIDTH "2"
188 #define DEF_ROWCOL_HEIGHT "8"
189 #define DEF_ROWCOL_RELIEF "raised"
190 #define DEF_SPAN_STIPPLE "gray50"
191 #define DEF_SPAN_COLOR RGB_BLACK
192 #define DEF_SPAN_MONO RGB_BLACK
193 #define DEF_SPAN_GRIP_SIZE "5"
194 #define DEF_GRID_DOUBLE_BUFFER "1"
195
196 static Tk_ConfigSpec configSpecs[] =
197 {
198 {TK_CONFIG_BORDER, "-bg", "tedBorder", (char *)NULL,
199 DEF_ROWCOL_BORDER_COLOR, Tk_Offset(Ted, border), TK_CONFIG_COLOR_ONLY},
200 {TK_CONFIG_BORDER, "-bg", "tedBorder", (char *)NULL,
201 DEF_ROWCOL_BORDER_MONO, Tk_Offset(Ted, border), TK_CONFIG_MONO_ONLY},
202 {TK_CONFIG_COLOR, "-background", "tedBackground", (char *)NULL,
203 DEF_GRID_BACKGROUND, Tk_Offset(Ted, normalBg), TK_CONFIG_COLOR_ONLY},
204 {TK_CONFIG_COLOR, "-background", "tedBackground", (char *)NULL,
205 DEF_GRID_BG_MONO, Tk_Offset(Ted, normalBg), TK_CONFIG_MONO_ONLY},
206 {TK_CONFIG_CURSOR, "-cursor", "cursor", (char *)NULL,
207 DEF_GRID_CURSOR, Tk_Offset(Ted, cursor), TK_CONFIG_NULL_OK},
208 {TK_CONFIG_COLOR, "-gridcolor", "gridColor", (char *)NULL,
209 DEF_GRID_FOREGROUND, Tk_Offset(Ted, gridColor), TK_CONFIG_COLOR_ONLY},
210 {TK_CONFIG_COLOR, "-gridcolor", "gridColor", (char *)NULL,
211 DEF_GRID_FG_MONO, Tk_Offset(Ted, gridColor), TK_CONFIG_MONO_ONLY},
212 {TK_CONFIG_COLOR, "-buttoncolor", "buttonColor", (char *)NULL,
213 DEF_ROWCOL_BACKGROUND, Tk_Offset(Ted, buttonColor), TK_CONFIG_COLOR_ONLY},
214 {TK_CONFIG_COLOR, "-buttoncolor", "buttonColor", (char *)NULL,
215 DEF_ROWCOL_BG_MONO, Tk_Offset(Ted, buttonColor), TK_CONFIG_MONO_ONLY},
216 {TK_CONFIG_COLOR, "-padcolor", "padColor", (char *)NULL,
217 DEF_GRID_PAD_COLOR, Tk_Offset(Ted, padColor), TK_CONFIG_COLOR_ONLY},
218 {TK_CONFIG_COLOR, "-padcolor", "padColor", (char *)NULL,
219 DEF_GRID_PAD_MONO, Tk_Offset(Ted, padColor), TK_CONFIG_MONO_ONLY},
220 {TK_CONFIG_BITMAP, "-padstipple", "padStipple", (char *)NULL,
221 DEF_GRID_PAD_STIPPLE, Tk_Offset(Ted, padStipple), TK_CONFIG_NULL_OK},
222 {TK_CONFIG_FONT, "-font", "font", (char *)NULL,
223 DEF_GRID_FONT, Tk_Offset(Ted, font), 0},
224 {TK_CONFIG_CUSTOM, "-gridlinewidth", "gridLineWidth", (char *)NULL,
225 DEF_GRID_LINE_WIDTH, Tk_Offset(Ted, gridLineWidth),
226 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
227 {TK_CONFIG_CUSTOM, "-buttonheight", "buttonHeight", (char *)NULL,
228 DEF_ROWCOL_HEIGHT, Tk_Offset(Ted, buttonHeight),
229 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
230 {TK_CONFIG_CUSTOM, "-cavitypad", "cavityPad", (char *)NULL,
231 DEF_GRID_PAD_CAVITY, Tk_Offset(Ted, cavityPad),
232 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
233 {TK_CONFIG_CUSTOM, "-minsize", "minSize", (char *)NULL,
234 DEF_GRID_PAD_MIN, Tk_Offset(Ted, minSize),
235 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
236 {TK_CONFIG_CUSTOM, "-dashes", "dashes", (char *)NULL,
237 DEF_GRID_DASHES, Tk_Offset(Ted, dashes),
238 TK_CONFIG_NULL_OK, &bltDashesOption},
239 {TK_CONFIG_RELIEF, "-relief", "relief", (char *)NULL,
240 DEF_ROWCOL_RELIEF, Tk_Offset(Ted, relief), TK_CONFIG_DONT_SET_DEFAULT},
241 {TK_CONFIG_CUSTOM, "-borderwidth", "borderWidth", (char *)NULL,
242 DEF_ROWCOL_BORDERWIDTH, Tk_Offset(Ted, borderWidth),
243 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
244 {TK_CONFIG_CURSOR, "-entrycursor", "entryCursor", (char *)NULL,
245 DEF_ENTRY_CURSOR, Tk_Offset(Ted, attributes.cursor),
246 TK_CONFIG_NULL_OK},
247 {TK_CONFIG_FONT, "-entryfont", "entryFont", (char *)NULL,
248 DEF_ENTRY_FONT, Tk_Offset(Ted, attributes.font), 0},
249 {TK_CONFIG_BITMAP, "-entrystipple", "entryStipple", (char *)NULL,
250 DEF_ENTRY_STIPPLE, Tk_Offset(Ted, attributes.stipple),
251 TK_CONFIG_NULL_OK},
252 {TK_CONFIG_COLOR, "-widgetbackground", "widgetBackground", (char *)NULL,
253 DEF_ENTRY_WIDGET_BACKGROUND, Tk_Offset(Ted, attributes.widgetColor),
254 TK_CONFIG_COLOR_ONLY},
255 {TK_CONFIG_COLOR, "-widgetbackground", "widgetBackground", (char *)NULL,
256 DEF_ENTRY_WIDGET_BG_MONO, Tk_Offset(Ted, attributes.widgetColor),
257 TK_CONFIG_MONO_ONLY},
258 {TK_CONFIG_COLOR, "-controlbackground", "controlBackground", (char *)NULL,
259 DEF_ENTRY_CONTROL_BACKGROUND, Tk_Offset(Ted, attributes.cntlColor),
260 TK_CONFIG_COLOR_ONLY},
261 {TK_CONFIG_COLOR, "-controlbackground", "controlBackground", (char *)NULL,
262 DEF_ENTRY_WIDGET_BG_MONO, Tk_Offset(Ted, attributes.cntlColor),
263 TK_CONFIG_MONO_ONLY},
264 {TK_CONFIG_COLOR, "-entrybackground", "entryBackground", (char *)NULL,
265 DEF_ENTRY_NORMAL_BACKGROUND, Tk_Offset(Ted, attributes.normalBg),
266 TK_CONFIG_COLOR_ONLY},
267 {TK_CONFIG_COLOR, "-entrybackground", "entryBackground", (char *)NULL,
268 DEF_ENTRY_NORMAL_BG_MONO, Tk_Offset(Ted, attributes.normalBg),
269 TK_CONFIG_MONO_ONLY},
270 {TK_CONFIG_COLOR, "-entryactivebackground", "entryActiveBackground", (char *)NULL,
271 DEF_ENTRY_ACTIVE_BACKGROUND, Tk_Offset(Ted, attributes.activeBg),
272 TK_CONFIG_COLOR_ONLY},
273 {TK_CONFIG_COLOR, "-entryactivebackground", "entryActiveBackground", (char *)NULL,
274 DEF_ENTRY_ACTIVE_BG_MONO, Tk_Offset(Ted, attributes.activeBg),
275 TK_CONFIG_MONO_ONLY},
276 {TK_CONFIG_COLOR, "-entryactiveforeground", "entryActiveForeground", (char *)NULL,
277 DEF_ENTRY_ACTIVE_FOREGROUND, Tk_Offset(Ted, attributes.activeFg),
278 TK_CONFIG_COLOR_ONLY},
279 {TK_CONFIG_COLOR, "-entryactiveforeground", "entryActiveForeground", (char *)NULL,
280 DEF_ENTRY_ACTIVE_FG_MONO, Tk_Offset(Ted, attributes.activeFg),
281 TK_CONFIG_MONO_ONLY},
282 {TK_CONFIG_COLOR, "-entryforeground", "entryForeground", (char *)NULL,
283 DEF_ENTRY_NORMAL_FOREGROUND, Tk_Offset(Ted, attributes.normalFg),
284 TK_CONFIG_COLOR_ONLY},
285 {TK_CONFIG_COLOR, "-entryforeground", "entryForeground", (char *)NULL,
286 DEF_ENTRY_NORMAL_FG_MONO, Tk_Offset(Ted, attributes.normalFg),
287 TK_CONFIG_MONO_ONLY},
288 {TK_CONFIG_COLOR, "-spancolor", "spanColor", (char *)NULL,
289 DEF_SPAN_COLOR, Tk_Offset(Ted, spanColor), TK_CONFIG_COLOR_ONLY},
290 {TK_CONFIG_COLOR, "-spancolor", "spanColor", (char *)NULL,
291 DEF_SPAN_MONO, Tk_Offset(Ted, spanColor), TK_CONFIG_MONO_ONLY},
292 {TK_CONFIG_BITMAP, "-spanstipple", "spanStipple", (char *)NULL,
293 DEF_SPAN_STIPPLE, Tk_Offset(Ted, spanStipple), TK_CONFIG_NULL_OK},
294 {TK_CONFIG_CUSTOM, "-gripsize", "gripSize", (char *)NULL,
295 DEF_SPAN_GRIP_SIZE, Tk_Offset(Ted, gripSize),
296 TK_CONFIG_DONT_SET_DEFAULT, &bltDistanceOption},
297 {TK_CONFIG_BOOLEAN, "-dbl", "doubleBuffer", (char *)NULL,
298 DEF_GRID_DOUBLE_BUFFER, Tk_Offset(Ted, doubleBuffer),
299 TK_CONFIG_DONT_SET_DEFAULT},
300 {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
301 };
302
303
304 static void DrawEditor _ANSI_ARGS_((Editor *editor));
305 static void DestroyEditor _ANSI_ARGS_((DestroyData destroyData));
306 static void DisplayTed _ANSI_ARGS_((ClientData clientData));
307 static void DestroyTed _ANSI_ARGS_((DestroyData destroyData));
308 static void DisplayEntry _ANSI_ARGS_((ClientData clientData));
309 static void DestroyEntry _ANSI_ARGS_((DestroyData destoryData));
310
311 static Tcl_CmdProc TedCmd;
312 static Tk_EventProc EntryEventProc;
313 static Tk_EventProc TedEventProc;
314
315 /*
316 *----------------------------------------------------------------------
317 *
318 * EventuallyRedraw --
319 *
320 * Queues a request to redraw the text window at the next idle
321 * point.
322 *
323 * Results:
324 * None.
325 *
326 * Side effects:
327 * Information gets redisplayed. Right now we don't do selective
328 * redisplays: the whole window will be redrawn. This doesn't
329 * seem to hurt performance noticeably, but if it does then this
330 * could be changed.
331 *
332 *----------------------------------------------------------------------
333 */
334 static void
EventuallyRedraw(tedPtr)335 EventuallyRedraw(tedPtr)
336 Ted *tedPtr; /* Information about editor. */
337 {
338 if ((tedPtr->tkwin != NULL) && !(tedPtr->flags & REDRAW_PENDING)) {
339 tedPtr->flags |= REDRAW_PENDING;
340 Tcl_DoWhenIdle(DisplayTed, tedPtr);
341 }
342 }
343
344 /*
345 *----------------------------------------------------------------------
346 *
347 * EventuallyRedraw --
348 *
349 * Queues a request to redraw the text window at the next idle
350 * point.
351 *
352 * Results:
353 * None.
354 *
355 * Side effects:
356 * Information gets redisplayed. Right now we don't do selective
357 * redisplays: the whole window will be redrawn. This doesn't
358 * seem to hurt performance noticeably, but if it does then this
359 * could be changed.
360 *
361 *----------------------------------------------------------------------
362 */
363 static void
EventuallyRedrawEntry(repPtr)364 EventuallyRedrawEntry(repPtr)
365 EntryRep *repPtr; /* Information about editor. */
366 {
367 if ((repPtr->tkwin != NULL) && !(repPtr->flags & REDRAW_PENDING)) {
368 repPtr->flags |= REDRAW_PENDING;
369 Tcl_DoWhenIdle(DisplayEntry, repPtr);
370 }
371 }
372
373 /*
374 * --------------------------------------------------------------
375 *
376 * EntryEventProc --
377 *
378 * This procedure is invoked by the Tk dispatcher for various
379 * events on the editing grid for the table.
380 *
381 * Results:
382 * None.
383 *
384 * Side effects:
385 * When the window gets deleted, internal structures get
386 * cleaned up. When it gets exposed, it is redisplayed.
387 *
388 * --------------------------------------------------------------
389 */
390 static void
EntryEventProc(clientData,eventPtr)391 EntryEventProc(clientData, eventPtr)
392 ClientData clientData; /* Information about window. */
393 XEvent *eventPtr; /* Information about event. */
394 {
395 EntryRep *repPtr = (EntryRep *) clientData;
396
397 if (eventPtr->type == ConfigureNotify) {
398 EventuallyRedrawEntry(repPtr);
399 } else if (eventPtr->type == Expose) {
400 if (eventPtr->xexpose.count == 0) {
401 EventuallyRedrawEntry(repPtr);
402 }
403 } else if (eventPtr->type == DestroyNotify) {
404 repPtr->tkwin = NULL;
405 if (repPtr->flags & REDRAW_PENDING) {
406 Tcl_CancelIdleCall(DisplayEntry, repPtr);
407 }
408 Tcl_EventuallyFree(repPtr, DestroyEntry);
409 }
410 }
411
412 /*
413 * --------------------------------------------------------------
414 *
415 * TedEventProc --
416 *
417 * This procedure is invoked by the Tk dispatcher for various
418 * events on the editing grid for the table.
419 *
420 * Results:
421 * None.
422 *
423 * Side effects:
424 * When the window gets deleted, internal structures get
425 * cleaned up. When it gets exposed, it is redisplayed.
426 *
427 * --------------------------------------------------------------
428 */
429 static void
TedEventProc(clientData,eventPtr)430 TedEventProc(clientData, eventPtr)
431 ClientData clientData; /* Information about window. */
432 XEvent *eventPtr; /* Information about event. */
433 {
434 Ted *tedPtr = (Ted *) clientData;
435
436 if (eventPtr->type == ConfigureNotify) {
437 EventuallyRedraw(tedPtr);
438 } else if (eventPtr->type == Expose) {
439 if (eventPtr->xexpose.count == 0) {
440 EventuallyRedraw(tedPtr);
441 }
442 } else if (eventPtr->type == DestroyNotify) {
443 tedPtr->tkwin = NULL;
444 if (tedPtr->flags & REDRAW_PENDING) {
445 Tcl_CancelIdleCall(DisplayTed, tedPtr);
446 }
447 Tcl_EventuallyFree(tedPtr, DestroyTed);
448 }
449 }
450
451 /*
452 * ----------------------------------------------------------------------------
453 *
454 * CreateGrid --
455 *
456 * ----------------------------------------------------------------------------
457 */
458 static int
CreateGrid(tedPtr)459 CreateGrid(tedPtr)
460 Ted *tedPtr;
461 {
462 Tcl_Interp *interp;
463 Tk_Window tkwin;
464 Tk_Window master;
465 /*
466 * Create a sibling window to cover the master window. It will
467 * be stacked just above the master window.
468 */
469 interp = tedPtr->tablePtr->interp;
470 master = tedPtr->tablePtr->tkwin;
471 tkwin = Tk_CreateWindow(interp, master, "ted_%output%", (char *)NULL);
472 if (tkwin == NULL) {
473 return TCL_ERROR;
474 }
475 Tk_SetClass(tkwin, "BltTed");
476 Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,
477 TedEventProc, tedPtr);
478 Tk_MoveResizeWindow(tkwin, 0, 0, Tk_Width(master), Tk_Height(master));
479 Tk_RestackWindow(tkwin, Below, (Tk_Window)NULL);
480 Tk_MapWindow(tkwin);
481 tedPtr->tkwin = tkwin;
482 return TCL_OK;
483 }
484
485 /*
486 * ----------------------------------------------------------------------------
487 *
488 * CreateEventWindow --
489 *
490 * ----------------------------------------------------------------------------
491 */
492 static int
CreateEventWindow(tedPtr)493 CreateEventWindow(tedPtr)
494 Ted *tedPtr;
495 {
496 Tcl_Interp *interp;
497 Tk_Window tkwin;
498 Tk_Window master;
499 Tk_Window parent;
500
501 interp = tedPtr->tablePtr->interp;
502 master = tedPtr->tablePtr->tkwin;
503 /*
504 * Create an InputOnly window which sits above the table to
505 * collect and dispatch user events.
506 */
507 if (Tk_IsTopLevel(master)) {
508 /*
509 * If master is a top-level window, it's also the parent of
510 * the widgets (it can't have a sibling).
511 * In this case, the InputOnly window is a child of the
512 * master instead of a sibling.
513 */
514 parent = master;
515 tkwin = Tk_CreateWindow(interp, parent, "ted_%input%", (char *)NULL);
516 if (tkwin != NULL) {
517 Tk_ResizeWindow(tkwin, Tk_Width(parent), Tk_Height(parent));
518 }
519 tedPtr->inputIsSibling = 0;
520 } else {
521 char *namePtr; /* Name of InputOnly window. */
522
523 parent = Tk_Parent(master);
524 namePtr = Blt_Malloc(strlen(Tk_Name(master)) + 5);
525 sprintf(namePtr, "ted_%s", Tk_Name(master));
526 tkwin = Tk_CreateWindow(interp, parent, namePtr, (char *)NULL);
527 Blt_Free(namePtr);
528 if (tkwin != NULL) {
529 Tk_MoveResizeWindow(tkwin, Tk_X(master), Tk_Y(master),
530 Tk_Width(master), Tk_Height(master));
531 }
532 tedPtr->inputIsSibling = 1;
533 }
534 if (tkwin == NULL) {
535 return TCL_ERROR;
536 }
537 Blt_MakeTransparentWindowExist(tkwin, Tk_WindowId(parent), TRUE);
538 Tk_RestackWindow(tkwin, Above, (Tk_Window)NULL);
539 Tk_MapWindow(tkwin);
540 tedPtr->input = tkwin;
541 return TCL_OK;
542 }
543
544 /*
545 * ----------------------------------------------------------------------------
546 *
547 * CreateEntry --
548 *
549 * ----------------------------------------------------------------------------
550 */
551 static int
CreateEntry(tedPtr,entryPtr)552 CreateEntry(tedPtr, entryPtr)
553 Ted *tedPtr;
554 Entry *entryPtr;
555 {
556 Tk_Window tkwin, master;
557 char string[200];
558 EntryRep *repPtr;
559 Blt_ChainLink *linkPtr;
560
561 repPtr = Blt_Calloc(1, sizeof(EntryRep));
562 assert(repPtr);
563 repPtr->tablePtr = tedPtr->tablePtr;
564 repPtr->tedPtr = tedPtr;
565 repPtr->interp = tedPtr->interp;
566 repPtr->entryPtr = entryPtr;
567 repPtr->mapped = 0;
568
569 /*
570 * Create a sibling window to cover the master window. It will
571 * be stacked just above the master window.
572 */
573
574 master = tedPtr->tablePtr->tkwin;
575 sprintf(string, "bltTed%d", tedPtr->nextWindowId);
576 tedPtr->nextWindowId++;
577 tkwin = Tk_CreateWindow(tedPtr->interp, master, string, (char *)NULL);
578 if (tkwin == NULL) {
579 Blt_Free(repPtr);
580 return TCL_ERROR;
581 }
582 Tk_SetClass(tkwin, "BltTed");
583 Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,
584 EntryEventProc, repPtr);
585 repPtr->tkwin = tkwin;
586 linkPtr = Blt_ChainNewLink();
587 Blt_ChainSetValue(linkPtr, repPtr);
588 Blt_ChainLinkAfter(tedPtr->chainPtr, linkPtr, (Blt_ChainLink *)NULL);
589 return TCL_OK;
590 }
591
592 /*
593 * ----------------------------------------------------------------------------
594 *
595 * DestroyEntry --
596 *
597 * ----------------------------------------------------------------------------
598 */
599 static void
DestroyEntry(data)600 DestroyEntry(data)
601 DestroyData data;
602 {
603 EntryRep *repPtr = (EntryRep *)data;
604 Blt_ChainLink *linkPtr;
605 Entry *entryPtr;
606
607 for (linkPtr = Blt_ChainFirstLink(repPtr->tedPtr->chainPtr);
608 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
609 entryPtr = Blt_ChainGetValue(linkPtr);
610 if (entryPtr == repPtr->entryPtr) {
611 Blt_ChainDeleteLink(repPtr->tedPtr->chainPtr, linkPtr);
612 Blt_Free(repPtr);
613 return;
614 }
615 }
616 }
617
618 /*
619 * ----------------------------------------------------------------------------
620 *
621 * DisplayEntry --
622 *
623 * ----------------------------------------------------------------------------
624 */
625 static void
DisplayEntry(clientData)626 DisplayEntry(clientData)
627 ClientData clientData;
628 {
629 EntryRep *repPtr = (EntryRep *) clientData;
630 Ted *tedPtr;
631 Entry *entryPtr;
632 Tk_Window tkwin;
633 int x, y, width, height;
634
635 repPtr->flags &= ~REDRAW_PENDING;
636 if ((repPtr->tkwin == NULL) || (repPtr->entryPtr == NULL)) {
637 return;
638 }
639 if (!Tk_IsMapped(repPtr->tkwin)) {
640 return;
641 }
642 tedPtr = repPtr->tedPtr;
643 entryPtr = repPtr->entryPtr;
644 tkwin = repPtr->tkwin;
645
646 /*
647 * Check if the entry size and position.
648 * Move and resize the window accordingly.
649 */
650 x = Tk_X(entryPtr->tkwin) - (entryPtr->padLeft + tedPtr->cavityPad);
651 y = Tk_Y(entryPtr->tkwin) - (entryPtr->padTop + tedPtr->cavityPad);
652 width = Tk_Width(entryPtr->tkwin) + PADDING(entryPtr->padX) +
653 (2 * tedPtr->cavityPad);
654 height = Tk_Height(entryPtr->tkwin) + PADDING(entryPtr->padY) +
655 (2 * tedPtr->cavityPad);
656
657
658 if ((Tk_X(tkwin) != x) || (Tk_Y(tkwin) != y) ||
659 (Tk_Width(tkwin) != width) || (Tk_Height(tkwin) != height)) {
660 Tk_MoveResizeWindow(tkwin, x, y, width, height);
661 Tk_RestackWindow(tkwin, Above, (Tk_Window)NULL);
662 }
663 /* Clear the background of the entry */
664
665 XFillRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin),
666 tedPtr->attributes.fillGC, 0, 0, width, height);
667
668 /* Draw the window */
669
670 x = entryPtr->padLeft + tedPtr->cavityPad;
671 y = entryPtr->padTop + tedPtr->cavityPad;
672
673 XFillRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin),
674 tedPtr->attributes.widgetFillGC, x, y, Tk_Width(entryPtr->tkwin),
675 Tk_Height(entryPtr->tkwin));
676 XDrawRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin),
677 tedPtr->attributes.drawGC, x, y, Tk_Width(entryPtr->tkwin),
678 Tk_Height(entryPtr->tkwin));
679 }
680
681 /*
682 * ----------------------------------------------------------------------------
683 *
684 * FindEditor --
685 *
686 * Searches for a table associated with the window given by its
687 * pathname. This window represents the master window of the table.
688 *
689 * Errors may occur because
690 * 1) pathName does not represent a valid Tk window or
691 * 2) the window is not associated with any table as its master.
692 *
693 * Results:
694 * If a table entry exists, a pointer to the Table structure is
695 * returned. Otherwise NULL is returned.
696 *
697 * ----------------------------------------------------------------------------
698 */
699 static Ted *
FindEditor(clientData,interp,pathName)700 FindEditor(clientData, interp, pathName)
701 ClientData clientData; /* Thread-specific data. */
702 Tcl_Interp *interp; /* Interpreter to report errors back to */
703 char *pathName; /* Path name of the master window */
704 {
705 Table *tablePtr;
706
707 if (Blt_GetTable(clientData, interp, pathName, &tablePtr) != TCL_OK) {
708 return NULL;
709 }
710 if (tablePtr->editPtr == NULL) {
711 Tcl_AppendResult(interp, "no editor exists for table \"",
712 Tk_PathName(tablePtr->tkwin), "\"", (char *)NULL);
713 return NULL;
714 }
715 return (Ted *) tablePtr->editPtr;
716 }
717
718 /*
719 * ----------------------------------------------------------------------------
720 *
721 * CreateTed --
722 *
723 * ----------------------------------------------------------------------------
724 */
725 static Ted *
CreateTed(tablePtr,interp)726 CreateTed(tablePtr, interp)
727 Table *tablePtr;
728 Tcl_Interp *interp;
729 {
730 Ted *tedPtr;
731
732 tedPtr = Blt_Calloc(1, sizeof(Ted));
733 assert(tedPtr);
734 tedPtr->nextWindowId = 0;
735 tedPtr->interp = interp;
736 tedPtr->tablePtr = tablePtr;
737 tedPtr->gridLineWidth = 1;
738 tedPtr->buttonHeight = 0;
739 tedPtr->cavityPad = 0;
740 tedPtr->minSize = 3;
741 tedPtr->gripSize = 5;
742 tedPtr->drawProc = DrawEditor;
743 tedPtr->destroyProc = DestroyEditor;
744 tedPtr->display = Tk_Display(tablePtr->tkwin);
745 tedPtr->relief = TK_RELIEF_RAISED;
746 tedPtr->borderWidth = 2;
747 tedPtr->doubleBuffer = 1;
748 tedPtr->chainPtr = Blt_ChainCreate();
749 /* Create the grid window */
750
751 if (CreateGrid(tedPtr) != TCL_OK) {
752 return NULL;
753 }
754 /* Create an InputOnly window to collect user events */
755 if (CreateEventWindow(tedPtr) != TCL_OK) {
756 return NULL;
757 }
758 tablePtr->editPtr = (Editor *)tedPtr;
759 return tedPtr;
760 }
761
762 /*
763 * ----------------------------------------------------------------------------
764 *
765 * DestroyTed --
766 *
767 * ----------------------------------------------------------------------------
768 */
769 static void
DestroyTed(freeProcData)770 DestroyTed(freeProcData)
771 DestroyData freeProcData;
772 {
773 Ted *tedPtr = (Ted *) freeProcData;
774
775 if (tedPtr->rectArr != NULL) {
776 Blt_Free(tedPtr->rectArr);
777 }
778 if (tedPtr->segArr != NULL) {
779 Blt_Free(tedPtr->segArr);
780 }
781 if (tedPtr->fillGC != NULL) {
782 Tk_FreeGC(tedPtr->display, tedPtr->fillGC);
783 }
784 if (tedPtr->drawGC != NULL) {
785 Tk_FreeGC(tedPtr->display, tedPtr->drawGC);
786 }
787 if (tedPtr->rectGC != NULL) {
788 Tk_FreeGC(tedPtr->display, tedPtr->rectGC);
789 }
790 if (tedPtr->padRectGC != NULL) {
791 Tk_FreeGC(tedPtr->display, tedPtr->padRectGC);
792 }
793 /* Is this save ? */
794 tedPtr->tablePtr->editPtr = NULL;
795 Blt_Free(tedPtr);
796
797 }
798
799 /*
800 * ----------------------------------------------------------------------------
801 *
802 * ConfigureTed --
803 *
804 * This procedure is called to process an argv/argc list in order to
805 * configure the table geometry manager.
806 *
807 * Results:
808 * The return value is a standard Tcl result. If TCL_ERROR is
809 * returned, then interp->result contains an error message.
810 *
811 * Side effects:
812 * Table configuration options (padx, pady, rows, columns, etc) get
813 * set. The table is recalculated and arranged at the next idle
814 * point.
815 *
816 * ----------------------------------------------------------------------------
817 */
818 static int
ConfigureTed(tedPtr,argc,argv,flags)819 ConfigureTed(tedPtr, argc, argv, flags)
820 Ted *tedPtr;
821 int argc;
822 char **argv; /* Option-value pairs */
823 int flags;
824 {
825 XGCValues gcValues;
826 GC newGC;
827 unsigned long gcMask;
828
829 if (Tk_ConfigureWidget(tedPtr->interp, tedPtr->tkwin, configSpecs,
830 argc, argv, (char *)tedPtr, flags) != TCL_OK) {
831 return TCL_ERROR;
832 }
833 /* GC for filling background of edit window */
834
835 gcMask = GCForeground;
836 gcValues.foreground = tedPtr->normalBg->pixel;
837 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
838 if (tedPtr->fillGC != NULL) {
839 Tk_FreeGC(tedPtr->display, tedPtr->fillGC);
840 }
841 tedPtr->fillGC = newGC;
842
843 /* GC for drawing grid lines */
844
845 gcMask = (GCForeground | GCBackground | GCLineWidth | GCLineStyle |
846 GCCapStyle | GCJoinStyle | GCFont);
847 gcValues.font = Tk_FontId(tedPtr->font);
848 gcValues.foreground = tedPtr->gridColor->pixel;
849 gcValues.background = tedPtr->normalBg->pixel;
850 gcValues.line_width = LineWidth(tedPtr->gridLineWidth);
851 gcValues.cap_style = CapRound;
852 gcValues.join_style = JoinRound;
853 gcValues.line_style = LineSolid;
854 if (LineIsDashed(tedPtr->dashes)) {
855 gcValues.line_style = LineOnOffDash;
856 }
857 newGC = Blt_GetPrivateGC(tedPtr->tkwin, gcMask, &gcValues);
858 if (tedPtr->drawGC != NULL) {
859 Blt_FreePrivateGC(tedPtr->display, tedPtr->drawGC);
860 }
861 if (LineIsDashed(tedPtr->dashes)) {
862 XSetDashes(tedPtr->display, newGC, 0,
863 (CONST char *)tedPtr->dashes.values,
864 strlen((char *)tedPtr->dashes.values));
865 }
866 tedPtr->drawGC = newGC;
867
868 /* GC for button rectangles */
869
870 gcMask = GCForeground;
871 gcValues.foreground = tedPtr->buttonColor->pixel;
872 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
873 if (tedPtr->rectGC != NULL) {
874 Tk_FreeGC(tedPtr->display, tedPtr->rectGC);
875 }
876 tedPtr->rectGC = newGC;
877
878 /* GC for button rectangles */
879
880 gcMask = GCForeground;
881 gcValues.foreground = tedPtr->padColor->pixel;
882 if (tedPtr->padStipple != None) {
883 gcMask |= GCStipple | GCFillStyle;
884 gcValues.stipple = tedPtr->padStipple;
885 gcValues.fill_style = FillStippled;
886 }
887 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
888 if (tedPtr->padRectGC != NULL) {
889 Tk_FreeGC(tedPtr->display, tedPtr->padRectGC);
890 }
891 tedPtr->padRectGC = newGC;
892
893 /* GC for filling entrys */
894
895 gcMask = GCForeground;
896 gcValues.foreground = tedPtr->attributes.normalBg->pixel;
897 if (tedPtr->attributes.stipple != None) {
898 gcMask |= GCStipple | GCFillStyle;
899 gcValues.stipple = tedPtr->attributes.stipple;
900 gcValues.fill_style = FillStippled;
901 }
902 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
903 if (tedPtr->attributes.fillGC != NULL) {
904 Tk_FreeGC(tedPtr->display, tedPtr->attributes.fillGC);
905 }
906 tedPtr->attributes.fillGC = newGC;
907
908 /* GC for drawing entrys */
909
910 gcMask = GCForeground | GCBackground | GCFont;
911 gcValues.foreground = tedPtr->attributes.normalFg->pixel;
912 gcValues.background = tedPtr->attributes.normalBg->pixel;
913 gcValues.font = Tk_FontId(tedPtr->attributes.font);
914 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
915 if (tedPtr->attributes.drawGC != NULL) {
916 Blt_FreePrivateGC(tedPtr->display, tedPtr->attributes.drawGC);
917 }
918 tedPtr->attributes.drawGC = newGC;
919
920 /* GC for filling widget rectangles */
921
922 gcMask = GCForeground;
923 gcValues.foreground = tedPtr->attributes.widgetColor->pixel;
924 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
925 if (tedPtr->attributes.widgetFillGC != NULL) {
926 Tk_FreeGC(tedPtr->display, tedPtr->attributes.widgetFillGC);
927 }
928 tedPtr->attributes.widgetFillGC = newGC;
929
930 gcMask = GCForeground;
931 gcValues.foreground = tedPtr->attributes.cntlColor->pixel;
932 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
933 if (tedPtr->attributes.cntlGC != NULL) {
934 Tk_FreeGC(tedPtr->display, tedPtr->attributes.cntlGC);
935 }
936 tedPtr->attributes.cntlGC = newGC;
937
938 /* GC for filling span rectangle */
939
940 gcMask = GCForeground;
941 gcValues.foreground = tedPtr->spanColor->pixel;
942 if (tedPtr->spanStipple != None) {
943 gcMask |= GCStipple | GCFillStyle;
944 gcValues.stipple = tedPtr->spanStipple;
945 gcValues.fill_style = FillStippled;
946 }
947 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
948 if (tedPtr->spanGC != NULL) {
949 Tk_FreeGC(tedPtr->display, tedPtr->spanGC);
950 }
951 tedPtr->spanGC = newGC;
952
953 /* Define cursor for grid events */
954 if (tedPtr->cursor != None) {
955 Tk_DefineCursor(tedPtr->input, tedPtr->cursor);
956 } else {
957 Tk_UndefineCursor(tedPtr->input);
958 }
959 return TCL_OK;
960 }
961
962
963 static void
LayoutGrid(tedPtr)964 LayoutGrid(tedPtr)
965 Ted *tedPtr;
966 {
967 int needed;
968 XSegment *segArr;
969 Table *tablePtr;
970 Blt_ChainLink *linkPtr;
971 RowColumn *rcPtr;
972 int startX, endX;
973 int startY, endY;
974 int count;
975
976 tablePtr = tedPtr->tablePtr;
977 if (tedPtr->segArr != NULL) {
978 Blt_Free(tedPtr->segArr);
979 tedPtr->segArr = NULL;
980 }
981 tedPtr->nSegs = 0;
982 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
983 return;
984 }
985 needed = tablePtr->nRows + tablePtr->nColumns + 2;
986 segArr = Blt_Calloc(needed, sizeof(XSegment));
987 if (segArr == NULL) {
988 return;
989 }
990 linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
991 rcPtr = Blt_ChainGetValue(linkPtr);
992 startX = rcPtr->offset - tedPtr->gridLineWidth;
993
994 linkPtr = Blt_ChainLastLink(tablePtr->columnInfo.chainPtr);
995 rcPtr = Blt_ChainGetValue(linkPtr);
996 endX = rcPtr->offset + rcPtr->size - 1;
997
998 linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
999 rcPtr = Blt_ChainGetValue(linkPtr);
1000 startY = rcPtr->offset - tedPtr->gridLineWidth;
1001
1002 linkPtr = Blt_ChainLastLink(tablePtr->rowInfo.chainPtr);
1003 rcPtr = Blt_ChainGetValue(linkPtr);
1004 endY = rcPtr->offset + rcPtr->size - 1;
1005
1006 count = 0; /* Reset segment counter */
1007
1008 for (linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1009 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1010 rcPtr = Blt_ChainGetValue(linkPtr);
1011 segArr[count].x1 = startX;
1012 segArr[count].x2 = endX;
1013 segArr[count].y1 = segArr[count].y2 = rcPtr->offset -
1014 tedPtr->gridLineWidth;
1015 count++;
1016 }
1017 segArr[count].x1 = startX;
1018 segArr[count].x2 = endX;
1019 segArr[count].y1 = segArr[count].y2 = endY;
1020 count++;
1021
1022 for (linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1023 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1024 rcPtr = Blt_ChainGetValue(linkPtr);
1025 segArr[count].y1 = startY;
1026 segArr[count].y2 = endY;
1027 segArr[count].x1 = segArr[count].x2 = rcPtr->offset -
1028 tedPtr->gridLineWidth;
1029 count++;
1030 }
1031 segArr[count].x1 = segArr[count].x2 = endX;
1032 segArr[count].y1 = startY;
1033 segArr[count].y2 = endY;
1034 count++;
1035 assert(count == needed);
1036 if (tedPtr->segArr != NULL) {
1037 Blt_Free(tedPtr->segArr);
1038 }
1039 tedPtr->segArr = segArr;
1040 tedPtr->nSegs = count;
1041 }
1042
1043
1044 static void
LayoutPads(tedPtr)1045 LayoutPads(tedPtr)
1046 Ted *tedPtr;
1047 {
1048 int needed;
1049 XRectangle *rectArr, *rectPtr;
1050 Table *tablePtr;
1051 Blt_ChainLink *linkPtr;
1052 RowColumn *rcPtr;
1053 int startX, endX;
1054 int startY, endY;
1055 int count;
1056
1057 tablePtr = tedPtr->tablePtr;
1058 if (tedPtr->padRectArr != NULL) {
1059 Blt_Free(tedPtr->padRectArr);
1060 tedPtr->padRectArr = NULL;
1061 }
1062 tedPtr->nPadRects = 0;
1063 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
1064 return;
1065 }
1066 needed = 2 * (tablePtr->nRows + tablePtr->nColumns);
1067 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1068 if (rectArr == NULL) {
1069 return;
1070 }
1071 linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1072 rcPtr = Blt_ChainGetValue(linkPtr);
1073 startX = rcPtr->offset;
1074
1075 linkPtr = Blt_ChainLastLink(tablePtr->columnInfo.chainPtr);
1076 rcPtr = Blt_ChainGetValue(linkPtr);
1077 endX = (rcPtr->offset + rcPtr->size);
1078
1079 linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1080 rcPtr = Blt_ChainGetValue(linkPtr);
1081 startY = rcPtr->offset;
1082
1083 linkPtr = Blt_ChainLastLink(tablePtr->rowInfo.chainPtr);
1084 rcPtr = Blt_ChainGetValue(linkPtr);
1085 endY = (rcPtr->offset + rcPtr->size);
1086
1087 count = 0; /* Reset segment counter */
1088 rectPtr = rectArr;
1089 for (linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1090 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1091 rcPtr = Blt_ChainGetValue(linkPtr);
1092 if (rcPtr->pad.side1 > 0) {
1093 rectPtr->x = startX;
1094 rectPtr->y = rcPtr->offset;
1095 rectPtr->height = rcPtr->pad.side1;
1096 rectPtr->width = endX - startX - 1;
1097 rectPtr++, count++;
1098 }
1099 if (rcPtr->pad.side2 > 0) {
1100 rectPtr->x = startX;
1101 rectPtr->y = rcPtr->offset + rcPtr->size - rcPtr->pad.side2 - 1;
1102 rectPtr->height = rcPtr->pad.side2;
1103 rectPtr->width = endX - startX - 1;
1104 rectPtr++, count++;
1105 }
1106 }
1107 for (linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1108 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1109 rcPtr = Blt_ChainGetValue(linkPtr);
1110 if (rcPtr->pad.side1 > 0) {
1111 rectPtr->x = rcPtr->offset;
1112 rectPtr->y = startY;
1113 rectPtr->height = endY - startY - 1;
1114 rectPtr->width = rcPtr->pad.side1;
1115 rectPtr++, count++;
1116 }
1117 if (rcPtr->pad.side2 > 0) {
1118 rectPtr->x = rcPtr->offset + rcPtr->size - rcPtr->pad.side2;
1119 rectPtr->y = startY;
1120 rectPtr->height = endY - startY - 1;
1121 rectPtr->width = rcPtr->pad.side2;
1122 rectPtr++, count++;
1123 }
1124 }
1125 if (count == 0) {
1126 Blt_Free(rectArr);
1127 return;
1128 }
1129 tedPtr->padRectArr = rectArr;
1130 tedPtr->nPadRects = count;
1131 }
1132
1133 static void
LayoutEntries(tedPtr)1134 LayoutEntries(tedPtr)
1135 Ted *tedPtr;
1136 {
1137 Entry *entryPtr;
1138 XRectangle *rectArr;
1139 int needed;
1140 int count;
1141 Blt_ChainLink *linkPtr;
1142
1143 if (tedPtr->widgetPadRectArr != NULL) {
1144 Blt_Free(tedPtr->widgetPadRectArr);
1145 tedPtr->widgetPadRectArr = NULL;
1146 }
1147 tedPtr->nWidgetPadRects = 0;
1148
1149 needed = Blt_ChainGetLength(tedPtr->tablePtr->chainPtr);
1150 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1151 if (rectArr == NULL) {
1152 return;
1153 }
1154 /* Draw any entry windows */
1155 count = 0;
1156 for (linkPtr = Blt_ChainFirstLink(tedPtr->tablePtr->chainPtr);
1157 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1158 entryPtr = Blt_ChainGetValue(linkPtr);
1159 if ((PADDING(entryPtr->padX) + PADDING(entryPtr->padY)) == 0) {
1160 continue;
1161 }
1162 rectArr[count].x = Tk_X(entryPtr->tkwin) - entryPtr->padLeft;
1163 rectArr[count].y = Tk_Y(entryPtr->tkwin) - entryPtr->padTop;
1164 rectArr[count].width = Tk_Width(entryPtr->tkwin) +
1165 PADDING(entryPtr->padX);
1166 rectArr[count].height = Tk_Height(entryPtr->tkwin) +
1167 PADDING(entryPtr->padY);
1168 count++;
1169 }
1170 if (count == 0) {
1171 Blt_Free(rectArr);
1172 return;
1173 }
1174 tedPtr->widgetPadRectArr = rectArr;
1175 tedPtr->nWidgetPadRects = count;
1176 }
1177
1178 static void
LayoutControlEntries(tedPtr)1179 LayoutControlEntries(tedPtr)
1180 Ted *tedPtr;
1181 {
1182 Entry *entryPtr;
1183 XRectangle *rectArr;
1184 int needed;
1185 int count;
1186 Table *tablePtr = tedPtr->tablePtr;
1187 Blt_ChainLink *linkPtr;
1188 RowColumn *rcPtr;
1189
1190 if (tedPtr->cntlRectArr != NULL) {
1191 Blt_Free(tedPtr->cntlRectArr);
1192 tedPtr->cntlRectArr = NULL;
1193 }
1194 tedPtr->nCntlRects = 0;
1195
1196 needed = (tablePtr->nRows + tablePtr->nColumns);
1197 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1198 if (rectArr == NULL) {
1199 return;
1200 }
1201 /* Draw any entry windows */
1202 count = 0;
1203 for (linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1204 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1205 rcPtr = Blt_ChainGetValue(linkPtr);
1206 entryPtr = rcPtr->control;
1207 if (entryPtr != NULL) {
1208 rectArr[count].x = Tk_X(entryPtr->tkwin) - entryPtr->padLeft;
1209 rectArr[count].y = Tk_Y(entryPtr->tkwin) - entryPtr->padTop;
1210 rectArr[count].width = Tk_Width(entryPtr->tkwin) +
1211 PADDING(entryPtr->padX);
1212 rectArr[count].height = Tk_Height(entryPtr->tkwin) +
1213 PADDING(entryPtr->padY);
1214 count++;
1215 }
1216 }
1217 for (linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1218 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1219 rcPtr = Blt_ChainGetValue(linkPtr);
1220 entryPtr = rcPtr->control;
1221 if (entryPtr != NULL) {
1222 rectArr[count].x = Tk_X(entryPtr->tkwin) - entryPtr->padLeft;
1223 rectArr[count].y = Tk_Y(entryPtr->tkwin) - entryPtr->padTop;
1224 rectArr[count].width = Tk_Width(entryPtr->tkwin) +
1225 PADDING(entryPtr->padX);
1226 rectArr[count].height = Tk_Height(entryPtr->tkwin) +
1227 PADDING(entryPtr->padY);
1228 count++;
1229 }
1230 }
1231 if (count == 0) {
1232 Blt_Free(rectArr);
1233 return;
1234 }
1235 tedPtr->cntlRectArr = rectArr;
1236 tedPtr->nCntlRects = count;
1237 }
1238
1239 static void
LayoutButtons(tedPtr)1240 LayoutButtons(tedPtr)
1241 Ted *tedPtr;
1242 {
1243 int needed;
1244 XRectangle *rectArr;
1245 Table *tablePtr;
1246 Blt_ChainLink *linkPtr;
1247 RowColumn *rcPtr;
1248 int count;
1249
1250 tablePtr = tedPtr->tablePtr;
1251 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
1252 if (tedPtr->rectArr != NULL) {
1253 Blt_Free(tedPtr->rectArr);
1254 }
1255 tedPtr->rectArr = NULL;
1256 tedPtr->nRects = 0;
1257 return; /* Nothing to display, empty table */
1258 }
1259 needed = 2 * (tablePtr->nRows + tablePtr->nColumns);
1260 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1261 if (rectArr == NULL) {
1262 return; /* Can't allocate rectangles */
1263 }
1264 count = 0;
1265 for (linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1266 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1267 rcPtr = Blt_ChainGetValue(linkPtr);
1268 rectArr[count].x = 0;
1269 rectArr[count].y = rcPtr->offset - rcPtr->pad.side1;
1270 rectArr[count].width = tedPtr->buttonHeight;
1271 rectArr[count].height = rcPtr->size - 2;
1272 count++;
1273 rectArr[count].x = Tk_Width(tedPtr->tkwin) - tedPtr->buttonHeight;
1274 rectArr[count].y = rcPtr->offset - rcPtr->pad.side1;
1275 rectArr[count].width = tedPtr->buttonHeight;
1276 rectArr[count].height = rcPtr->size - 2;
1277 count++;
1278 }
1279 for (linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1280 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1281 rcPtr = Blt_ChainGetValue(linkPtr);
1282 rectArr[count].x = rcPtr->offset - rcPtr->pad.side1;
1283 rectArr[count].y = 0;
1284 rectArr[count].width = rcPtr->size - 2;
1285 rectArr[count].height = tedPtr->buttonHeight;
1286 count++;
1287 rectArr[count].x = rcPtr->offset - rcPtr->pad.side1;
1288 rectArr[count].y = Tk_Height(tedPtr->tkwin) - tedPtr->buttonHeight;
1289 rectArr[count].width = rcPtr->size - 2;
1290 rectArr[count].height = tedPtr->buttonHeight;
1291 count++;
1292 }
1293 assert(count == needed);
1294 if (tedPtr->rectArr != NULL) {
1295 Blt_Free(tedPtr->rectArr);
1296 }
1297 tedPtr->rectArr = rectArr;
1298 tedPtr->nRects = count;
1299 }
1300
1301
1302 static void
DisplayTed(clientData)1303 DisplayTed(clientData)
1304 ClientData clientData;
1305 {
1306 Ted *tedPtr = (Ted *) clientData;
1307 Tk_Window master;
1308 Tk_Window tkwin;
1309 Blt_ChainLink *linkPtr;
1310 EntryRep *repPtr;
1311 Drawable drawable;
1312 Pixmap pixmap;
1313
1314 #ifdef notdef
1315 fprintf(stderr, "display grid\n");
1316 #endif
1317 tedPtr->flags &= ~REDRAW_PENDING;
1318 if (!Tk_IsMapped(tedPtr->tkwin)) {
1319 return;
1320 }
1321 /*
1322 * Check if the master window has changed size and resize the
1323 * grid and input windows accordingly.
1324 */
1325 master = tedPtr->tablePtr->tkwin;
1326 if ((Tk_Width(master) != Tk_Width(tedPtr->tkwin)) ||
1327 (Tk_Height(master) != Tk_Height(tedPtr->tkwin))) {
1328 #ifdef notdef
1329 fprintf(stderr, "resizing windows\n");
1330 #endif
1331 Tk_ResizeWindow(tedPtr->tkwin, Tk_Width(master), Tk_Height(master));
1332 Tk_ResizeWindow(tedPtr->input, Tk_Width(master), Tk_Height(master));
1333 if (tedPtr->inputIsSibling) {
1334 Tk_MoveWindow(tedPtr->input, Tk_X(master), Tk_X(master));
1335 }
1336 tedPtr->flags |= LAYOUT_PENDING;
1337 }
1338 if (tedPtr->flags & LAYOUT_PENDING) {
1339 #ifdef notdef
1340 fprintf(stderr, "layout of grid\n");
1341 #endif
1342 LayoutPads(tedPtr);
1343 LayoutEntries(tedPtr);
1344 LayoutControlEntries(tedPtr);
1345 LayoutGrid(tedPtr);
1346 LayoutButtons(tedPtr);
1347 tedPtr->flags &= ~LAYOUT_PENDING;
1348 }
1349 tkwin = tedPtr->tkwin;
1350
1351 pixmap = None; /* Suppress compiler warning. */
1352 drawable = Tk_WindowId(tkwin);
1353 if (tedPtr->doubleBuffer) {
1354 /* Create an off-screen pixmap for semi-smooth scrolling. */
1355 pixmap = Tk_GetPixmap(tedPtr->display, Tk_WindowId(tkwin),
1356 Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
1357 drawable = pixmap;
1358 }
1359 /* Clear the background of the grid */
1360
1361 XFillRectangle(Tk_Display(tkwin), drawable, tedPtr->fillGC, 0, 0,
1362 Tk_Width(tkwin), Tk_Height(tkwin));
1363
1364 /* Draw the row and column buttons */
1365
1366 if (tedPtr->nRects > 0) {
1367 int i;
1368
1369 for (i = 0; i < tedPtr->nRects; i++) {
1370 Blt_Fill3DRectangle(tkwin, drawable, tedPtr->border,
1371 tedPtr->rectArr[i].x, tedPtr->rectArr[i].y,
1372 tedPtr->rectArr[i].width, tedPtr->rectArr[i].height,
1373 tedPtr->borderWidth, tedPtr->relief);
1374 }
1375 #ifdef notdef
1376 XFillRectangles(tedPtr->display, drawable, tedPtr->rectGC,
1377 tedPtr->rectArr, tedPtr->nRects);
1378 XDrawRectangles(tedPtr->display, drawable, tedPtr->drawGC,
1379 tedPtr->rectArr, tedPtr->nRects);
1380 #endif
1381 }
1382 if (tedPtr->nPadRects > 0) {
1383 XFillRectangles(tedPtr->display, drawable, tedPtr->padRectGC,
1384 tedPtr->padRectArr, tedPtr->nPadRects);
1385 }
1386 if (tedPtr->spanActive) {
1387 XFillRectangles(tedPtr->display, drawable, tedPtr->spanGC,
1388 tedPtr->activeRectArr, 1);
1389 XFillRectangles(tedPtr->display, drawable, tedPtr->drawGC,
1390 tedPtr->activeRectArr + 1, 4);
1391 }
1392 if (tedPtr->nWidgetPadRects > 0) {
1393 XFillRectangles(tedPtr->display, drawable, tedPtr->attributes.fillGC,
1394 tedPtr->widgetPadRectArr, tedPtr->nWidgetPadRects);
1395 }
1396 if (tedPtr->nCntlRects > 0) {
1397 XFillRectangles(tedPtr->display, drawable, tedPtr->attributes.cntlGC,
1398 tedPtr->cntlRectArr, tedPtr->nCntlRects);
1399 }
1400 /* Draw the grid lines */
1401 if (tedPtr->nSegs > 0) {
1402 XDrawSegments(tedPtr->display, drawable, tedPtr->drawGC,
1403 tedPtr->segArr, tedPtr->nSegs);
1404 }
1405 #ifndef notdef
1406 /* Draw any entry windows */
1407 for (linkPtr = Blt_ChainFirstLink(tedPtr->chainPtr); linkPtr != NULL;
1408 linkPtr = Blt_ChainNextLink(linkPtr)) {
1409 repPtr = Blt_ChainGetValue(linkPtr);
1410 if (repPtr->mapped) {
1411 DisplayEntry(repPtr);
1412 }
1413 }
1414 #endif
1415 if (tedPtr->doubleBuffer) {
1416 XCopyArea(tedPtr->display, drawable, Tk_WindowId(tkwin), tedPtr->fillGC,
1417 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, 0);
1418 Tk_FreePixmap(tedPtr->display, pixmap);
1419 }
1420 }
1421
1422
1423 static void
DrawEditor(editPtr)1424 DrawEditor(editPtr)
1425 Editor *editPtr;
1426 {
1427 Ted *tedPtr = (Ted *) editPtr;
1428
1429 tedPtr->flags |= LAYOUT_PENDING;
1430 if ((tedPtr->tkwin != NULL) && !(tedPtr->flags & REDRAW_PENDING)) {
1431 tedPtr->flags |= REDRAW_PENDING;
1432 #ifdef notdef
1433 fprintf(stderr, "from draw editor\n");
1434 #endif
1435 Tcl_DoWhenIdle(DisplayTed, tedPtr);
1436 }
1437 }
1438
1439 static void
DestroyEditor(destroyData)1440 DestroyEditor(destroyData)
1441 DestroyData destroyData;
1442 {
1443 Ted *tedPtr = (Ted *) destroyData;
1444
1445 tedPtr->tkwin = NULL;
1446 if (tedPtr->flags & REDRAW_PENDING) {
1447 Tcl_CancelIdleCall(DisplayTed, tedPtr);
1448 }
1449 Tcl_EventuallyFree(tedPtr, DestroyTed);
1450 }
1451
1452 /*
1453 * ----------------------------------------------------------------------------
1454 *
1455 * EditOp --
1456 *
1457 * Processes an argv/argc list of table entries to add and configure
1458 * new widgets into the table. A table entry consists of the
1459 * window path name, table index, and optional configuration options.
1460 * The first argument in the argv list is the name of the table. If
1461 * no table exists for the given window, a new one is created.
1462 *
1463 * Results:
1464 * Returns a standard Tcl result. If an error occurred, TCL_ERROR is
1465 * returned and an error message is left in interp->result.
1466 *
1467 * Side Effects:
1468 * Memory is allocated, a new master table is possibly created, etc.
1469 * The table is re-computed and arranged at the next idle point.
1470 *
1471 * ----------------------------------------------------------------------------
1472 */
1473 static int
EditOp(dataPtr,interp,argc,argv)1474 EditOp(dataPtr, interp, argc, argv)
1475 TableInterpData *dataPtr; /* Interpreter-specific data. */
1476 Tcl_Interp *interp; /* Interpreter to return list of names to */
1477 int argc; /* Number of arguments */
1478 char **argv;
1479 {
1480 Table *tablePtr;
1481 Ted *tedPtr;
1482
1483 if (Blt_GetTable(dataPtr, interp, argv[2], &tablePtr) != TCL_OK) {
1484 return TCL_ERROR;
1485 }
1486 if (tablePtr->editPtr != NULL) { /* Already editing this table */
1487 tedPtr = (Ted *) tablePtr->editPtr;
1488 } else {
1489 tedPtr = CreateTed(tablePtr, interp);
1490 if (tedPtr == NULL) {
1491 return TCL_ERROR;
1492 }
1493 }
1494 if (ConfigureTed(tedPtr, argc - 3, argv + 3, 0) != TCL_OK) {
1495 tedPtr->tkwin = NULL;
1496 if (tedPtr->flags & REDRAW_PENDING) {
1497 Tcl_CancelIdleCall(DisplayTed, tedPtr);
1498 }
1499 Tcl_EventuallyFree(tedPtr, DestroyTed);
1500 return TCL_ERROR;
1501 }
1502 /* Rearrange the table */
1503 if (!(tablePtr->flags & ARRANGE_PENDING)) {
1504 tablePtr->flags |= ARRANGE_PENDING;
1505 Tcl_DoWhenIdle(tablePtr->arrangeProc, tablePtr);
1506 }
1507 Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tedPtr->tkwin), -1));
1508 tedPtr->flags |= LAYOUT_PENDING;
1509 EventuallyRedraw(tedPtr);
1510 return TCL_OK;
1511 }
1512
1513 /*
1514 * ----------------------------------------------------------------------------
1515 *
1516 * CgetCmd --
1517 *
1518 * Results:
1519 * The return value is a standard Tcl result. If TCL_ERROR is
1520 * returned, then interp->result contains an error message.
1521 *
1522 * ----------------------------------------------------------------------------
1523 */
1524 /*ARGSUSED*/
1525 static int
CgetOp(dataPtr,interp,argc,argv)1526 CgetOp(dataPtr, interp, argc, argv)
1527 TableInterpData *dataPtr; /* Interpreter-specific data. */
1528 Tcl_Interp *interp; /* Interpreter to report results back to */
1529 int argc; /* Not used. */
1530 char **argv; /* Option-value pairs */
1531 {
1532 Ted *tedPtr;
1533
1534 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1535 if (tedPtr == NULL) {
1536 return TCL_ERROR;
1537 }
1538 return Tk_ConfigureValue(interp, tedPtr->tkwin, configSpecs,
1539 (char *)tedPtr, argv[3], 0);
1540 }
1541
1542 /*
1543 * ----------------------------------------------------------------------------
1544 *
1545 * ConfigureCmd --
1546 *
1547 * This procedure is called to process an argv/argc list in order to
1548 * configure the table geometry manager.
1549 *
1550 * Results:
1551 * The return value is a standard Tcl result. If TCL_ERROR is
1552 * returned, then interp->result contains an error message.
1553 *
1554 * Side effects:
1555 * Table configuration options (padx, pady, rows, columns, etc) get
1556 * set. The table is recalculated and arranged at the next idle
1557 * point.
1558 *
1559 * ----------------------------------------------------------------------------
1560 */
1561 static int
ConfigureOp(dataPtr,interp,argc,argv)1562 ConfigureOp(dataPtr, interp, argc, argv)
1563 TableInterpData *dataPtr; /* Interpreter-specific data. */
1564 Tcl_Interp *interp; /* Interpreter to report results back to */
1565 int argc;
1566 char **argv; /* Option-value pairs */
1567 {
1568 Ted *tedPtr;
1569
1570 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1571 if (tedPtr == NULL) {
1572 return TCL_ERROR;
1573 }
1574 if (argc == 3) {
1575 return Tk_ConfigureInfo(interp, tedPtr->tkwin, configSpecs,
1576 (char *)tedPtr, (char *)NULL, 0);
1577 } else if (argc == 4) {
1578 return Tk_ConfigureInfo(interp, tedPtr->tkwin, configSpecs,
1579 (char *)tedPtr, argv[3], 0);
1580 }
1581 if (ConfigureTed(tedPtr, argc - 3, argv + 3,
1582 TK_CONFIG_ARGV_ONLY) != TCL_OK) {
1583 return TCL_ERROR;
1584 }
1585 EventuallyRedraw(tedPtr);
1586 return TCL_OK;
1587 }
1588
1589 /*
1590 * ----------------------------------------------------------------------------
1591 *
1592 * SelectOp --
1593 *
1594 * ----------------------------------------------------------------------------
1595 */
1596 /*ARGSUSED*/
1597 static int
SelectOp(dataPtr,interp,argc,argv)1598 SelectOp(dataPtr, interp, argc, argv)
1599 TableInterpData *dataPtr; /* Interpreter-specific data. */
1600 Tcl_Interp *interp; /* Interpreter to return list of names to */
1601 int argc; /* Not used. */
1602 char **argv;
1603 {
1604 Table *tablePtr;
1605 Ted *tedPtr;
1606 Entry *entryPtr;
1607 int active;
1608 int x, y, width, height;
1609 int ix, iy;
1610 Blt_ChainLink *linkPtr;
1611 Tk_Window tkwin;
1612
1613 /* ted select master @x,y */
1614 tkwin = Tk_MainWindow(interp);
1615 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1616 if (tedPtr == NULL) {
1617 return TCL_ERROR;
1618 }
1619 if (Blt_GetXY(interp, tkwin, argv[3], &ix, &iy) != TCL_OK) {
1620 return TCL_ERROR;
1621 }
1622 tablePtr = tedPtr->tablePtr;
1623 active = 0;
1624 for (linkPtr = Blt_ChainFirstLink(tablePtr->chainPtr);
1625 linkPtr != NULL; linkPtr = Blt_ChainNextLink(linkPtr)) {
1626 entryPtr = Blt_ChainGetValue(linkPtr);
1627 x = entryPtr->x - entryPtr->padX.side1;
1628 y = entryPtr->y - entryPtr->padY.side1;
1629 width = Tk_Width(entryPtr->tkwin) + PADDING(entryPtr->padX);
1630 height = Tk_Height(entryPtr->tkwin) + PADDING(entryPtr->padY);
1631 if ((ix >= x) && (ix <= (x + width)) &&
1632 (iy >= y) && (iy <= (y + height))) {
1633 int left, right, top, bottom;
1634 int last;
1635 int grip;
1636 RowColumn *rcPtr;
1637
1638 last = entryPtr->column.rcPtr->index + entryPtr->column.span - 1;
1639 linkPtr = Blt_ChainGetNthLink(tablePtr->columnInfo.chainPtr, last);
1640 rcPtr = Blt_ChainGetValue(linkPtr);
1641
1642 /* Calculate the span rectangle */
1643 left = (entryPtr->column.rcPtr->offset -
1644 entryPtr->column.rcPtr->pad.side1);
1645 right = (rcPtr->offset - rcPtr->pad.side1) + rcPtr->size;
1646
1647 top = (entryPtr->row.rcPtr->offset -
1648 entryPtr->row.rcPtr->pad.side1);
1649
1650 last = entryPtr->row.rcPtr->index + entryPtr->row.span - 1;
1651 linkPtr = Blt_ChainGetNthLink(tablePtr->rowInfo.chainPtr, last);
1652 rcPtr = Blt_ChainGetValue(linkPtr);
1653 bottom = (rcPtr->offset - rcPtr->pad.side1) + rcPtr->size;
1654
1655 tedPtr->activeRectArr[0].x = left;
1656 tedPtr->activeRectArr[0].y = top;
1657 tedPtr->activeRectArr[0].width = (right - left);
1658 tedPtr->activeRectArr[0].height = (bottom - top);
1659
1660 grip = tedPtr->gripSize;
1661 tedPtr->activeRectArr[1].x = (left + right - grip) / 2;
1662 tedPtr->activeRectArr[1].y = top;
1663 tedPtr->activeRectArr[1].width = grip - 1;
1664 tedPtr->activeRectArr[1].height = grip - 1;
1665
1666 tedPtr->activeRectArr[2].x = left;
1667 tedPtr->activeRectArr[2].y = (top + bottom - grip) / 2;
1668 tedPtr->activeRectArr[2].width = grip - 1;
1669 tedPtr->activeRectArr[2].height = grip - 1;
1670
1671 tedPtr->activeRectArr[3].x = (left + right - grip) / 2;
1672 tedPtr->activeRectArr[3].y = bottom - grip;
1673 tedPtr->activeRectArr[3].width = grip - 1;
1674 tedPtr->activeRectArr[3].height = grip - 1;
1675
1676 tedPtr->activeRectArr[4].x = right - grip;
1677 tedPtr->activeRectArr[4].y = (top + bottom - grip) / 2;
1678 tedPtr->activeRectArr[4].width = grip - 1;
1679 tedPtr->activeRectArr[4].height = grip - 1;
1680
1681 Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(entryPtr->tkwin), -1));
1682 active = 1;
1683 break;
1684 }
1685 }
1686 if ((active) || (active != tedPtr->spanActive)) {
1687 tedPtr->spanActive = active;
1688 EventuallyRedraw(tedPtr);
1689 }
1690 return TCL_OK;
1691 }
1692
1693 /*
1694 * ----------------------------------------------------------------------------
1695 *
1696 * EditOp --
1697 *
1698 * Processes an argv/argc list of table entries to add and configure
1699 * new widgets into the table. A table entry consists of the
1700 * window path name, table index, and optional configuration options.
1701 * The first argument in the argv list is the name of the table. If
1702 * no table exists for the given window, a new one is created.
1703 *
1704 * Results:
1705 * Returns a standard Tcl result. If an error occurred, TCL_ERROR is
1706 * returned and an error message is left in interp->result.
1707 *
1708 * Side Effects:
1709 * Memory is allocated, a new master table is possibly created, etc.
1710 * The table is re-computed and arranged at the next idle point.
1711 *
1712 * ----------------------------------------------------------------------------
1713 */
1714 static int
RepOp(dataPtr,interp,argc,argv)1715 RepOp(dataPtr, interp, argc, argv)
1716 TableInterpData *dataPtr; /* Interpreter-specific data. */
1717 Tcl_Interp *interp; /* Interpreter to return list of names to */
1718 int argc; /* Number of arguments */
1719 char **argv;
1720 {
1721 Tk_Window tkwin;
1722 Table *tablePtr;
1723 Ted *tedPtr;
1724
1725 /* ted rep master index */
1726 tkwin = Tk_NameToWindow(interp, argv[3], Tk_MainWindow(interp));
1727 if (tkwin == NULL) {
1728 return TCL_ERROR;
1729 }
1730 if (Blt_GetTable(dataPtr, interp, argv[2], &tablePtr) != TCL_OK) {
1731 return TCL_ERROR;
1732 }
1733 if (tablePtr->editPtr != NULL) { /* Already editing this table */
1734 tedPtr = (Ted *) tablePtr->editPtr;
1735 } else {
1736 tedPtr = CreateTed(tablePtr, interp);
1737 if (tedPtr == NULL) {
1738 return TCL_ERROR;
1739 }
1740 }
1741 if (ConfigureTed(tedPtr, argc - 3, argv + 3, 0) != TCL_OK) {
1742 tedPtr->tkwin = NULL;
1743 if (tedPtr->flags & REDRAW_PENDING) {
1744 Tcl_CancelIdleCall(DisplayTed, tedPtr);
1745 }
1746 Tcl_EventuallyFree(tedPtr, DestroyTed);
1747 return TCL_ERROR;
1748 }
1749 /* Rearrange the table */
1750 if (!(tablePtr->flags & ARRANGE_PENDING)) {
1751 tablePtr->flags |= ARRANGE_PENDING;
1752 Tcl_DoWhenIdle(tablePtr->arrangeProc, tablePtr);
1753 }
1754 Tcl_SetObjResult(interp, Tcl_NewStringObj(Tk_PathName(tedPtr->tkwin), -1));
1755 tedPtr->flags |= LAYOUT_PENDING;
1756 EventuallyRedraw(tedPtr);
1757 return TCL_OK;
1758 }
1759
1760 /*
1761 * ----------------------------------------------------------------------------
1762 *
1763 * Command options for the table editor.
1764 *
1765 * The fields for Blt_OperSpec are as follows:
1766 *
1767 * - option name
1768 * - minimum number of characters required to disambiguate the option name.
1769 * - function associated with command option.
1770 * - minimum number of arguments required.
1771 * - maximum number of arguments allowed (0 indicates no limit).
1772 * - usage string
1773 *
1774 * ----------------------------------------------------------------------------
1775 */
1776 static Blt_OpSpec opSpecs[] =
1777 {
1778 {"cget", 2, (Blt_Op)CgetOp, 4, 4, "master option",},
1779 {"configure", 2, (Blt_Op)ConfigureOp, 3, 0,
1780 "master ?option...?",},
1781 {"edit", 1, (Blt_Op)EditOp, 3, 0, "master ?options...?",},
1782 {"rep", 1, (Blt_Op)RepOp, 2, 0, "master index ?options...?",},
1783 {"select", 1, (Blt_Op)SelectOp, 4, 0, "master @x,y",},
1784 /* {"forget", 1, (Blt_Op)ForgetOp, 3, 0, "master ?master...?",},
1785 {"index", 1, (Blt_Op)IndexOp, 3, 0, "master ?item...?",}, */
1786 };
1787 static int nSpecs = sizeof(opSpecs) / sizeof(Blt_OpSpec);
1788
1789 /*
1790 * ----------------------------------------------------------------------------
1791 *
1792 * TedCmd --
1793 *
1794 * This procedure is invoked to process the Tcl command that
1795 * corresponds to the table geometry manager. See the user
1796 * documentation for details on what it does.
1797 *
1798 * Results:
1799 * A standard Tcl result.
1800 *
1801 * Side effects:
1802 * See the user documentation.
1803 *
1804 * ----------------------------------------------------------------------------
1805 */
1806 static int
TedCmd(clientData,interp,argc,argv)1807 TedCmd(clientData, interp, argc, argv)
1808 ClientData clientData; /* Thread-specific data. */
1809 Tcl_Interp *interp;
1810 int argc;
1811 char **argv;
1812 {
1813 Blt_Op proc;
1814 int result;
1815
1816 proc = Blt_GetOp(interp, nSpecs, opSpecs, BLT_OP_ARG1, argc, argv, 0);
1817 if (proc == NULL) {
1818 return TCL_ERROR;
1819 }
1820 result = (*proc) (clientData, interp, argc, argv);
1821 return result;
1822 }
1823
1824 static TableData *
GetTableInterpData(interp)1825 GetTableInterpData(interp)
1826 Tcl_Interp *interp;
1827 {
1828 TableData *dataPtr;
1829 Tcl_InterpDeleteProc *proc;
1830
1831 dataPtr = (TableData *)Tcl_GetAssocData(interp, TABLE_THREAD_KEY, &proc);
1832 assert(dataPtr);
1833 return dataPtr;
1834 }
1835
1836 /*
1837 * ----------------------------------------------------------------------------
1838 *
1839 * Blt_TedInit --
1840 *
1841 * This procedure is invoked to initialize the Tcl command that
1842 * corresponds to the table geometry manager.
1843 *
1844 * Results:
1845 * None.
1846 *
1847 * Side effects:
1848 * Creates the new command and adds an entry into a global Tcl
1849 * associative array.
1850 *
1851 * ---------------------------------------------------------------------------
1852 */
1853 int
Blt_TedInit(interp)1854 Blt_TedInit(interp)
1855 Tcl_Interp *interp;
1856 {
1857 static Blt_CmdSpec cmdSpec = {"ted", TedCmd, };
1858 TableData *dataPtr;
1859
1860 dataPtr = GetTableInterpData(interp);
1861 cmdSpec.clientData = dataPtr;
1862 if (Blt_InitCmd(interp, "blt", &cmdSpec) == NULL) {
1863 return TCL_ERROR;
1864 }
1865 return TCL_OK;
1866 }
1867