4 * This module implements an editor for the table geometry
5 * manager in the BLT toolkit.
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.
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.
25 * Table editor was created by George Howlett.
32 extern Tk_CustomOption bltDistanceOption;
33 extern Tk_CustomOption bltDashesOption;
35 typedef struct TedStruct Ted;
37 #define TABLE_THREAD_KEY "BLT Table Data"
40 Blt_HashTable tableTable; /* Hash table of table structures keyed by
41 * the address of the reference Tk window */
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
61 XColor *normalFg, *normalBg;
62 XColor *activeFg, *activeBg;
64 Tk_Cursor cursor; /* Cursor to display inside of this window */
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 */
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 */
85 EditorDrawProc *drawProc;
86 EditorDestroyProc *destroyProc;
90 Table *tablePtr; /* Pointer to table being debugged */
93 Tk_Window tkwin; /* Grid window */
94 Tk_Window input; /* InputOnly window to receive events */
100 XRectangle *padRectArr;
102 XRectangle *widgetPadRectArr;
105 XRectangle *cntlRectArr;
111 XRectangle activeRectArr[5];
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 */
120 Tk_3DBorder border; /* Border to use with buttons */
122 int borderWidth; /* Border width of buttons */
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
142 EntryAttributes attributes; /* Entry attributes */
145 #define REDRAW_PENDING (1<<0) /* A DoWhenIdle handler has already
146 * been queued to redraw the window */
147 #define LAYOUT_PENDING (1<<1)
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"
196 static Tk_ConfigSpec configSpecs[] =
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),
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),
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}
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));
311 static Tcl_CmdProc TedCmd;
312 static Tk_EventProc EntryEventProc;
313 static Tk_EventProc TedEventProc;
316 *----------------------------------------------------------------------
318 * EventuallyRedraw --
320 * Queues a request to redraw the text window at the next idle
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
332 *----------------------------------------------------------------------
335 EventuallyRedraw(tedPtr)
336 Ted *tedPtr; /* Information about editor. */
338 if ((tedPtr->tkwin != NULL) && !(tedPtr->flags & REDRAW_PENDING)) {
339 tedPtr->flags |= REDRAW_PENDING;
340 Tcl_DoWhenIdle(DisplayTed, tedPtr);
345 *----------------------------------------------------------------------
347 * EventuallyRedraw --
349 * Queues a request to redraw the text window at the next idle
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
361 *----------------------------------------------------------------------
364 EventuallyRedrawEntry(repPtr)
365 EntryRep *repPtr; /* Information about editor. */
367 if ((repPtr->tkwin != NULL) && !(repPtr->flags & REDRAW_PENDING)) {
368 repPtr->flags |= REDRAW_PENDING;
369 Tcl_DoWhenIdle(DisplayEntry, repPtr);
374 * --------------------------------------------------------------
378 * This procedure is invoked by the Tk dispatcher for various
379 * events on the editing grid for the table.
385 * When the window gets deleted, internal structures get
386 * cleaned up. When it gets exposed, it is redisplayed.
388 * --------------------------------------------------------------
391 EntryEventProc(clientData, eventPtr)
392 ClientData clientData; /* Information about window. */
393 XEvent *eventPtr; /* Information about event. */
395 EntryRep *repPtr = (EntryRep *) clientData;
397 if (eventPtr->type == ConfigureNotify) {
398 EventuallyRedrawEntry(repPtr);
399 } else if (eventPtr->type == Expose) {
400 if (eventPtr->xexpose.count == 0) {
401 EventuallyRedrawEntry(repPtr);
403 } else if (eventPtr->type == DestroyNotify) {
404 repPtr->tkwin = NULL;
405 if (repPtr->flags & REDRAW_PENDING) {
406 Tcl_CancelIdleCall(DisplayEntry, repPtr);
408 Tcl_EventuallyFree(repPtr, DestroyEntry);
413 * --------------------------------------------------------------
417 * This procedure is invoked by the Tk dispatcher for various
418 * events on the editing grid for the table.
424 * When the window gets deleted, internal structures get
425 * cleaned up. When it gets exposed, it is redisplayed.
427 * --------------------------------------------------------------
430 TedEventProc(clientData, eventPtr)
431 ClientData clientData; /* Information about window. */
432 XEvent *eventPtr; /* Information about event. */
434 Ted *tedPtr = (Ted *) clientData;
436 if (eventPtr->type == ConfigureNotify) {
437 EventuallyRedraw(tedPtr);
438 } else if (eventPtr->type == Expose) {
439 if (eventPtr->xexpose.count == 0) {
440 EventuallyRedraw(tedPtr);
442 } else if (eventPtr->type == DestroyNotify) {
443 tedPtr->tkwin = NULL;
444 if (tedPtr->flags & REDRAW_PENDING) {
445 Tcl_CancelIdleCall(DisplayTed, tedPtr);
447 Tcl_EventuallyFree(tedPtr, DestroyTed);
452 * ----------------------------------------------------------------------------
456 * ----------------------------------------------------------------------------
466 * Create a sibling window to cover the master window. It will
467 * be stacked just above the master window.
469 interp = tedPtr->tablePtr->interp;
470 master = tedPtr->tablePtr->tkwin;
471 tkwin = Tk_CreateWindow(interp, master, "ted_%output%", (char *)NULL);
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);
481 tedPtr->tkwin = tkwin;
486 * ----------------------------------------------------------------------------
488 * CreateEventWindow --
490 * ----------------------------------------------------------------------------
493 CreateEventWindow(tedPtr)
501 interp = tedPtr->tablePtr->interp;
502 master = tedPtr->tablePtr->tkwin;
504 * Create an InputOnly window which sits above the table to
505 * collect and dispatch user events.
507 if (Tk_IsTopLevel(master)) {
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.
515 tkwin = Tk_CreateWindow(interp, parent, "ted_%input%", (char *)NULL);
517 Tk_ResizeWindow(tkwin, Tk_Width(parent), Tk_Height(parent));
519 tedPtr->inputIsSibling = 0;
521 char *namePtr; /* Name of InputOnly window. */
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);
529 Tk_MoveResizeWindow(tkwin, Tk_X(master), Tk_Y(master),
530 Tk_Width(master), Tk_Height(master));
532 tedPtr->inputIsSibling = 1;
537 Blt_MakeTransparentWindowExist(tkwin, Tk_WindowId(parent), TRUE);
538 Tk_RestackWindow(tkwin, Above, (Tk_Window)NULL);
540 tedPtr->input = tkwin;
545 * ----------------------------------------------------------------------------
549 * ----------------------------------------------------------------------------
552 CreateEntry(tedPtr, entryPtr)
556 Tk_Window tkwin, master;
559 Blt_ChainLink *linkPtr;
561 repPtr = Blt_Calloc(1, sizeof(EntryRep));
563 repPtr->tablePtr = tedPtr->tablePtr;
564 repPtr->tedPtr = tedPtr;
565 repPtr->interp = tedPtr->interp;
566 repPtr->entryPtr = entryPtr;
570 * Create a sibling window to cover the master window. It will
571 * be stacked just above the master window.
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);
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);
593 * ----------------------------------------------------------------------------
597 * ----------------------------------------------------------------------------
603 EntryRep *repPtr = (EntryRep *)data;
604 Blt_ChainLink *linkPtr;
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);
619 * ----------------------------------------------------------------------------
623 * ----------------------------------------------------------------------------
626 DisplayEntry(clientData)
627 ClientData clientData;
629 EntryRep *repPtr = (EntryRep *) clientData;
633 int x, y, width, height;
635 repPtr->flags &= ~REDRAW_PENDING;
636 if ((repPtr->tkwin == NULL) || (repPtr->entryPtr == NULL)) {
639 if (!Tk_IsMapped(repPtr->tkwin)) {
642 tedPtr = repPtr->tedPtr;
643 entryPtr = repPtr->entryPtr;
644 tkwin = repPtr->tkwin;
647 * Check if the entry size and position.
648 * Move and resize the window accordingly.
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);
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);
663 /* Clear the background of the entry */
665 XFillRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin),
666 tedPtr->attributes.fillGC, 0, 0, width, height);
668 /* Draw the window */
670 x = entryPtr->padLeft + tedPtr->cavityPad;
671 y = entryPtr->padTop + tedPtr->cavityPad;
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));
682 * ----------------------------------------------------------------------------
686 * Searches for a table associated with the window given by its
687 * pathname. This window represents the master window of the table.
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.
694 * If a table entry exists, a pointer to the Table structure is
695 * returned. Otherwise NULL is returned.
697 * ----------------------------------------------------------------------------
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 */
707 if (Blt_GetTable(clientData, interp, pathName, &tablePtr) != TCL_OK) {
710 if (tablePtr->editPtr == NULL) {
711 Tcl_AppendResult(interp, "no editor exists for table \"",
712 Tk_PathName(tablePtr->tkwin), "\"", (char *)NULL);
715 return (Ted *) tablePtr->editPtr;
719 * ----------------------------------------------------------------------------
723 * ----------------------------------------------------------------------------
726 CreateTed(tablePtr, interp)
732 tedPtr = Blt_Calloc(1, sizeof(Ted));
734 tedPtr->nextWindowId = 0;
735 tedPtr->interp = interp;
736 tedPtr->tablePtr = tablePtr;
737 tedPtr->gridLineWidth = 1;
738 tedPtr->buttonHeight = 0;
739 tedPtr->cavityPad = 0;
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 */
751 if (CreateGrid(tedPtr) != TCL_OK) {
754 /* Create an InputOnly window to collect user events */
755 if (CreateEventWindow(tedPtr) != TCL_OK) {
758 tablePtr->editPtr = (Editor *)tedPtr;
763 * ----------------------------------------------------------------------------
767 * ----------------------------------------------------------------------------
770 DestroyTed(freeProcData)
771 DestroyData freeProcData;
773 Ted *tedPtr = (Ted *) freeProcData;
775 if (tedPtr->rectArr != NULL) {
776 Blt_Free(tedPtr->rectArr);
778 if (tedPtr->segArr != NULL) {
779 Blt_Free(tedPtr->segArr);
781 if (tedPtr->fillGC != NULL) {
782 Tk_FreeGC(tedPtr->display, tedPtr->fillGC);
784 if (tedPtr->drawGC != NULL) {
785 Tk_FreeGC(tedPtr->display, tedPtr->drawGC);
787 if (tedPtr->rectGC != NULL) {
788 Tk_FreeGC(tedPtr->display, tedPtr->rectGC);
790 if (tedPtr->padRectGC != NULL) {
791 Tk_FreeGC(tedPtr->display, tedPtr->padRectGC);
794 tedPtr->tablePtr->editPtr = NULL;
800 * ----------------------------------------------------------------------------
804 * This procedure is called to process an argv/argc list in order to
805 * configure the table geometry manager.
808 * The return value is a standard Tcl result. If TCL_ERROR is
809 * returned, then interp->result contains an error message.
812 * Table configuration options (padx, pady, rows, columns, etc) get
813 * set. The table is recalculated and arranged at the next idle
816 * ----------------------------------------------------------------------------
819 ConfigureTed(tedPtr, argc, argv, flags)
822 char **argv; /* Option-value pairs */
827 unsigned long gcMask;
829 if (Tk_ConfigureWidget(tedPtr->interp, tedPtr->tkwin, configSpecs,
830 argc, argv, (char *)tedPtr, flags) != TCL_OK) {
833 /* GC for filling background of edit window */
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);
841 tedPtr->fillGC = newGC;
843 /* GC for drawing grid lines */
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;
857 newGC = Blt_GetPrivateGC(tedPtr->tkwin, gcMask, &gcValues);
858 if (tedPtr->drawGC != NULL) {
859 Blt_FreePrivateGC(tedPtr->display, tedPtr->drawGC);
861 if (LineIsDashed(tedPtr->dashes)) {
862 XSetDashes(tedPtr->display, newGC, 0,
863 (CONST char *)tedPtr->dashes.values,
864 strlen((char *)tedPtr->dashes.values));
866 tedPtr->drawGC = newGC;
868 /* GC for button rectangles */
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);
876 tedPtr->rectGC = newGC;
878 /* GC for button rectangles */
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;
887 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
888 if (tedPtr->padRectGC != NULL) {
889 Tk_FreeGC(tedPtr->display, tedPtr->padRectGC);
891 tedPtr->padRectGC = newGC;
893 /* GC for filling entrys */
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;
902 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
903 if (tedPtr->attributes.fillGC != NULL) {
904 Tk_FreeGC(tedPtr->display, tedPtr->attributes.fillGC);
906 tedPtr->attributes.fillGC = newGC;
908 /* GC for drawing entrys */
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);
918 tedPtr->attributes.drawGC = newGC;
920 /* GC for filling widget rectangles */
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);
928 tedPtr->attributes.widgetFillGC = newGC;
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);
936 tedPtr->attributes.cntlGC = newGC;
938 /* GC for filling span rectangle */
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;
947 newGC = Tk_GetGC(tedPtr->tkwin, gcMask, &gcValues);
948 if (tedPtr->spanGC != NULL) {
949 Tk_FreeGC(tedPtr->display, tedPtr->spanGC);
951 tedPtr->spanGC = newGC;
953 /* Define cursor for grid events */
954 if (tedPtr->cursor != None) {
955 Tk_DefineCursor(tedPtr->input, tedPtr->cursor);
957 Tk_UndefineCursor(tedPtr->input);
970 Blt_ChainLink *linkPtr;
976 tablePtr = tedPtr->tablePtr;
977 if (tedPtr->segArr != NULL) {
978 Blt_Free(tedPtr->segArr);
979 tedPtr->segArr = NULL;
982 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
985 needed = tablePtr->nRows + tablePtr->nColumns + 2;
986 segArr = Blt_Calloc(needed, sizeof(XSegment));
987 if (segArr == NULL) {
990 linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
991 rcPtr = Blt_ChainGetValue(linkPtr);
992 startX = rcPtr->offset - tedPtr->gridLineWidth;
994 linkPtr = Blt_ChainLastLink(tablePtr->columnInfo.chainPtr);
995 rcPtr = Blt_ChainGetValue(linkPtr);
996 endX = rcPtr->offset + rcPtr->size - 1;
998 linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
999 rcPtr = Blt_ChainGetValue(linkPtr);
1000 startY = rcPtr->offset - tedPtr->gridLineWidth;
1002 linkPtr = Blt_ChainLastLink(tablePtr->rowInfo.chainPtr);
1003 rcPtr = Blt_ChainGetValue(linkPtr);
1004 endY = rcPtr->offset + rcPtr->size - 1;
1006 count = 0; /* Reset segment counter */
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;
1017 segArr[count].x1 = startX;
1018 segArr[count].x2 = endX;
1019 segArr[count].y1 = segArr[count].y2 = endY;
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;
1031 segArr[count].x1 = segArr[count].x2 = endX;
1032 segArr[count].y1 = startY;
1033 segArr[count].y2 = endY;
1035 assert(count == needed);
1036 if (tedPtr->segArr != NULL) {
1037 Blt_Free(tedPtr->segArr);
1039 tedPtr->segArr = segArr;
1040 tedPtr->nSegs = count;
1049 XRectangle *rectArr, *rectPtr;
1051 Blt_ChainLink *linkPtr;
1057 tablePtr = tedPtr->tablePtr;
1058 if (tedPtr->padRectArr != NULL) {
1059 Blt_Free(tedPtr->padRectArr);
1060 tedPtr->padRectArr = NULL;
1062 tedPtr->nPadRects = 0;
1063 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
1066 needed = 2 * (tablePtr->nRows + tablePtr->nColumns);
1067 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1068 if (rectArr == NULL) {
1071 linkPtr = Blt_ChainFirstLink(tablePtr->columnInfo.chainPtr);
1072 rcPtr = Blt_ChainGetValue(linkPtr);
1073 startX = rcPtr->offset;
1075 linkPtr = Blt_ChainLastLink(tablePtr->columnInfo.chainPtr);
1076 rcPtr = Blt_ChainGetValue(linkPtr);
1077 endX = (rcPtr->offset + rcPtr->size);
1079 linkPtr = Blt_ChainFirstLink(tablePtr->rowInfo.chainPtr);
1080 rcPtr = Blt_ChainGetValue(linkPtr);
1081 startY = rcPtr->offset;
1083 linkPtr = Blt_ChainLastLink(tablePtr->rowInfo.chainPtr);
1084 rcPtr = Blt_ChainGetValue(linkPtr);
1085 endY = (rcPtr->offset + rcPtr->size);
1087 count = 0; /* Reset segment counter */
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;
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;
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;
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;
1129 tedPtr->padRectArr = rectArr;
1130 tedPtr->nPadRects = count;
1134 LayoutEntries(tedPtr)
1138 XRectangle *rectArr;
1141 Blt_ChainLink *linkPtr;
1143 if (tedPtr->widgetPadRectArr != NULL) {
1144 Blt_Free(tedPtr->widgetPadRectArr);
1145 tedPtr->widgetPadRectArr = NULL;
1147 tedPtr->nWidgetPadRects = 0;
1149 needed = Blt_ChainGetLength(tedPtr->tablePtr->chainPtr);
1150 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1151 if (rectArr == NULL) {
1154 /* Draw any entry windows */
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) {
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);
1174 tedPtr->widgetPadRectArr = rectArr;
1175 tedPtr->nWidgetPadRects = count;
1179 LayoutControlEntries(tedPtr)
1183 XRectangle *rectArr;
1186 Table *tablePtr = tedPtr->tablePtr;
1187 Blt_ChainLink *linkPtr;
1190 if (tedPtr->cntlRectArr != NULL) {
1191 Blt_Free(tedPtr->cntlRectArr);
1192 tedPtr->cntlRectArr = NULL;
1194 tedPtr->nCntlRects = 0;
1196 needed = (tablePtr->nRows + tablePtr->nColumns);
1197 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1198 if (rectArr == NULL) {
1201 /* Draw any entry windows */
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);
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);
1235 tedPtr->cntlRectArr = rectArr;
1236 tedPtr->nCntlRects = count;
1240 LayoutButtons(tedPtr)
1244 XRectangle *rectArr;
1246 Blt_ChainLink *linkPtr;
1250 tablePtr = tedPtr->tablePtr;
1251 if ((tablePtr->nRows == 0) || (tablePtr->nColumns == 0)) {
1252 if (tedPtr->rectArr != NULL) {
1253 Blt_Free(tedPtr->rectArr);
1255 tedPtr->rectArr = NULL;
1257 return; /* Nothing to display, empty table */
1259 needed = 2 * (tablePtr->nRows + tablePtr->nColumns);
1260 rectArr = Blt_Calloc(needed, sizeof(XRectangle));
1261 if (rectArr == NULL) {
1262 return; /* Can't allocate rectangles */
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;
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;
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;
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;
1293 assert(count == needed);
1294 if (tedPtr->rectArr != NULL) {
1295 Blt_Free(tedPtr->rectArr);
1297 tedPtr->rectArr = rectArr;
1298 tedPtr->nRects = count;
1303 DisplayTed(clientData)
1304 ClientData clientData;
1306 Ted *tedPtr = (Ted *) clientData;
1309 Blt_ChainLink *linkPtr;
1315 fprintf(stderr, "display grid\n");
1317 tedPtr->flags &= ~REDRAW_PENDING;
1318 if (!Tk_IsMapped(tedPtr->tkwin)) {
1322 * Check if the master window has changed size and resize the
1323 * grid and input windows accordingly.
1325 master = tedPtr->tablePtr->tkwin;
1326 if ((Tk_Width(master) != Tk_Width(tedPtr->tkwin)) ||
1327 (Tk_Height(master) != Tk_Height(tedPtr->tkwin))) {
1329 fprintf(stderr, "resizing windows\n");
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));
1336 tedPtr->flags |= LAYOUT_PENDING;
1338 if (tedPtr->flags & LAYOUT_PENDING) {
1340 fprintf(stderr, "layout of grid\n");
1343 LayoutEntries(tedPtr);
1344 LayoutControlEntries(tedPtr);
1346 LayoutButtons(tedPtr);
1347 tedPtr->flags &= ~LAYOUT_PENDING;
1349 tkwin = tedPtr->tkwin;
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));
1359 /* Clear the background of the grid */
1361 XFillRectangle(Tk_Display(tkwin), drawable, tedPtr->fillGC, 0, 0,
1362 Tk_Width(tkwin), Tk_Height(tkwin));
1364 /* Draw the row and column buttons */
1366 if (tedPtr->nRects > 0) {
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);
1376 XFillRectangles(tedPtr->display, drawable, tedPtr->rectGC,
1377 tedPtr->rectArr, tedPtr->nRects);
1378 XDrawRectangles(tedPtr->display, drawable, tedPtr->drawGC,
1379 tedPtr->rectArr, tedPtr->nRects);
1382 if (tedPtr->nPadRects > 0) {
1383 XFillRectangles(tedPtr->display, drawable, tedPtr->padRectGC,
1384 tedPtr->padRectArr, tedPtr->nPadRects);
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);
1392 if (tedPtr->nWidgetPadRects > 0) {
1393 XFillRectangles(tedPtr->display, drawable, tedPtr->attributes.fillGC,
1394 tedPtr->widgetPadRectArr, tedPtr->nWidgetPadRects);
1396 if (tedPtr->nCntlRects > 0) {
1397 XFillRectangles(tedPtr->display, drawable, tedPtr->attributes.cntlGC,
1398 tedPtr->cntlRectArr, tedPtr->nCntlRects);
1400 /* Draw the grid lines */
1401 if (tedPtr->nSegs > 0) {
1402 XDrawSegments(tedPtr->display, drawable, tedPtr->drawGC,
1403 tedPtr->segArr, tedPtr->nSegs);
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);
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);
1427 Ted *tedPtr = (Ted *) editPtr;
1429 tedPtr->flags |= LAYOUT_PENDING;
1430 if ((tedPtr->tkwin != NULL) && !(tedPtr->flags & REDRAW_PENDING)) {
1431 tedPtr->flags |= REDRAW_PENDING;
1433 fprintf(stderr, "from draw editor\n");
1435 Tcl_DoWhenIdle(DisplayTed, tedPtr);
1440 DestroyEditor(destroyData)
1441 DestroyData destroyData;
1443 Ted *tedPtr = (Ted *) destroyData;
1445 tedPtr->tkwin = NULL;
1446 if (tedPtr->flags & REDRAW_PENDING) {
1447 Tcl_CancelIdleCall(DisplayTed, tedPtr);
1449 Tcl_EventuallyFree(tedPtr, DestroyTed);
1453 * ----------------------------------------------------------------------------
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.
1464 * Returns a standard Tcl result. If an error occurred, TCL_ERROR is
1465 * returned and an error message is left in interp->result.
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.
1471 * ----------------------------------------------------------------------------
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 */
1483 if (Blt_GetTable(dataPtr, interp, argv[2], &tablePtr) != TCL_OK) {
1486 if (tablePtr->editPtr != NULL) { /* Already editing this table */
1487 tedPtr = (Ted *) tablePtr->editPtr;
1489 tedPtr = CreateTed(tablePtr, interp);
1490 if (tedPtr == NULL) {
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);
1499 Tcl_EventuallyFree(tedPtr, DestroyTed);
1502 /* Rearrange the table */
1503 if (!(tablePtr->flags & ARRANGE_PENDING)) {
1504 tablePtr->flags |= ARRANGE_PENDING;
1505 Tcl_DoWhenIdle(tablePtr->arrangeProc, tablePtr);
1507 interp->result = Tk_PathName(tedPtr->tkwin);
1508 tedPtr->flags |= LAYOUT_PENDING;
1509 EventuallyRedraw(tedPtr);
1514 * ----------------------------------------------------------------------------
1519 * The return value is a standard Tcl result. If TCL_ERROR is
1520 * returned, then interp->result contains an error message.
1522 * ----------------------------------------------------------------------------
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 */
1534 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1535 if (tedPtr == NULL) {
1538 return Tk_ConfigureValue(interp, tedPtr->tkwin, configSpecs,
1539 (char *)tedPtr, argv[3], 0);
1543 * ----------------------------------------------------------------------------
1547 * This procedure is called to process an argv/argc list in order to
1548 * configure the table geometry manager.
1551 * The return value is a standard Tcl result. If TCL_ERROR is
1552 * returned, then interp->result contains an error message.
1555 * Table configuration options (padx, pady, rows, columns, etc) get
1556 * set. The table is recalculated and arranged at the next idle
1559 * ----------------------------------------------------------------------------
1562 ConfigureOp(dataPtr, interp, argc, argv)
1563 TableInterpData *dataPtr; /* Interpreter-specific data. */
1564 Tcl_Interp *interp; /* Interpreter to report results back to */
1566 char **argv; /* Option-value pairs */
1570 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1571 if (tedPtr == NULL) {
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);
1581 if (ConfigureTed(tedPtr, argc - 3, argv + 3,
1582 TK_CONFIG_ARGV_ONLY) != TCL_OK) {
1585 EventuallyRedraw(tedPtr);
1590 * ----------------------------------------------------------------------------
1594 * ----------------------------------------------------------------------------
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. */
1608 int x, y, width, height;
1610 Blt_ChainLink *linkPtr;
1613 /* ted select master @x,y */
1614 tkwin = Tk_MainWindow(interp);
1615 tedPtr = FindEditor(dataPtr, interp, argv[2]);
1616 if (tedPtr == NULL) {
1619 if (Blt_GetXY(interp, tkwin, argv[3], &ix, &iy) != TCL_OK) {
1622 tablePtr = tedPtr->tablePtr;
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;
1638 last = entryPtr->column.rcPtr->index + entryPtr->column.span - 1;
1639 linkPtr = Blt_ChainGetNthLink(tablePtr->columnInfo.chainPtr, last);
1640 rcPtr = Blt_ChainGetValue(linkPtr);
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;
1647 top = (entryPtr->row.rcPtr->offset -
1648 entryPtr->row.rcPtr->pad.side1);
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;
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);
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;
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;
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;
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;
1681 interp->result = Tk_PathName(entryPtr->tkwin);
1686 if ((active) || (active != tedPtr->spanActive)) {
1687 tedPtr->spanActive = active;
1688 EventuallyRedraw(tedPtr);
1694 * ----------------------------------------------------------------------------
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.
1705 * Returns a standard Tcl result. If an error occurred, TCL_ERROR is
1706 * returned and an error message is left in interp->result.
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.
1712 * ----------------------------------------------------------------------------
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 */
1725 /* ted rep master index */
1726 tkwin = Tk_NameToWindow(interp, argv[3], Tk_MainWindow(interp));
1727 if (tkwin == NULL) {
1730 if (Blt_GetTable(dataPtr, interp, argv[2], &tablePtr) != TCL_OK) {
1733 if (tablePtr->editPtr != NULL) { /* Already editing this table */
1734 tedPtr = (Ted *) tablePtr->editPtr;
1736 tedPtr = CreateTed(tablePtr, interp);
1737 if (tedPtr == NULL) {
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);
1746 Tcl_EventuallyFree(tedPtr, DestroyTed);
1749 /* Rearrange the table */
1750 if (!(tablePtr->flags & ARRANGE_PENDING)) {
1751 tablePtr->flags |= ARRANGE_PENDING;
1752 Tcl_DoWhenIdle(tablePtr->arrangeProc, tablePtr);
1754 interp->result = Tk_PathName(tedPtr->tkwin);
1755 tedPtr->flags |= LAYOUT_PENDING;
1756 EventuallyRedraw(tedPtr);
1761 * ----------------------------------------------------------------------------
1763 * Command options for the table editor.
1765 * The fields for Blt_OperSpec are as follows:
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).
1774 * ----------------------------------------------------------------------------
1776 static Blt_OpSpec opSpecs[] =
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...?",}, */
1787 static int nSpecs = sizeof(opSpecs) / sizeof(Blt_OpSpec);
1790 * ----------------------------------------------------------------------------
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.
1799 * A standard Tcl result.
1802 * See the user documentation.
1804 * ----------------------------------------------------------------------------
1807 TedCmd(clientData, interp, argc, argv)
1808 ClientData clientData; /* Thread-specific data. */
1816 proc = Blt_GetOp(interp, nSpecs, opSpecs, BLT_OP_ARG1, argc, argv, 0);
1820 result = (*proc) (clientData, interp, argc, argv);
1825 GetTableInterpData(interp)
1829 Tcl_InterpDeleteProc *proc;
1831 dataPtr = (TableData *)Tcl_GetAssocData(interp, TABLE_THREAD_KEY, &proc);
1837 * ----------------------------------------------------------------------------
1841 * This procedure is invoked to initialize the Tcl command that
1842 * corresponds to the table geometry manager.
1848 * Creates the new command and adds an entry into a global Tcl
1849 * associative array.
1851 * ---------------------------------------------------------------------------
1857 static Blt_CmdSpec cmdSpec = {"ted", TedCmd, };
1860 dataPtr = GetTableInterpData(interp);
1861 cmdSpec.clientData = dataPtr;
1862 if (Blt_InitCmd(interp, "blt", &cmdSpec) == NULL) {