OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [generic/] [tixGrid.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tixGrid.c --
3
 *
4
 *      This module implements "tixGrid" widgets.
5
 *
6
 * Copyright (c) 1996, Expert Interface Technologies
7
 *
8
 * See the file "license.terms" for information on usage and redistribution
9
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10
 *
11
 */
12
 
13
#include <tixPort.h>
14
#include <tixInt.h>
15
#include <tixDef.h>
16
#include <tixGrid.h>
17
 
18
/*
19
 * Information used for argv parsing.
20
 */
21
static Tk_ConfigSpec configSpecs[] = {
22
    {TK_CONFIG_COLOR, "-background", "background", "Background",
23
       DEF_GRID_BG_COLOR, Tk_Offset(WidgetRecord, normalBg),
24
       TK_CONFIG_COLOR_ONLY},
25
 
26
    {TK_CONFIG_COLOR, "-background", "background", "Background",
27
       DEF_GRID_BG_MONO, Tk_Offset(WidgetRecord, normalBg),
28
       TK_CONFIG_MONO_ONLY},
29
 
30
    {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
31
       (char *) NULL, 0, 0},
32
 
33
    {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
34
       (char *) NULL, 0, 0},
35
 
36
    {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
37
       DEF_GRID_BORDER_WIDTH, Tk_Offset(WidgetRecord, borderWidth), 0},
38
 
39
    {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
40
       DEF_GRID_CURSOR, Tk_Offset(WidgetRecord, cursor),
41
       TK_CONFIG_NULL_OK},
42
 
43
    {TK_CONFIG_STRING, "-editdonecmd", "editDoneCmd", "EditDoneCmd",
44
       DEF_GRID_EDITDONE_COMMAND, Tk_Offset(WidgetRecord, editDoneCmd),
45
       TK_CONFIG_NULL_OK},
46
 
47
    {TK_CONFIG_STRING, "-editnotifycmd", "editNotifyCmd", "EditNotifyCmd",
48
       DEF_GRID_EDITNOTIFY_COMMAND, Tk_Offset(WidgetRecord, editNotifyCmd),
49
       TK_CONFIG_NULL_OK},
50
 
51
    {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
52
       (char *) NULL, 0, 0},
53
 
54
    {TK_CONFIG_BOOLEAN, "-floatingcols", "floatingCols", "FloatingCols",
55
        DEF_GRID_FLOATING_COLS, Tk_Offset(WidgetRecord, floatRange[1]), 0},
56
 
57
    {TK_CONFIG_BOOLEAN, "-floatingrows", "floatingRows", "FloatingRows",
58
        DEF_GRID_FLOATING_ROWS, Tk_Offset(WidgetRecord, floatRange[0]), 0},
59
 
60
    {TK_CONFIG_FONT, "-font", "font", "Font",
61
       DEF_GRID_FONT, Tk_Offset(WidgetRecord, font), 0},
62
 
63
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
64
       DEF_GRID_FG_COLOR, Tk_Offset(WidgetRecord, normalFg),
65
       TK_CONFIG_COLOR_ONLY},
66
 
67
    {TK_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
68
       DEF_GRID_FG_MONO, Tk_Offset(WidgetRecord, normalFg),
69
       TK_CONFIG_MONO_ONLY},
70
 
71
    {TK_CONFIG_STRING, "-formatcmd", "formatCmd", "FormatCmd",
72
       DEF_GRID_FORMAT_COMMAND, Tk_Offset(WidgetRecord, formatCmd),
73
       TK_CONFIG_NULL_OK},
74
 
75
    {TK_CONFIG_PIXELS, "-height", "height", "Height",
76
       DEF_GRID_HEIGHT, Tk_Offset(WidgetRecord, reqSize[1]), 0},
77
 
78
    {TK_CONFIG_BORDER, "-highlightbackground", "highlightBackground",
79
       "HighlightBackground",
80
       DEF_GRID_BG_COLOR, Tk_Offset(WidgetRecord, border),
81
       TK_CONFIG_COLOR_ONLY},
82
 
83
    {TK_CONFIG_BORDER, "-highlightbackground", "highlightBackground",
84
       "HighlightBackground",
85
       DEF_GRID_BG_MONO, Tk_Offset(WidgetRecord, border),
86
       TK_CONFIG_MONO_ONLY},
87
 
88
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
89
       DEF_GRID_HIGHLIGHT_COLOR, Tk_Offset(WidgetRecord, highlightColorPtr),
90
       TK_CONFIG_COLOR_ONLY},
91
 
92
    {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
93
       DEF_GRID_HIGHLIGHT_MONO, Tk_Offset(WidgetRecord, highlightColorPtr),
94
       TK_CONFIG_MONO_ONLY},
95
 
96
    {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
97
       "HighlightThickness",
98
       DEF_GRID_HIGHLIGHT_WIDTH, Tk_Offset(WidgetRecord, highlightWidth), 0},
99
 
100
    {TK_CONFIG_INT, "-leftmargin", "leftMargin", "LeftMargin",
101
       DEF_GRID_LEFT_MARGIN, Tk_Offset(WidgetRecord, hdrSize[0]), 0},
102
 
103
    {TK_CONFIG_CUSTOM, "-itemtype", "itemType", "ItemType",
104
       DEF_GRID_ITEM_TYPE, Tk_Offset(WidgetRecord, diTypePtr),
105
       0, &tixConfigItemType},
106
 
107
    {TK_CONFIG_PIXELS, "-padx", "padX", "Pad",
108
        DEF_GRID_PADX, Tk_Offset(WidgetRecord, padX), 0},
109
 
110
    {TK_CONFIG_PIXELS, "-pady", "padY", "Pad",
111
        DEF_GRID_PADY, Tk_Offset(WidgetRecord, padY), 0},
112
 
113
    {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
114
       DEF_GRID_RELIEF, Tk_Offset(WidgetRecord, relief), 0},
115
 
116
    {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
117
        DEF_GRID_SELECT_BG_COLOR, Tk_Offset(WidgetRecord, selectBorder),
118
        TK_CONFIG_COLOR_ONLY},
119
 
120
    {TK_CONFIG_BORDER, "-selectbackground", "selectBackground", "Foreground",
121
        DEF_GRID_SELECT_BG_MONO, Tk_Offset(WidgetRecord, selectBorder),
122
        TK_CONFIG_MONO_ONLY},
123
 
124
    {TK_CONFIG_PIXELS, "-selectborderwidth", "selectBorderWidth","BorderWidth",
125
       DEF_GRID_SELECT_BORDERWIDTH,Tk_Offset(WidgetRecord, selBorderWidth),0},
126
 
127
    {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
128
       DEF_GRID_SELECT_FG_COLOR, Tk_Offset(WidgetRecord, selectFg),
129
       TK_CONFIG_COLOR_ONLY},
130
 
131
    {TK_CONFIG_COLOR, "-selectforeground", "selectForeground", "Background",
132
       DEF_GRID_SELECT_FG_MONO, Tk_Offset(WidgetRecord, selectFg),
133
       TK_CONFIG_MONO_ONLY},
134
 
135
    {TK_CONFIG_UID, "-selectmode", "selectMode", "SelectMode",
136
        DEF_GRID_SELECT_MODE, Tk_Offset(WidgetRecord, selectMode), 0},
137
 
138
    {TK_CONFIG_UID, "-selectunit", "selectUnit", "SelectUnit",
139
        DEF_GRID_SELECT_UNIT, Tk_Offset(WidgetRecord, selectUnit), 0},
140
 
141
    {TK_CONFIG_STRING, "-sizecmd", "sizeCmd", "SizeCmd",
142
       DEF_GRID_SIZE_COMMAND, Tk_Offset(WidgetRecord, sizeCmd),
143
       TK_CONFIG_NULL_OK},
144
 
145
    {TK_CONFIG_UID, "-state", (char*)NULL, (char*)NULL,
146
       DEF_GRID_STATE, Tk_Offset(WidgetRecord, state), 0},
147
 
148
    {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
149
        DEF_GRID_TAKE_FOCUS, Tk_Offset(WidgetRecord, takeFocus),
150
        TK_CONFIG_NULL_OK},
151
 
152
    {TK_CONFIG_INT, "-topmargin", "topMargin", "TopMargin",
153
       DEF_GRID_TOP_MARGIN, Tk_Offset(WidgetRecord, hdrSize[1]), 0},
154
 
155
    {TK_CONFIG_PIXELS, "-width", "width", "Width",
156
        DEF_GRID_WIDTH, Tk_Offset(WidgetRecord, reqSize[0]), 0},
157
 
158
    {TK_CONFIG_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
159
       DEF_GRID_X_SCROLL_COMMAND,
160
       Tk_Offset(WidgetRecord, scrollInfo[0].command),
161
       TK_CONFIG_NULL_OK},
162
 
163
    {TK_CONFIG_STRING, "-yscrollcommand", "yScrollCommand", "ScrollCommand",
164
       DEF_GRID_Y_SCROLL_COMMAND,
165
       Tk_Offset(WidgetRecord, scrollInfo[1].command),
166
       TK_CONFIG_NULL_OK},
167
 
168
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
169
       (char *) NULL, 0, 0}
170
};
171
 
172
static Tk_ConfigSpec entryConfigSpecs[] = {
173
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
174
       (char *) NULL, 0, 0}
175
};
176
 
177
 
178
/*
179
 * Forward declarations for procedures defined later in this file:
180
 */
181
 
182
        /* These are standard procedures for TK widgets
183
         * implemeted in C
184
         */
185
 
186
static void             WidgetCmdDeletedProc _ANSI_ARGS_((
187
                            ClientData clientData));
188
static int              WidgetConfigure _ANSI_ARGS_((Tcl_Interp *interp,
189
                            WidgetPtr wPtr, int argc, char **argv,
190
                            int flags));
191
static void             WidgetDestroy _ANSI_ARGS_((ClientData clientData));
192
static void             WidgetEventProc _ANSI_ARGS_((ClientData clientData,
193
                            XEvent *eventPtr));
194
static int              WidgetCommand _ANSI_ARGS_((ClientData clientData,
195
                            Tcl_Interp *, int argc, char **argv));
196
static void             WidgetDisplay _ANSI_ARGS_((ClientData clientData));
197
static void             WidgetComputeGeometry _ANSI_ARGS_((
198
                            ClientData clientData));
199
static void             IdleHandler _ANSI_ARGS_((
200
                            ClientData clientData));
201
        /* Extra procedures for this widget
202
         */
203
static int              ConfigElement _ANSI_ARGS_((WidgetPtr wPtr,
204
                            TixGrEntry *chPtr, int argc, char ** argv,
205
                            int flags, int forced));
206
static void             Tix_GrDisplayMainBody _ANSI_ARGS_((
207
                            WidgetPtr wPtr, Drawable buffer,
208
                            int winW, int winH));
209
static void             Tix_GrDrawBackground _ANSI_ARGS_((WidgetPtr wPtr,
210
                            RenderInfo * riPtr,Drawable drawable));
211
static void             Tix_GrDrawCells _ANSI_ARGS_((WidgetPtr wPtr,
212
                            RenderInfo * riPtr,Drawable drawable));
213
static void             Tix_GrDrawSites _ANSI_ARGS_((WidgetPtr wPtr,
214
                            RenderInfo * riPtr,Drawable drawable));
215
int                     Tix_GrGetElementPosn _ANSI_ARGS_((
216
                            WidgetPtr wPtr, int x, int y,
217
                            int rect[2][2], int clipOK, int isSite,
218
                            int isScr, int nearest));
219
static void             UpdateScrollBars _ANSI_ARGS_((WidgetPtr wPtr,
220
                            int sizeChanged));
221
static void             GetScrollFractions _ANSI_ARGS_((
222
                            WidgetPtr wPtr, Tix_GridScrollInfo *siPtr,
223
                            double * first_ret, double * last_ret));
224
static void             Tix_GrDItemSizeChanged _ANSI_ARGS_((
225
                            Tix_DItem *iPtr));
226
static TixGrEntry *     Tix_GrFindCreateElem _ANSI_ARGS_((Tcl_Interp * interp,
227
                            WidgetPtr wPtr, int x, int y));
228
static TixGrEntry *     Tix_GrFindElem _ANSI_ARGS_((Tcl_Interp * interp,
229
                            WidgetPtr wPtr, int x, int y));
230
static void             Tix_GrPropagateSize _ANSI_ARGS_((
231
                            WidgetPtr wPtr, TixGrEntry * chPtr));
232
static RenderBlock *    Tix_GrAllocateRenderBlock _ANSI_ARGS_((
233
                            WidgetPtr wPtr, int winW, int winH,
234
                            int *exactW, int *exactH));
235
static void             Tix_GrFreeRenderBlock _ANSI_ARGS_((
236
                            WidgetPtr wPtr, RenderBlock * rbPtr));
237
static void             Tix_GrComputeSelection _ANSI_ARGS_((
238
                            WidgetPtr wPtr));
239
static int              Tix_GrBBox _ANSI_ARGS_((Tcl_Interp * interp,
240
                            WidgetPtr wPtr, int x, int y));
241
static int              TranslateFromTo _ANSI_ARGS_((Tcl_Interp * interp,
242
                            WidgetPtr wPtr, int argc, char **argv, int *from,
243
                            int * to, int *which));
244
static void             Tix_GrComputeSubSelection _ANSI_ARGS_((
245
                            WidgetPtr wPtr, int rect[2][2], int offs[2]));
246
static int              Tix_GrCallFormatCmd _ANSI_ARGS_((WidgetPtr wPtr,
247
                            int which));
248
static void             RecalScrollRegion _ANSI_ARGS_((WidgetPtr wPtr,
249
                            int winW, int winH,
250
                            Tix_GridScrollInfo *scrollInfo));
251
static void             Tix_GrResetRenderBlocks _ANSI_ARGS_((WidgetPtr wPtr));
252
 
253
static TIX_DECLARE_SUBCMD(Tix_GrBdType);
254
static TIX_DECLARE_SUBCMD(Tix_GrCGet);
255
static TIX_DECLARE_SUBCMD(Tix_GrConfig);
256
static TIX_DECLARE_SUBCMD(Tix_GrDelete);
257
static TIX_DECLARE_SUBCMD(Tix_GrEdit);
258
static TIX_DECLARE_SUBCMD(Tix_GrEntryCget);
259
static TIX_DECLARE_SUBCMD(Tix_GrEntryConfig);
260
EXTERN TIX_DECLARE_SUBCMD(Tix_GrFormat);
261
static TIX_DECLARE_SUBCMD(Tix_GrGeometryInfo);
262
static TIX_DECLARE_SUBCMD(Tix_GrInfo);
263
static TIX_DECLARE_SUBCMD(Tix_GrIndex);
264
static TIX_DECLARE_SUBCMD(Tix_GrMove);
265
static TIX_DECLARE_SUBCMD(Tix_GrNearest);
266
EXTERN TIX_DECLARE_SUBCMD(Tix_GrSelection);
267
static TIX_DECLARE_SUBCMD(Tix_GrSet);
268
EXTERN TIX_DECLARE_SUBCMD(Tix_GrSetSize);
269
static TIX_DECLARE_SUBCMD(Tix_GrSetSite);
270
EXTERN TIX_DECLARE_SUBCMD(Tix_GrSort);
271
static TIX_DECLARE_SUBCMD(Tix_GrView);
272
static TIX_DECLARE_SUBCMD(Tix_GrUnset);
273
 
274
 
275
/*
276
 *--------------------------------------------------------------
277
 *
278
 * Tix_GridCmd --
279
 *
280
 *      This procedure is invoked to process the "tixGrid" Tcl
281
 *      command.  It creates a new "TixGrid" widget.
282
 *
283
 * Results:
284
 *      A standard Tcl result.
285
 *
286
 * Side effects:
287
 *      A new widget is created and configured.
288
 *
289
 *--------------------------------------------------------------
290
 */
291
int
292
Tix_GridCmd(clientData, interp, argc, argv)
293
    ClientData clientData;
294
    Tcl_Interp *interp;         /* Current interpreter. */
295
    int argc;                   /* Number of arguments. */
296
    char **argv;                /* Argument strings. */
297
{
298
    Tk_Window main = (Tk_Window) clientData;
299
    WidgetPtr wPtr;
300
    Tk_Window tkwin;
301
 
302
    if (argc < 2) {
303
        Tcl_AppendResult(interp, "wrong # args:  should be \"",
304
                argv[0], " pathName ?options?\"", (char *) NULL);
305
        return TCL_ERROR;
306
    }
307
 
308
    tkwin = Tk_CreateWindowFromPath(interp, main, argv[1], (char *) NULL);
309
    if (tkwin == NULL) {
310
        return TCL_ERROR;
311
    }
312
 
313
    Tk_SetClass(tkwin, "TixGrid");
314
 
315
    /*
316
     * Allocate and initialize the widget record.
317
     */
318
    wPtr = (WidgetPtr) ckalloc(sizeof(WidgetRecord));
319
 
320
    wPtr->dispData.tkwin        = tkwin;
321
    wPtr->dispData.display      = Tk_Display(tkwin);
322
    wPtr->dispData.interp       = interp;
323
    wPtr->dispData.sizeChangedProc = Tix_GrDItemSizeChanged;
324
    wPtr->font          = NULL;
325
    wPtr->normalBg              = NULL;
326
    wPtr->normalFg              = NULL;
327
    wPtr->command               = NULL;
328
    wPtr->border                = NULL;
329
    wPtr->borderWidth           = 0;
330
    wPtr->selectBorder          = NULL;
331
    wPtr->selBorderWidth        = 0;
332
    wPtr->selectFg              = NULL;
333
    wPtr->backgroundGC          = None;
334
    wPtr->selectGC              = None;
335
    wPtr->anchorGC              = None;
336
    wPtr->highlightWidth        = 0;
337
    wPtr->highlightColorPtr     = NULL;
338
    wPtr->highlightGC           = None;
339
    wPtr->relief                = TK_RELIEF_FLAT;
340
    wPtr->cursor                = None;
341
    wPtr->selectMode            = NULL;
342
    wPtr->selectUnit            = NULL;
343
    wPtr->anchor[0]              = TIX_SITE_NONE;
344
    wPtr->anchor[1]             = TIX_SITE_NONE;
345
    wPtr->dragSite[0]            = TIX_SITE_NONE;
346
    wPtr->dragSite[1]           = TIX_SITE_NONE;
347
    wPtr->dropSite[0]            = TIX_SITE_NONE;
348
    wPtr->dropSite[1]           = TIX_SITE_NONE;
349
    wPtr->browseCmd             = 0;
350
    wPtr->formatCmd             = 0;
351
    wPtr->editDoneCmd           = 0;
352
    wPtr->editNotifyCmd         = 0;
353
    wPtr->sizeCmd               = 0;
354
    wPtr->takeFocus             = NULL;
355
    wPtr->serial                = 0;
356
    wPtr->mainRB                = (RenderBlock*)NULL;
357
    wPtr->hdrSize[0]             = 1;
358
    wPtr->hdrSize[1]            = 1;
359
    wPtr->expArea.x1            = 10000;
360
    wPtr->expArea.y1            = 10000;
361
    wPtr->expArea.x2            = 0;
362
    wPtr->expArea.y2            = 0;
363
    wPtr->dataSet               = TixGridDataSetInit();
364
    wPtr->renderInfo            = NULL;
365
    wPtr->defSize[0].sizeType    = TIX_GR_DEFINED_CHAR;
366
    wPtr->defSize[0].charValue   = 10.0;
367
    wPtr->defSize[0].pad0        = 2;
368
    wPtr->defSize[0].pad1        = 2;
369
    wPtr->defSize[1].sizeType   = TIX_GR_DEFINED_CHAR;
370
    wPtr->defSize[1].charValue  = 1.2;
371
    wPtr->defSize[1].pad0       = 2;
372
    wPtr->defSize[1].pad1       = 2;
373
    wPtr->gridSize[0]            = 0;
374
    wPtr->gridSize[1]           = 0;
375
    wPtr->reqSize[0]             = 0;
376
    wPtr->reqSize[1]            = 0;
377
    wPtr->state                 = tixNormalUid;
378
    wPtr->colorInfoCounter      = 0;
379
 
380
    /* The flags */
381
    wPtr->idleEvent             = 0;
382
    wPtr->toRedraw              = 0;
383
    wPtr->toResize              = 0;
384
    wPtr->toResetRB             = 0;
385
    wPtr->toComputeSel          = 0;
386
    wPtr->toRedrawHighlight     = 0;
387
 
388
    wPtr->scrollInfo[0].command  = NULL;
389
    wPtr->scrollInfo[1].command  = NULL;
390
 
391
    wPtr->scrollInfo[0].max  = 1;
392
    wPtr->scrollInfo[0].unit   = 1;
393
    wPtr->scrollInfo[0].offset = 0;
394
    wPtr->scrollInfo[0].window = 1.0;
395
    wPtr->scrollInfo[1].max  = 1;
396
    wPtr->scrollInfo[1].unit   = 1;
397
    wPtr->scrollInfo[1].offset = 0;
398
    wPtr->scrollInfo[1].window = 1.0;
399
 
400
    Tix_SimpleListInit(&wPtr->colorInfo);
401
    Tix_SimpleListInit(&wPtr->selList);
402
    Tix_SimpleListInit(&wPtr->mappedWindows);
403
 
404
    Tk_CreateEventHandler(wPtr->dispData.tkwin,
405
        ExposureMask|StructureNotifyMask|FocusChangeMask,
406
        WidgetEventProc, (ClientData) wPtr);
407
    wPtr->widgetCmd = Tcl_CreateCommand(interp,
408
        Tk_PathName(wPtr->dispData.tkwin), WidgetCommand, (ClientData) wPtr,
409
        WidgetCmdDeletedProc);
410
 
411
    if (WidgetConfigure(interp, wPtr, argc-2, argv+2, 0) != TCL_OK) {
412
        Tk_DestroyWindow(wPtr->dispData.tkwin);
413
        return TCL_ERROR;
414
    }
415
 
416
    interp->result = Tk_PathName(wPtr->dispData.tkwin);
417
    return TCL_OK;
418
}
419
 
420
/*
421
 *----------------------------------------------------------------------
422
 *
423
 * WidgetConfigure --
424
 *
425
 *      This procedure is called to process an argv/argc list in
426
 *      conjunction with the Tk option database to configure (or
427
 *      reconfigure) a List widget.
428
 *
429
 * Results:
430
 *      The return value is a standard Tcl result.  If TCL_ERROR is
431
 *      returned, then interp->result contains an error message.
432
 *
433
 * Side effects:
434
 *      Configuration information, such as colors, border width,
435
 *      etc. get set for wPtr;  old resources get freed,
436
 *      if there were any.
437
 *
438
 *----------------------------------------------------------------------
439
 */
440
static int
441
WidgetConfigure(interp, wPtr, argc, argv, flags)
442
    Tcl_Interp *interp;                 /* Used for error reporting. */
443
    WidgetPtr wPtr;                     /* Information about widget. */
444
    int argc;                           /* Number of valid entries in argv. */
445
    char **argv;                        /* Arguments. */
446
    int flags;                          /* Flags to pass to
447
                                         * Tk_ConfigureWidget. */
448
{
449
    XGCValues gcValues;
450
    GC newGC;
451
    TixFont oldfont;
452
    Tix_StyleTemplate stTmpl;
453
 
454
    oldfont = wPtr->font;
455
 
456
    if (Tk_ConfigureWidget(interp, wPtr->dispData.tkwin, configSpecs,
457
            argc, argv, (char *) wPtr, flags) != TCL_OK) {
458
        return TCL_ERROR;
459
    }
460
 
461
    wPtr->bdPad = wPtr->highlightWidth + wPtr->borderWidth;
462
 
463
    if ((wPtr->state != tixNormalUid) && (wPtr->state != tixDisabledUid)) {
464
        Tcl_AppendResult(interp, "bad state value \"", wPtr->state,
465
            "\":  must be normal or disabled", (char *) NULL);
466
        wPtr->state = tixNormalUid;
467
        return TCL_ERROR;
468
    }
469
 
470
    if (oldfont != wPtr->font) {
471
        int i;
472
 
473
        /*
474
         * Font has been changed (initialized), we need to reset the render
475
         * blocks
476
         */
477
        wPtr->toResetRB = 1;
478
 
479
        TixComputeTextGeometry(wPtr->font, "0", 1,
480
            0, &wPtr->fontSize[0], &wPtr->fontSize[1]);
481
 
482
        /* Recalculate the default size of the cells
483
         */
484
        for (i=0; i<2; i++) {
485
            switch (wPtr->defSize[i].sizeType) {
486
              case TIX_GR_DEFINED_CHAR:
487
                wPtr->defSize[i].pixels = (int)
488
                    (wPtr->defSize[i].charValue * wPtr->fontSize[i]);
489
                break;
490
              case TIX_GR_AUTO:
491
                if (i==0) {
492
                    wPtr->defSize[i].pixels = 10 * wPtr->fontSize[0];
493
                }
494
                if (i==1) {
495
                    wPtr->defSize[i].pixels =  1 * wPtr->fontSize[1];
496
                }
497
                break;
498
            }
499
        }
500
    }
501
 
502
    /*
503
     * A few options need special processing, such as setting the
504
     * background from a 3-D border, or filling in complicated
505
     * defaults that couldn't be specified to Tk_ConfigureWidget.
506
     */
507
 
508
    Tk_SetBackgroundFromBorder(wPtr->dispData.tkwin, wPtr->border);
509
 
510
    /*
511
     * Note: GraphicsExpose events are disabled in normalGC because it's
512
     * used to copy stuff from an off-screen pixmap onto the screen (we know
513
     * that there's no problem with obscured areas).
514
     */
515
 
516
    /* The background GC */
517
    gcValues.foreground         = wPtr->normalBg->pixel;
518
    gcValues.graphics_exposures = False;
519
 
520
    newGC = Tk_GetGC(wPtr->dispData.tkwin,
521
        GCForeground|GCGraphicsExposures, &gcValues);
522
    if (wPtr->backgroundGC != None) {
523
        Tk_FreeGC(wPtr->dispData.display, wPtr->backgroundGC);
524
    }
525
    wPtr->backgroundGC = newGC;
526
 
527
    /* The selected text GC */
528
    gcValues.font               = TixFontId(wPtr->font);
529
    gcValues.foreground         = wPtr->selectFg->pixel;
530
    gcValues.background         = Tk_3DBorderColor(wPtr->selectBorder)->pixel;
531
    gcValues.graphics_exposures = False;
532
 
533
    newGC = Tk_GetGC(wPtr->dispData.tkwin,
534
        GCForeground|GCBackground|GCFont|GCGraphicsExposures, &gcValues);
535
    if (wPtr->selectGC != None) {
536
        Tk_FreeGC(wPtr->dispData.display, wPtr->selectGC);
537
    }
538
    wPtr->selectGC = newGC;
539
 
540
    /* The dotted anchor lines */
541
    gcValues.foreground         = wPtr->normalFg->pixel;
542
    gcValues.background         = wPtr->normalBg->pixel;
543
    gcValues.graphics_exposures = False;
544
    gcValues.line_style         = LineDoubleDash;
545
    gcValues.dashes             = 2;
546
    gcValues.subwindow_mode     = IncludeInferiors;
547
 
548
    newGC = Tk_GetGC(wPtr->dispData.tkwin,
549
        GCForeground|GCBackground|GCGraphicsExposures|GCLineStyle|GCDashList|
550
        GCSubwindowMode, &gcValues);
551
    if (wPtr->anchorGC != None) {
552
        Tk_FreeGC(wPtr->dispData.display, wPtr->anchorGC);
553
    }
554
    wPtr->anchorGC = newGC;
555
 
556
    /* The highlight border */
557
    gcValues.background         = wPtr->selectFg->pixel;
558
    gcValues.foreground         = wPtr->highlightColorPtr->pixel;
559
    gcValues.graphics_exposures = False;
560
 
561
    newGC = Tk_GetGC(wPtr->dispData.tkwin,
562
        GCForeground|GCBackground|GCGraphicsExposures, &gcValues);
563
    if (wPtr->highlightGC != None) {
564
        Tk_FreeGC(wPtr->dispData.display, wPtr->highlightGC);
565
    }
566
    wPtr->highlightGC = newGC;
567
 
568
    /* We must set the options of the default styles so that
569
     * -- the default styles will change according to what is in
570
     *    stTmpl
571
     */
572
    stTmpl.font                         = wPtr->font;
573
    stTmpl.pad[0]                        = wPtr->padX;
574
    stTmpl.pad[1]                       = wPtr->padY;
575
    stTmpl.colors[TIX_DITEM_NORMAL].fg  = wPtr->normalFg;
576
    stTmpl.colors[TIX_DITEM_NORMAL].bg  = wPtr->normalBg;
577
    stTmpl.colors[TIX_DITEM_SELECTED].fg= wPtr->selectFg;
578
    stTmpl.colors[TIX_DITEM_SELECTED].bg= Tk_3DBorderColor(wPtr->selectBorder);
579
    stTmpl.flags = TIX_DITEM_FONT|TIX_DITEM_NORMAL_BG|
580
        TIX_DITEM_SELECTED_BG|TIX_DITEM_NORMAL_FG|TIX_DITEM_SELECTED_FG |
581
        TIX_DITEM_PADX|TIX_DITEM_PADY;
582
 
583
    Tix_SetDefaultStyleTemplate(wPtr->dispData.tkwin, &stTmpl);
584
 
585
    Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
586
 
587
    return TCL_OK;
588
}
589
/*
590
 *--------------------------------------------------------------
591
 *
592
 * WidgetCommand --
593
 *
594
 *      This procedure is invoked to process the Tcl command
595
 *      that corresponds to a widget managed by this module.
596
 *      See the user documentation for details on what it does.
597
 *
598
 * Results:
599
 *      A standard Tcl result.
600
 *
601
 * Side effects:
602
 *      See the user documentation.
603
 *
604
 *--------------------------------------------------------------
605
 */
606
 
607
static int
608
WidgetCommand(clientData, interp, argc, argv)
609
    ClientData clientData;              /* Information about the widget. */
610
    Tcl_Interp *interp;                 /* Current interpreter. */
611
    int argc;                           /* Number of arguments. */
612
    char **argv;                        /* Argument strings. */
613
{
614
    int code;
615
 
616
    static Tix_SubCmdInfo subCmdInfo[] = {
617
        {TIX_DEFAULT_LEN, "anchor", 1, 3, Tix_GrSetSite,
618
           "option ?x y?"},
619
        {TIX_DEFAULT_LEN, "bdtype", 2, 4, Tix_GrBdType,
620
           "x y ?xbdWidth ybdWidth?"},
621
        {TIX_DEFAULT_LEN, "cget", 1, 1, Tix_GrCGet,
622
           "option"},
623
        {TIX_DEFAULT_LEN, "configure", 0, TIX_VAR_ARGS, Tix_GrConfig,
624
           "?option? ?value? ?option value ... ?"},
625
        {TIX_DEFAULT_LEN, "delete", 2, 3, Tix_GrDelete,
626
           "option from ?to?"},
627
        {TIX_DEFAULT_LEN, "dragsite", 1, 3, Tix_GrSetSite,
628
           "option ?x y?"},
629
        {TIX_DEFAULT_LEN, "dropsite", 1, 3, Tix_GrSetSite,
630
           "option ?x y?"},
631
        {TIX_DEFAULT_LEN, "entrycget", 3, 3, Tix_GrEntryCget,
632
           "x y option"},
633
        {TIX_DEFAULT_LEN, "edit", 1, 3, Tix_GrEdit,
634
           "option ?args ...?"},
635
        {TIX_DEFAULT_LEN, "entryconfigure", 2, TIX_VAR_ARGS, Tix_GrEntryConfig,
636
           "x y ?option? ?value? ?option value ... ?"},
637
        {TIX_DEFAULT_LEN, "format", 1, TIX_VAR_ARGS, Tix_GrFormat,
638
           "option ?args ...?"},
639
        {TIX_DEFAULT_LEN, "geometryinfo", 0, 2, Tix_GrGeometryInfo,
640
           "?width height?"},
641
        {TIX_DEFAULT_LEN, "info", 1, TIX_VAR_ARGS, Tix_GrInfo,
642
           "option ?args ...?"},
643
        {TIX_DEFAULT_LEN, "index", 2, 2, Tix_GrIndex,
644
           "x y"},
645
        {TIX_DEFAULT_LEN, "move", 4, 4, Tix_GrMove,
646
           "option from to by"},
647
        {TIX_DEFAULT_LEN, "nearest", 2, 2, Tix_GrNearest,
648
           "x y"},
649
#if 0
650
        {TIX_DEFAULT_LEN, "see", 1, 1, Tix_GrSee,
651
           "x y"},
652
#endif
653
        {TIX_DEFAULT_LEN, "selection", 3, 5, Tix_GrSelection,
654
           "option x1 y1 ?x2 y2?"},
655
        {TIX_DEFAULT_LEN, "set", 2, TIX_VAR_ARGS, Tix_GrSet,
656
           "x y ?option value ...?"},
657
        {TIX_DEFAULT_LEN, "size", 1, TIX_VAR_ARGS, Tix_GrSetSize,
658
           "option ?args ...?"},
659
#ifndef _WINDOWS
660
        {TIX_DEFAULT_LEN, "sort", 3, TIX_VAR_ARGS, Tix_GrSort,
661
           "dimension start end ?args ...?"},
662
#endif
663
        {TIX_DEFAULT_LEN, "unset", 2, 2, Tix_GrUnset,
664
           "x y"},
665
        {TIX_DEFAULT_LEN, "xview", 0, 3, Tix_GrView,
666
           "args"},
667
        {TIX_DEFAULT_LEN, "yview", 0, 3, Tix_GrView,
668
           "args"},
669
    };
670
 
671
    static Tix_CmdInfo cmdInfo = {
672
        Tix_ArraySize(subCmdInfo), 1, TIX_VAR_ARGS, "?option? arg ?arg ...?",
673
    };
674
 
675
    Tk_Preserve(clientData);
676
    code = Tix_HandleSubCmds(&cmdInfo, subCmdInfo, clientData,
677
        interp, argc, argv);
678
    Tk_Release(clientData);
679
 
680
    return code;
681
}
682
 
683
/*
684
 *--------------------------------------------------------------
685
 *
686
 * WidgetEventProc --
687
 *
688
 *      This procedure is invoked by the Tk dispatcher for various
689
 *      events on Lists.
690
 *
691
 * Results:
692
 *      None.
693
 *
694
 * Side effects:
695
 *      When the window gets deleted, internal structures get
696
 *      cleaned up.  When it gets exposed, it is redisplayed.
697
 *
698
 *--------------------------------------------------------------
699
 */
700
 
701
static void
702
WidgetEventProc(clientData, eventPtr)
703
    ClientData clientData;      /* Information about window. */
704
    XEvent *eventPtr;           /* Information about event. */
705
{
706
    WidgetPtr wPtr = (WidgetPtr) clientData;
707
    int x2, y2;
708
 
709
    switch (eventPtr->type) {
710
      case DestroyNotify:
711
        if (wPtr->dispData.tkwin != NULL) {
712
            wPtr->dispData.tkwin = NULL;
713
            Tcl_DeleteCommand(wPtr->dispData.interp,
714
                Tcl_GetCommandName(wPtr->dispData.interp, wPtr->widgetCmd));
715
        }
716
        Tix_GrCancelDoWhenIdle(wPtr);
717
        Tk_EventuallyFree((ClientData) wPtr, (Tix_FreeProc*)WidgetDestroy);
718
        break;
719
 
720
      case ConfigureNotify:
721
        wPtr->expArea.x1 = 0;
722
        wPtr->expArea.y1 = 0;
723
        wPtr->expArea.x2 = Tk_Width (wPtr->dispData.tkwin) - 1;
724
        wPtr->expArea.y2 = Tk_Height(wPtr->dispData.tkwin) - 1;
725
        Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
726
        break;
727
 
728
      case Expose:
729
        if (wPtr->expArea.x1 > eventPtr->xexpose.x) {
730
            wPtr->expArea.x1 = eventPtr->xexpose.x;
731
        }
732
        if (wPtr->expArea.y1 > eventPtr->xexpose.y) {
733
            wPtr->expArea.y1 = eventPtr->xexpose.y;
734
        }
735
        x2 = eventPtr->xexpose.x + eventPtr->xexpose.width  - 1;
736
        y2 = eventPtr->xexpose.y + eventPtr->xexpose.height - 1;
737
 
738
        if (wPtr->expArea.x2 < x2) {
739
            wPtr->expArea.x2 = x2;
740
        }
741
        if (wPtr->expArea.y2 < y2) {
742
            wPtr->expArea.y2 = y2;
743
        }
744
        wPtr->toRedrawHighlight = 1;
745
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
746
        break;
747
 
748
      case FocusIn:
749
        wPtr->hasFocus = 1;
750
        wPtr->toRedrawHighlight = 1;
751
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
752
        break;
753
 
754
      case FocusOut:
755
        wPtr->hasFocus = 0;
756
        wPtr->toRedrawHighlight = 1;
757
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
758
        break;
759
    }
760
}
761
 
762
/*
763
 *----------------------------------------------------------------------
764
 *
765
 * WidgetDestroy --
766
 *
767
 *      This procedure is invoked by Tk_EventuallyFree or Tk_Release
768
 *      to clean up the internal structure of a List at a safe time
769
 *      (when no-one is using it anymore).
770
 *
771
 * Results:
772
 *      None.
773
 *
774
 * Side effects:
775
 *      Everything associated with the List is freed up.
776
 *
777
 *----------------------------------------------------------------------
778
 */
779
 
780
static void
781
WidgetDestroy(clientData)
782
    ClientData clientData;      /* Info about the Grid widget. */
783
{
784
    WidgetPtr wPtr = (WidgetPtr) clientData;
785
 
786
    if (wPtr->dataSet) {
787
        Tix_GrDataRowSearch rowSearch;
788
        Tix_GrDataCellSearch cellSearch;
789
        int rowDone, cellDone;
790
 
791
        for (rowDone = TixGrDataFirstRow(wPtr->dataSet, &rowSearch);
792
                !rowDone;
793
                rowDone = TixGrDataNextRow(&rowSearch)) {
794
 
795
 
796
            for (cellDone = TixGrDataFirstCell(&rowSearch, &cellSearch);
797
                    !cellDone;
798
                    cellDone = TixGrDataNextCell(&cellSearch)) {
799
 
800
                TixGridDataDeleteSearchedEntry(&cellSearch);
801
                Tix_GrFreeElem((TixGrEntry*)cellSearch.data);
802
            }
803
        }
804
 
805
        TixGridDataSetFree(wPtr->dataSet);
806
    }
807
 
808
    if (wPtr->backgroundGC != None) {
809
        Tk_FreeGC(wPtr->dispData.display, wPtr->backgroundGC);
810
    }
811
    if (wPtr->selectGC != None) {
812
        Tk_FreeGC(wPtr->dispData.display, wPtr->selectGC);
813
    }
814
    if (wPtr->anchorGC != None) {
815
        Tk_FreeGC(wPtr->dispData.display, wPtr->anchorGC);
816
    }
817
    if (wPtr->highlightGC != None) {
818
        Tk_FreeGC(wPtr->dispData.display, wPtr->highlightGC);
819
    }
820
 
821
    if (wPtr->mainRB) {
822
        Tix_GrFreeRenderBlock(wPtr, wPtr->mainRB);
823
    }
824
 
825
    Tix_GrFreeUnusedColors(wPtr, 1);
826
 
827
    if (!Tix_IsLinkListEmpty(wPtr->mappedWindows)) {
828
        /*
829
         * All mapped windows should have been unmapped when the
830
         * the entries were deleted
831
         */
832
        panic("tixGrid: mappedWindows not NULL");
833
    }
834
 
835
    Tk_FreeOptions(configSpecs, (char *) wPtr, wPtr->dispData.display, 0);
836
    ckfree((char *) wPtr);
837
}
838
 
839
/*
840
 *----------------------------------------------------------------------
841
 *
842
 * WidgetCmdDeletedProc --
843
 *
844
 *      This procedure is invoked when a widget command is deleted.  If
845
 *      the widget isn't already in the process of being destroyed,
846
 *      this command destroys it.
847
 *
848
 * Results:
849
 *      None.
850
 *
851
 * Side effects:
852
 *      The widget is destroyed.
853
 *
854
 *----------------------------------------------------------------------
855
 */
856
static void
857
WidgetCmdDeletedProc(clientData)
858
    ClientData clientData;      /* Info about Grid widget. */
859
{
860
    WidgetPtr wPtr = (WidgetPtr) clientData;
861
 
862
    /*
863
     * This procedure could be invoked either because the window was
864
     * destroyed and the command was then deleted (in which case tkwin
865
     * is NULL) or because the command was deleted, and then this procedure
866
     * destroys the widget.
867
     */
868
    if (wPtr->dispData.tkwin != NULL) {
869
        Tk_Window tkwin = wPtr->dispData.tkwin;
870
        wPtr->dispData.tkwin = NULL;
871
        Tk_DestroyWindow(tkwin);
872
    }
873
}
874
 
875
static void
876
RecalScrollRegion(wPtr, winW, winH, scrollInfo)
877
    WidgetPtr wPtr;             /* Info about Grid widget. */
878
    int winW;
879
    int winH;
880
    Tix_GridScrollInfo *scrollInfo;
881
{
882
    int gridSize[2];
883
    int winSize[2];
884
    int i, k;
885
    int count;
886
    int visibleSize;
887
    int totalSize;
888
    int pad0, pad1;
889
 
890
    winSize[0] = winW;
891
    winSize[1] = winH;
892
 
893
    TixGridDataGetGridSize(wPtr->dataSet, &gridSize[0],
894
        &gridSize[1]);
895
 
896
    for (i=0; i<2; i++) {
897
        for (k=0; k<wPtr->hdrSize[i] && k<gridSize[i]; k++) {
898
            winSize[i] -= TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
899
                k, &wPtr->defSize[i], &pad0, &pad1);
900
            winSize[i] -= pad0 + pad1;
901
        }
902
        if (winSize[i] <= 0) {
903
            /*
904
             * The window's contents are not visible.
905
             */
906
            scrollInfo[i].max    = 0;
907
            scrollInfo[i].window = 1.0;
908
            continue;
909
        }
910
        if (wPtr->hdrSize[i] >= gridSize[i]) {
911
            /*
912
             * There is no scrollable stuff in this dimension.
913
             */
914
            scrollInfo[i].max    = 0;
915
            scrollInfo[i].window = 1.0;
916
            continue;
917
        }
918
 
919
        visibleSize = winSize[i];
920
 
921
        for (count=0,k=gridSize[i]-1; k>=wPtr->hdrSize[i]&&k>=0; count++,k--) {
922
            winSize[i] -= TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
923
                k, &wPtr->defSize[i], &pad0, &pad1);
924
            winSize[i] -= pad0 + pad1;
925
 
926
            if (winSize[i] == 0) {
927
                ++ count;
928
                break;
929
            }
930
            else if (winSize[i] < 0) {
931
                break;
932
            }
933
        }
934
 
935
        if (count == 0) {
936
            /*
937
             * There is only one scrollable element and it is  *partially*
938
             * visible.
939
             */
940
            count = 1;
941
        }
942
        scrollInfo[i].max  = (gridSize[i]-wPtr->hdrSize[i]) - count;
943
 
944
        /*
945
         * calculate the total pixel size  (%%SLOOOOOOW)
946
         */
947
        for (totalSize=0,k=wPtr->hdrSize[i];k<gridSize[i];k++) {
948
            totalSize += TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
949
                k, &wPtr->defSize[i], &pad0, &pad1);
950
            totalSize += pad0 + pad1;
951
        }
952
 
953
        /*
954
         *we may need some left over spaces after the last element.
955
         */
956
        totalSize += (-winSize[i]);
957
 
958
        scrollInfo[i].window =
959
          (double)(visibleSize) / (double)totalSize;
960
    }
961
    for (i=0; i<2; i++) {
962
        if (scrollInfo[i].offset < 0) {
963
            scrollInfo[i].offset  = 0;
964
        }
965
        if (scrollInfo[i].offset > scrollInfo[i].max) {
966
            scrollInfo[i].offset = scrollInfo[i].max;
967
        }
968
    }
969
}
970
 
971
 
972
/*
973
 *--------------------------------------------------------------
974
 *
975
 * WidgetComputeGeometry --
976
 *
977
 *      This procedure is invoked to process the Tcl command
978
 *      that corresponds to a widget managed by this module.
979
 *      See the user documentation for details on what it does.
980
 *
981
 * Results:
982
 *      A standard Tcl result.
983
 *
984
 * Side effects:
985
 *      none
986
 *
987
 *--------------------------------------------------------------
988
 */
989
static void
990
WidgetComputeGeometry(clientData)
991
    ClientData clientData;
992
{
993
    WidgetPtr wPtr = (WidgetPtr)clientData;
994
    int i, k;
995
    int gridSize[2];
996
    int req[2], pad0, pad1;
997
    Tk_Window tkwin = wPtr->dispData.tkwin;
998
 
999
    TixGridDataGetGridSize(wPtr->dataSet, &gridSize[0],
1000
        &gridSize[1]);
1001
 
1002
    for (i=0; i<2; i++) {
1003
        int end = wPtr->reqSize[i];
1004
        if (end == 0) {
1005
            end = gridSize[0] + 1;
1006
        }
1007
        for (req[i]=0,k=0; k<end; k++) {
1008
            req[i] += TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
1009
                k, &wPtr->defSize[i], &pad0, &pad1);
1010
            req[i] += pad0 + pad1;
1011
        }
1012
 
1013
        req[i] += 2*(wPtr->highlightWidth + wPtr->borderWidth);
1014
    }
1015
 
1016
    if (Tk_ReqWidth(tkwin) != req[0] || Tk_ReqHeight(tkwin) != req[0]) {
1017
        Tk_GeometryRequest(tkwin, req[0], req[1]);
1018
    }
1019
 
1020
    /* arrange for the widget to be redrawn */
1021
    wPtr->toResetRB      = 1;
1022
    wPtr->toComputeSel   = 1;
1023
    wPtr->toRedrawHighlight = 1;
1024
 
1025
    Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
1026
}
1027
 
1028
static void
1029
Tix_GrResetRenderBlocks(wPtr)
1030
    WidgetPtr wPtr;
1031
{
1032
    int winW, winH, exactW, exactH;
1033
    Tk_Window tkwin = wPtr->dispData.tkwin;
1034
 
1035
    winW = Tk_Width (tkwin) - 2*wPtr->highlightWidth - 2*wPtr->borderWidth;
1036
    winH = Tk_Height(tkwin) - 2*wPtr->highlightWidth - 2*wPtr->borderWidth;
1037
 
1038
    RecalScrollRegion(wPtr, winW, winH, wPtr->scrollInfo);
1039
 
1040
    UpdateScrollBars(wPtr, 1);
1041
 
1042
    if (wPtr->mainRB) {
1043
        Tix_GrFreeRenderBlock(wPtr, wPtr->mainRB);
1044
    }
1045
    wPtr->mainRB = Tix_GrAllocateRenderBlock(wPtr, winW, winH,&exactW,&exactH);
1046
 
1047
    wPtr->expArea.x1 = 0;
1048
    wPtr->expArea.y1 = 0;
1049
    wPtr->expArea.x2 = Tk_Width (wPtr->dispData.tkwin) - 1;
1050
    wPtr->expArea.y2 = Tk_Height(wPtr->dispData.tkwin) - 1;
1051
}
1052
 
1053
/*----------------------------------------------------------------------
1054
 * DItemSizeChanged --
1055
 *
1056
 *      This is called whenever the size of one of the HList's items
1057
 *      changes its size.
1058
 *----------------------------------------------------------------------
1059
 */
1060
static void
1061
Tix_GrDItemSizeChanged(iPtr)
1062
    Tix_DItem *iPtr;
1063
{
1064
    WidgetPtr wPtr = (WidgetPtr)iPtr->base.clientData;
1065
 
1066
    if (wPtr) {
1067
        /* double-check: perhaps we haven't set the clientData yet! */
1068
        Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
1069
    }
1070
}
1071
 
1072
/*
1073
 *----------------------------------------------------------------------
1074
 * Tix_GrDoWhenIdle --
1075
 *----------------------------------------------------------------------
1076
 */
1077
void
1078
Tix_GrDoWhenIdle(wPtr, type)
1079
    WidgetPtr wPtr;
1080
    int type;
1081
{
1082
    switch (type) {
1083
      case TIX_GR_RESIZE:
1084
        wPtr->toResize = 1;
1085
        break;
1086
      case TIX_GR_REDRAW:
1087
        wPtr->toRedraw = 1;
1088
        break;
1089
    }
1090
 
1091
    if (!wPtr->idleEvent) {
1092
        wPtr->idleEvent = 1;
1093
        Tk_DoWhenIdle(IdleHandler, (ClientData)wPtr);
1094
    }
1095
}
1096
 
1097
static void
1098
IdleHandler(clientData)
1099
    ClientData clientData;      /* Info about my widget. */
1100
{
1101
    WidgetPtr wPtr = (WidgetPtr) clientData;
1102
 
1103
    if (!wPtr->idleEvent) {     /* sanity check */
1104
        return;
1105
    }
1106
    wPtr->idleEvent = 0;
1107
 
1108
    if (wPtr->toResize) {
1109
        wPtr->toResize = 0;
1110
        WidgetComputeGeometry(clientData);
1111
    }
1112
    else if (wPtr->toRedraw) {
1113
        wPtr->toRedraw = 0;
1114
        WidgetDisplay(clientData);
1115
    }
1116
}
1117
 
1118
/*
1119
 *----------------------------------------------------------------------
1120
 * Tix_GrCancelDoWhenIdle --
1121
 *----------------------------------------------------------------------
1122
 */
1123
void
1124
Tix_GrCancelDoWhenIdle(wPtr)
1125
    WidgetPtr wPtr;
1126
{
1127
    wPtr->toResize = 0;
1128
    wPtr->toRedraw = 0;
1129
 
1130
    if (wPtr->idleEvent) {
1131
        Tk_CancelIdleCall(IdleHandler, (ClientData)wPtr);
1132
        wPtr->idleEvent = 0;
1133
    }
1134
}
1135
 
1136
/*----------------------------------------------------------------------
1137
 * WidgetDisplay --
1138
 *
1139
 *      Display the widget: the borders, the background and the entries.
1140
 *
1141
 *----------------------------------------------------------------------
1142
 */
1143
static void
1144
WidgetDisplay(clientData)
1145
    ClientData clientData;      /* Info about my widget. */
1146
{
1147
    WidgetPtr wPtr = (WidgetPtr) clientData;
1148
    Drawable buffer = None;
1149
    Tk_Window tkwin = wPtr->dispData.tkwin;
1150
    int winH, winW, expW, expH;
1151
    GC highlightGC;
1152
 
1153
    if (!Tk_IsMapped(tkwin)) {
1154
        return;
1155
    }
1156
    wPtr->serial ++;
1157
 
1158
    winW = Tk_Width(tkwin)  - 2*wPtr->highlightWidth - 2*wPtr->borderWidth;
1159
    winH = Tk_Height(tkwin) - 2*wPtr->highlightWidth - 2*wPtr->borderWidth;
1160
 
1161
    if (winW <= 0 || winH <= 0) { /* nothing to draw */
1162
        goto done;
1163
    }
1164
 
1165
    if (wPtr->toResetRB) {
1166
        Tix_GrResetRenderBlocks(wPtr);
1167
        wPtr->toResetRB = 0;
1168
    }
1169
    if (wPtr->toComputeSel) {
1170
        Tix_GrComputeSelection(wPtr);
1171
        wPtr->toComputeSel = 0;
1172
    }
1173
 
1174
    /* clip the exposed area to the visible part of the widget,
1175
     * just in case some of the routines had made it larger than
1176
     * it should be
1177
     */
1178
    if (wPtr->expArea.x1 < wPtr->bdPad) {
1179
        wPtr->expArea.x1 = wPtr->bdPad;
1180
    }
1181
    if (wPtr->expArea.y1 < wPtr->bdPad) {
1182
        wPtr->expArea.y1 = wPtr->bdPad;
1183
    }
1184
    if (wPtr->expArea.x2 >= Tk_Width(tkwin)  - wPtr->bdPad) {
1185
        wPtr->expArea.x2  = Tk_Width(tkwin)  - wPtr->bdPad - 1;
1186
    }
1187
    if (wPtr->expArea.y2 >= Tk_Height(tkwin) - wPtr->bdPad) {
1188
        wPtr->expArea.y2  = Tk_Height(tkwin) - wPtr->bdPad - 1;
1189
    }
1190
 
1191
    expW = wPtr->expArea.x2 - wPtr->expArea.x1 + 1;
1192
    expH = wPtr->expArea.y2 - wPtr->expArea.y1 + 1;
1193
 
1194
    if (expW <= 0 || expH <= 0) { /* no cells to draw */
1195
        goto drawBorder;
1196
    }
1197
 
1198
    buffer = Tix_GetRenderBuffer(wPtr->dispData.display, Tk_WindowId(tkwin),
1199
        expW, expH, Tk_Depth(tkwin));
1200
 
1201
    if (buffer == Tk_WindowId(tkwin)) {
1202
        /* clear the window directly */
1203
        XFillRectangle(wPtr->dispData.display, buffer, wPtr->backgroundGC,
1204
            wPtr->expArea.x1, wPtr->expArea.y1, expW, expH);
1205
    } else {
1206
        XFillRectangle(wPtr->dispData.display, buffer, wPtr->backgroundGC,
1207
            0, 0, expW, expH);
1208
    }
1209
 
1210
    if (wPtr->mainRB) {
1211
        Tix_GrDisplayMainBody(wPtr, buffer, winW, winH);
1212
    }
1213
 
1214
    if (buffer != Tk_WindowId(tkwin)) {
1215
        XCopyArea(wPtr->dispData.display, buffer, Tk_WindowId(tkwin),
1216
            wPtr->backgroundGC, 0, 0, expW, expH,
1217
            wPtr->expArea.x1, wPtr->expArea.y1);
1218
        Tk_FreePixmap(wPtr->dispData.display, buffer);
1219
    }
1220
 
1221
  drawBorder:
1222
    Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), wPtr->border,
1223
        wPtr->highlightWidth,
1224
        wPtr->highlightWidth,
1225
        Tk_Width(tkwin)  - 2*wPtr->highlightWidth,
1226
        Tk_Height(tkwin) - 2*wPtr->highlightWidth,
1227
        wPtr->borderWidth, wPtr->relief);
1228
 
1229
    if (wPtr->toRedrawHighlight && wPtr->highlightWidth > 0) {
1230
        if (wPtr->hasFocus) {
1231
            highlightGC = wPtr->highlightGC;
1232
        } else {
1233
            highlightGC = Tk_3DBorderGC(tkwin, wPtr->border,
1234
                TK_3D_FLAT_GC);
1235
        }
1236
 
1237
        Tk_DrawFocusHighlight(tkwin, highlightGC, wPtr->highlightWidth,
1238
            Tk_WindowId(tkwin));
1239
    }
1240
 
1241
  done:
1242
    wPtr->expArea.x1 = 10000;
1243
    wPtr->expArea.y1 = 10000;
1244
    wPtr->expArea.x2 = 0;
1245
    wPtr->expArea.y2 = 0;
1246
}
1247
 
1248
/*
1249
 *----------------------------------------------------------------------
1250
 *
1251
 * Tix_GrDisplayMainBody  --
1252
 *
1253
 *      Draw the background and cells
1254
 *
1255
 * Results:
1256
 *      None.
1257
 *
1258
 * Side effects:
1259
 *
1260
 *----------------------------------------------------------------------
1261
 */
1262
static void Tix_GrDisplayMainBody(wPtr, buffer, winW, winH)
1263
    WidgetPtr wPtr;
1264
    Drawable buffer;
1265
    int winW;
1266
    int winH;
1267
{
1268
    Tk_Window tkwin = wPtr->dispData.tkwin;
1269
    RenderInfo mainRI;                  /* render info for main body */
1270
    int i, j;
1271
 
1272
    if (buffer == Tk_WindowId(tkwin)) {
1273
        /* rendering directly into the window */
1274
        mainRI.origin[0] = wPtr->highlightWidth + wPtr->borderWidth;
1275
        mainRI.origin[1] = wPtr->highlightWidth + wPtr->borderWidth;
1276
 
1277
    } else {
1278
        /* rendering into a pixmap */
1279
        mainRI.origin[0] = wPtr->highlightWidth + wPtr->borderWidth
1280
            - wPtr->expArea.x1;
1281
        mainRI.origin[1] = wPtr->highlightWidth + wPtr->borderWidth
1282
            - wPtr->expArea.y1;
1283
    }
1284
 
1285
    mainRI.drawable = buffer;
1286
    wPtr->colorInfoCounter ++;
1287
 
1288
    wPtr->renderInfo = &mainRI;
1289
 
1290
    /* 1. Draw the backgrounds
1291
     */
1292
    for (i=0; i<wPtr->mainRB->size[0]; i++) {
1293
        for (j=0; j<wPtr->mainRB->size[1]; j++) {
1294
            wPtr->mainRB->elms[i][j].borderW[0][0] = 0;
1295
            wPtr->mainRB->elms[i][j].borderW[1][0] = 0;
1296
            wPtr->mainRB->elms[i][j].borderW[0][1] = 0;
1297
            wPtr->mainRB->elms[i][j].borderW[1][1] = 0;
1298
            wPtr->mainRB->elms[i][j].filled        = 0;
1299
        }
1300
    }
1301
    Tix_GrDrawBackground(wPtr, &mainRI, buffer);
1302
 
1303
    /* 2. Draw the cells
1304
     */
1305
    Tix_GrDrawCells(wPtr, &mainRI, buffer);
1306
 
1307
    /* 3. Draw the special sites (anchor, drag, drop).
1308
     */
1309
    Tix_GrDrawSites(wPtr, &mainRI, buffer);
1310
 
1311
    /* done */
1312
    wPtr->renderInfo = NULL;
1313
 
1314
    /* Free the unwanted colors: they are left overs from the "format"
1315
     * widget command.
1316
     */
1317
    Tix_GrFreeUnusedColors(wPtr, 0);
1318
}
1319
 
1320
/*----------------------------------------------------------------------
1321
 * Tix_GrDrawCells --
1322
 *
1323
 *      Redraws the cells of the Grid
1324
 *----------------------------------------------------------------------
1325
 */
1326
static void Tix_GrDrawCells(wPtr, riPtr, drawable)
1327
    WidgetPtr wPtr;
1328
    RenderInfo * riPtr;
1329
    Drawable drawable;
1330
{
1331
    int x, y, i, j;
1332
    int x1, y1, x2, y2;
1333
    TixGrEntry * chPtr;
1334
    int margin = wPtr->borderWidth + wPtr->highlightWidth;
1335
 
1336
    for (x=0,i=0; i<wPtr->mainRB->size[0]; i++) {
1337
        x1 = x  + margin;
1338
        x2 = x1 - 1 + wPtr->mainRB->dispSize[0][i].total;
1339
 
1340
        if (x1 > wPtr->expArea.x2) {
1341
            goto nextCol;
1342
        }
1343
        if (x2 < wPtr->expArea.x1) {
1344
            goto nextCol;
1345
        }
1346
        /*
1347
         * iterate over the columns
1348
         */
1349
        for (y=0,j=0; j<wPtr->mainRB->size[1]; j++) {
1350
            /*
1351
             * iterate over each item in the column, from top
1352
             * to bottom
1353
             */
1354
            y1 = y  + margin;
1355
            y2 = y1 - 1 + wPtr->mainRB->dispSize[1][j].total;
1356
 
1357
            if (y1 > wPtr->expArea.y2) {
1358
                goto nextRow;
1359
            }
1360
            if (y2 < wPtr->expArea.y1) {
1361
                goto nextRow;
1362
            }
1363
            if (!wPtr->mainRB->elms[i][j].filled) {
1364
                if (wPtr->mainRB->elms[i][j].selected) {
1365
 
1366
                    Tk_Fill3DRectangle(wPtr->dispData.tkwin,
1367
                        drawable, wPtr->selectBorder,
1368
                        x+riPtr->origin[0]+
1369
                            wPtr->mainRB->elms[i][j].borderW[0][0],
1370
                        y+riPtr->origin[1]+
1371
                            wPtr->mainRB->elms[i][j].borderW[1][0],
1372
                        wPtr->mainRB->dispSize[0][i].total -
1373
                            wPtr->mainRB->elms[i][j].borderW[0][0] -
1374
                            wPtr->mainRB->elms[i][j].borderW[0][1],
1375
                        wPtr->mainRB->dispSize[1][j].total -
1376
                            wPtr->mainRB->elms[i][j].borderW[1][0] -
1377
                            wPtr->mainRB->elms[i][j].borderW[1][1],
1378
                        0, TK_RELIEF_FLAT);
1379
                }
1380
            }
1381
 
1382
            chPtr = wPtr->mainRB->elms[i][j].chPtr;
1383
            if (chPtr != NULL) {
1384
                if (Tix_DItemType(chPtr->iPtr) == TIX_DITEM_WINDOW) {
1385
                    Tix_DItemDisplay(Tk_WindowId(wPtr->dispData.tkwin), None,
1386
                        chPtr->iPtr, x1, y1,
1387
                        wPtr->mainRB->dispSize[0][i].size,
1388
                        wPtr->mainRB->dispSize[1][j].size,
1389
                        TIX_DITEM_NORMAL_FG);
1390
                } else {
1391
                    int drawX, drawY;
1392
                    drawX = x + riPtr->origin[0] +
1393
                        wPtr->mainRB->dispSize[0][i].preBorder;
1394
                    drawY = y + riPtr->origin[1] +
1395
                        wPtr->mainRB->dispSize[1][j].preBorder;
1396
 
1397
                    Tix_DItemDisplay(drawable, None, chPtr->iPtr,
1398
                        drawX, drawY,
1399
                        wPtr->mainRB->dispSize[0][i].size,
1400
                        wPtr->mainRB->dispSize[1][j].size,
1401
                        TIX_DITEM_NORMAL_FG);
1402
                }
1403
            }
1404
          nextRow:
1405
            y+= wPtr->mainRB->dispSize[1][j].total;
1406
        }
1407
      nextCol:
1408
        x+= wPtr->mainRB->dispSize[0][i].total;
1409
    }
1410
 
1411
    for (i=0; i<wPtr->mainRB->size[0]; i++) {
1412
        for (j=0; j<wPtr->mainRB->size[1]; j++) {
1413
            chPtr = wPtr->mainRB->elms[i][j].chPtr;
1414
            if (chPtr != NULL) {
1415
                if (Tix_DItemType(chPtr->iPtr) == TIX_DITEM_WINDOW) {
1416
 
1417
                    Tix_SetWindowItemSerial(&wPtr->mappedWindows,
1418
                        chPtr->iPtr, wPtr->serial);
1419
                }
1420
            }
1421
        }
1422
    }
1423
 
1424
    /* unmap those windows we mapped the last time */
1425
    Tix_UnmapInvisibleWindowItems(&wPtr->mappedWindows, wPtr->serial);
1426
}
1427
 
1428
/*----------------------------------------------------------------------
1429
 * Tix_GrDrawSites --
1430
 *
1431
 *      Redraws the special sites (anchor, drag, drop)
1432
 *----------------------------------------------------------------------
1433
 */
1434
static void Tix_GrDrawSites(wPtr, riPtr, drawable)
1435
    WidgetPtr wPtr;
1436
    RenderInfo * riPtr;
1437
    Drawable drawable;
1438
{
1439
    int rect[2][2];
1440
    int visible;
1441
 
1442
    visible = Tix_GrGetElementPosn(wPtr, wPtr->anchor[0], wPtr->anchor[1],
1443
        rect, 0, 1, 0, 0);
1444
    if (!visible) {
1445
        return;
1446
    }
1447
 
1448
    Tix_DrawAnchorLines(Tk_Display(wPtr->dispData.tkwin), drawable,
1449
        wPtr->anchorGC,
1450
        rect[0][0] + riPtr->origin[0],
1451
        rect[1][0] + riPtr->origin[1],
1452
        rect[0][1] - rect[0][0] + 1,
1453
        rect[1][1] - rect[1][0] + 1);
1454
}
1455
 
1456
/*----------------------------------------------------------------------
1457
 *
1458
 * Tix_GrGetElementPosn --
1459
 *
1460
 *      Returns the position of a visible element on the screen.
1461
 *
1462
 * Arguments
1463
 *      x,y:    index of the element.
1464
 *      rect:   stores the return values: four sides of the cell.
1465
 *      clipOK: if true and element is only partially visible, return only
1466
 *              the visible portion.
1467
 *      isSite: if (x,y) is a site, the return value depends on the
1468
 *              selectUnit variable.
1469
 *      isScr:  should we return the position within the widget (true)
1470
 *              or within the main display area (false).
1471
 *      nearest:if the element is outside of the widget, should we return
1472
 *              the position of the nearest element?
1473
 *
1474
 *----------------------------------------------------------------------
1475
 */
1476
 
1477
int
1478
Tix_GrGetElementPosn(wPtr, x, y, rect, clipOK, isSite, isScr, nearest)
1479
    WidgetPtr wPtr;
1480
    int x;
1481
    int y;
1482
    int rect[2][2];
1483
    int clipOK;         /* %% ignored */
1484
    int isSite;
1485
    int isScr;
1486
    int nearest;
1487
{
1488
    int i, j, pos[2];
1489
    int axis;
1490
    int useAxis;
1491
 
1492
    if (wPtr->selectUnit == tixRowUid) {
1493
        axis = 0;
1494
        useAxis = 1;
1495
    }
1496
    else if (wPtr->selectUnit == tixColumnUid) {
1497
        axis = 1;
1498
        useAxis = 1;
1499
    }
1500
    else {
1501
        useAxis = 0;
1502
    }
1503
 
1504
    /* %% didn't take care of the headers, etc */
1505
 
1506
    pos[0] = x;
1507
    pos[1] = y;
1508
 
1509
    /* clip the anchor site with the visible cells */
1510
    for (i=0; i<2; i++) {
1511
        if (pos[i] == TIX_SITE_NONE) {
1512
            return 0;
1513
        }
1514
 
1515
        if (isSite && useAxis && i == axis) {
1516
            rect[i][0] = 0;
1517
            rect[i][1] = wPtr->mainRB->visArea[i]-1;
1518
        } else {
1519
            if (pos[i] >= wPtr->hdrSize[i]) {
1520
                pos[i] -= wPtr->scrollInfo[i].offset;
1521
                if (pos[i] < wPtr->hdrSize[i]) {
1522
                    /* This cell has been scrolled "under the margins" */
1523
                    return 0;
1524
                }
1525
            }
1526
 
1527
            if (pos[i] < 0) {
1528
                if (!nearest) {
1529
                    return 0;
1530
                }
1531
                pos[i] = 0;
1532
            }
1533
            if (pos[i] >= wPtr->mainRB->size[i]) {
1534
                if (!nearest) {
1535
                    return 0;
1536
                }
1537
                pos[i] = wPtr->mainRB->size[i] - 1;
1538
            }
1539
            rect[i][0] = 0;
1540
            for (j=0; j<pos[i]; j++) {
1541
                rect[i][0] += wPtr->mainRB->dispSize[i][j].total;
1542
            }
1543
            rect[i][1] = rect[i][0] + wPtr->mainRB->dispSize[i][j].total - 1;
1544
        }
1545
    }
1546
 
1547
    if (isScr) {
1548
        rect[0][0] += wPtr->bdPad;
1549
        rect[1][0] += wPtr->bdPad;
1550
        rect[0][1] += wPtr->bdPad;
1551
        rect[1][1] += wPtr->bdPad;
1552
    }
1553
 
1554
    return 1;
1555
}
1556
 
1557
/*----------------------------------------------------------------------
1558
 *
1559
 * "bdtype" sub command --
1560
 *
1561
 *      Returns if the the screen position is at a border. This is useful
1562
 *      for changing the mouse cursor when the user points at a border
1563
 *      area. This indicates that the border can be adjusted interactively.
1564
 *
1565
 *----------------------------------------------------------------------
1566
 */
1567
static int
1568
Tix_GrBdType(clientData, interp, argc, argv)
1569
    ClientData clientData;
1570
    Tcl_Interp *interp;         /* Current interpreter. */
1571
    int argc;                   /* Number of arguments. */
1572
    char **argv;                /* Argument strings. */
1573
{
1574
    WidgetPtr wPtr = (WidgetPtr) clientData;
1575
    Tk_Window tkwin = wPtr->dispData.tkwin;
1576
    int i, k, screenPos[2], bd[2], pos[2], in[2], bdWidth[2];
1577
    char buf[100];
1578
    int inX = 0;
1579
    int inY = 0;
1580
 
1581
    if (argc != 2 && argc != 4) {
1582
        return Tix_ArgcError(interp, argc+2, argv-2, 2,
1583
            "x y ?xbdWidth ybdWidth?");
1584
    }
1585
 
1586
    if (Tcl_GetInt(interp, argv[0], &screenPos[0]) != TCL_OK) {
1587
        return TCL_ERROR;
1588
    }
1589
    if (Tcl_GetInt(interp, argv[1], &screenPos[1]) != TCL_OK) {
1590
        return TCL_ERROR;
1591
    }
1592
    if (argc == 4) {
1593
        if (Tcl_GetInt(interp, argv[2], &bdWidth[0]) != TCL_OK) {
1594
            return TCL_ERROR;
1595
        }
1596
        if (Tcl_GetInt(interp, argv[3], &bdWidth[1]) != TCL_OK) {
1597
            return TCL_ERROR;
1598
        }
1599
    } else {
1600
        bdWidth[0] = -1;
1601
        bdWidth[1] = -1;
1602
    }
1603
 
1604
    if (!Tk_IsMapped(tkwin)) {
1605
        Tcl_ResetResult(interp);
1606
        return TCL_OK;
1607
    }
1608
 
1609
    if (wPtr->mainRB == NULL || wPtr->toResetRB) {
1610
        Tix_GrResetRenderBlocks(wPtr);
1611
        wPtr->toResetRB = 0;
1612
    }
1613
 
1614
    screenPos[0] -= wPtr->highlightWidth - wPtr->borderWidth;
1615
    screenPos[1] -= wPtr->highlightWidth - wPtr->borderWidth;
1616
 
1617
    for (i=0; i<2; i++) {
1618
        bd[i]  = -1;
1619
        pos[i] = 0;
1620
        in[i]  = 0;
1621
        for (k=0; k<wPtr->mainRB->size[i]; k++) {
1622
            ElmDispSize * elm = &wPtr->mainRB->dispSize[i][k];
1623
            if (screenPos[i] - elm->total <= 0) {
1624
                if (bdWidth[i] != -1) {
1625
                    if (screenPos[i] < bdWidth[i]) {
1626
                        bd[i]  = k - 1;
1627
                        pos[i] = k;
1628
                    }
1629
                    else if ((elm->total - screenPos[i]) <= bdWidth[i]) {
1630
                        bd[i]  = k;
1631
                        pos[i] = k + 1;
1632
                    }
1633
                    else {
1634
                        pos[i] = k;
1635
                    }
1636
                } else {
1637
                    if (screenPos[i] < elm->preBorder) {
1638
                        bd[i]  = k - 1;
1639
                        pos[i] = k;
1640
                    }
1641
                    else if ((screenPos[i] - elm->preBorder - elm->size)>= 0) {
1642
                        bd[i]  = k;
1643
                        pos[i] = k + 1;
1644
                    }
1645
                    else {
1646
                        pos[i] = k;
1647
                    }
1648
                }
1649
                in[i] = k;
1650
                break;
1651
            } else {
1652
                screenPos[i] -= elm->total;
1653
            }
1654
        }
1655
    }
1656
 
1657
    if (in[0] < wPtr->hdrSize[0] && bd[1] >= 0) {
1658
        inY = 1;
1659
    }
1660
    else if (in[1] < wPtr->hdrSize[1] && bd[0] >= 0) {
1661
        inX = 1;
1662
    }
1663
 
1664
    if (bd[0] < 0) {
1665
        bd[0] = 0;
1666
    }
1667
    if (bd[1] < 0) {
1668
        bd[1] = 0;
1669
    }
1670
 
1671
    if (inX && inY) {
1672
        sprintf(buf, "xy %d %d", bd[0], bd[1]);
1673
    } else if (inX) {
1674
        sprintf(buf, "x %d %d", bd[0], bd[1]);
1675
    } else if (inY) {
1676
        sprintf(buf, "y %d %d", bd[0], bd[1]);
1677
    } else {
1678
        buf[0] = '\0';
1679
    }
1680
 
1681
    Tcl_ResetResult(interp);
1682
    Tcl_AppendResult(interp, buf, NULL);
1683
 
1684
    return TCL_OK;
1685
}
1686
 
1687
/*----------------------------------------------------------------------
1688
 * "set" sub command --
1689
 *
1690
 *      Sets the item at the position on the grid. This either creates
1691
 *      a new element or modifies the existing element. (if you don't want
1692
 *      to change the -itemtype of the existing element, it will be more
1693
 *      efficient to call the "itemconfigure" command).
1694
 *----------------------------------------------------------------------
1695
 */
1696
static int
1697
Tix_GrSet(clientData, interp, argc, argv)
1698
    ClientData clientData;
1699
    Tcl_Interp *interp;         /* Current interpreter. */
1700
    int argc;                   /* Number of arguments. */
1701
    char **argv;                /* Argument strings. */
1702
{
1703
    WidgetPtr wPtr = (WidgetPtr) clientData;
1704
    TixGrEntry * chPtr = NULL;
1705
    Tix_DItem * iPtr;
1706
    int x, y;
1707
    char * ditemType;
1708
    int code = TCL_OK;
1709
 
1710
    /*------------------------------------------------------------
1711
     * (0) We need to find out where you want to set
1712
     *------------------------------------------------------------
1713
     */
1714
    if (TixGridDataGetIndex(interp, wPtr, argv[0], argv[1], &x, &y)!=TCL_OK) {
1715
        return TCL_ERROR;
1716
    }
1717
 
1718
    /*------------------------------------------------------------
1719
     * (1) We need to determine the option: -itemtype.
1720
     *------------------------------------------------------------
1721
     */
1722
    /* (1.0) Find out the -itemtype, if specified */
1723
    ditemType = wPtr->diTypePtr->name;                   /* default value */
1724
    if (argc > 2) {
1725
        size_t len;
1726
        int i;
1727
        if (argc %2 != 0) {
1728
            Tcl_AppendResult(interp, "value for \"", argv[argc-1],
1729
                "\" missing", NULL);
1730
            code = TCL_ERROR;
1731
            goto done;
1732
        }
1733
        for (i=2; i<argc; i+=2) {
1734
            len = strlen(argv[i]);
1735
            if (strncmp(argv[i], "-itemtype", len) == 0) {
1736
                ditemType = argv[i+1];
1737
            }
1738
        }
1739
    }
1740
 
1741
    if (Tix_GetDItemType(interp, ditemType) == NULL) {
1742
        code = TCL_ERROR;
1743
        goto done;
1744
    }
1745
 
1746
    /*
1747
     * (2) Get this item (a new item will be allocated if it does not exist
1748
     *     yet)
1749
     */
1750
    chPtr = Tix_GrFindCreateElem(interp, wPtr, x, y);
1751
 
1752
    /* (2.1) The Display item data */
1753
    if ((iPtr = Tix_DItemCreate(&wPtr->dispData, ditemType)) == NULL) {
1754
        code = TCL_ERROR;
1755
        goto done;
1756
    }
1757
    iPtr->base.clientData = (ClientData)wPtr;     /* %%%% */
1758
 
1759
    if (chPtr->iPtr) {
1760
        Tix_DItemFree(chPtr->iPtr);
1761
    }
1762
    chPtr->iPtr = iPtr;
1763
 
1764
    if (ConfigElement(wPtr, chPtr, argc-2, argv+2, 0, 1) != TCL_OK) {
1765
        code = TCL_ERROR; goto done;
1766
    }
1767
    Tix_GrPropagateSize(wPtr, chPtr);
1768
 
1769
  done:
1770
    if (code == TCL_ERROR) {
1771
        /* ? */
1772
    } else {
1773
        Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
1774
    }
1775
 
1776
    return code;
1777
}
1778
 
1779
/*----------------------------------------------------------------------
1780
 * "unset" sub command
1781
 *----------------------------------------------------------------------
1782
 */
1783
 
1784
static int
1785
Tix_GrUnset(clientData, interp, argc, argv)
1786
    ClientData clientData;
1787
    Tcl_Interp *interp;         /* Current interpreter. */
1788
    int argc;                   /* Number of arguments. */
1789
    char **argv;                /* Argument strings. */
1790
{
1791
    WidgetPtr wPtr = (WidgetPtr) clientData;
1792
    TixGrEntry * chPtr;
1793
    int x, y;
1794
 
1795
    if (TixGridDataGetIndex(interp, wPtr, argv[0], argv[1], &x, &y)
1796
            !=TCL_OK) {
1797
        return TCL_ERROR;
1798
    }
1799
 
1800
    chPtr = Tix_GrFindElem(interp, wPtr, x, y);
1801
    if (chPtr != NULL) {
1802
        TixGridDataDeleteEntry(wPtr->dataSet, x, y);
1803
        Tix_GrFreeElem(chPtr);
1804
        Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
1805
    }
1806
    return TCL_OK;
1807
}
1808
 
1809
/*----------------------------------------------------------------------
1810
 * "cget" sub command --
1811
 *----------------------------------------------------------------------
1812
 */
1813
static int
1814
Tix_GrCGet(clientData, interp, argc, argv)
1815
    ClientData clientData;
1816
    Tcl_Interp *interp;         /* Current interpreter. */
1817
    int argc;                   /* Number of arguments. */
1818
    char **argv;                /* Argument strings. */
1819
{
1820
    WidgetPtr wPtr = (WidgetPtr) clientData;
1821
 
1822
    return Tk_ConfigureValue(interp, wPtr->dispData.tkwin, configSpecs,
1823
        (char *)wPtr, argv[0], 0);
1824
}
1825
 
1826
/*----------------------------------------------------------------------
1827
 * "configure" sub command
1828
 *----------------------------------------------------------------------
1829
 */
1830
static int
1831
Tix_GrConfig(clientData, interp, argc, argv)
1832
    ClientData clientData;
1833
    Tcl_Interp *interp;         /* Current interpreter. */
1834
    int argc;                   /* Number of arguments. */
1835
    char **argv;                /* Argument strings. */
1836
{
1837
    WidgetPtr wPtr = (WidgetPtr) clientData;
1838
 
1839
    if (argc == 0) {
1840
        return Tk_ConfigureInfo(interp, wPtr->dispData.tkwin, configSpecs,
1841
            (char *) wPtr, (char *) NULL, 0);
1842
    } else if (argc == 1) {
1843
        return Tk_ConfigureInfo(interp, wPtr->dispData.tkwin, configSpecs,
1844
            (char *) wPtr, argv[0], 0);
1845
    } else {
1846
        return WidgetConfigure(interp, wPtr, argc, argv,
1847
            TK_CONFIG_ARGV_ONLY);
1848
    }
1849
}
1850
 
1851
/*----------------------------------------------------------------------
1852
 * "delete" sub command
1853
 *----------------------------------------------------------------------
1854
 */
1855
static int
1856
Tix_GrDelete(clientData, interp, argc, argv)
1857
    ClientData clientData;
1858
    Tcl_Interp *interp;         /* Current interpreter. */
1859
    int argc;                   /* Number of arguments. */
1860
    char **argv;                /* Argument strings. */
1861
{
1862
    WidgetPtr wPtr = (WidgetPtr) clientData;
1863
    int from, to, which;
1864
 
1865
    if (TranslateFromTo(interp, wPtr, argc, argv, &from, &to, &which)!=TCL_OK){
1866
        return TCL_ERROR;
1867
    }
1868
    TixGridDataDeleteRange(wPtr, wPtr->dataSet, which, from, to);
1869
 
1870
    return TCL_OK;
1871
}
1872
 
1873
/*----------------------------------------------------------------------
1874
 * "edit" sub command
1875
 *----------------------------------------------------------------------
1876
 */
1877
static int
1878
Tix_GrEdit(clientData, interp, argc, argv)
1879
    ClientData clientData;
1880
    Tcl_Interp *interp;         /* Current interpreter. */
1881
    int argc;                   /* Number of arguments. */
1882
    char **argv;                /* Argument strings. */
1883
{
1884
    WidgetPtr wPtr = (WidgetPtr) clientData;
1885
    int x, y;
1886
    Tcl_DString dstring;
1887
    char buff[20];
1888
    int len, code;
1889
 
1890
    len = strlen(argv[0]);
1891
    if (strncmp(argv[0], "set", len) == 0) {
1892
        if (argc != 3) {
1893
            Tcl_AppendResult(interp, "wrong # of arguments, must be: ",
1894
                argv[-2], " edit set x y", NULL);
1895
        }
1896
        if (TixGridDataGetIndex(interp, wPtr, argv[1], argv[2], &x, &y)
1897
                !=TCL_OK) {
1898
            return TCL_ERROR;
1899
        }
1900
        Tcl_DStringInit(&dstring);
1901
 
1902
        Tcl_DStringAppendElement(&dstring, "tixGrid:EditCell");
1903
        Tcl_DStringAppendElement(&dstring, Tk_PathName(wPtr->dispData.tkwin));
1904
        sprintf(buff, "%d", x);
1905
        Tcl_DStringAppendElement(&dstring, buff);
1906
        sprintf(buff, "%d", y);
1907
        Tcl_DStringAppendElement(&dstring, buff);
1908
    } else if (strncmp(argv[0], "apply", len) == 0) {
1909
        if (argc != 1) {
1910
            Tcl_AppendResult(interp, "wrong # of arguments, must be: ",
1911
                argv[-2], " edit apply", NULL);
1912
        }
1913
        Tcl_DStringInit(&dstring);
1914
 
1915
        Tcl_DStringAppendElement(&dstring, "tixGrid:EditApply");
1916
        Tcl_DStringAppendElement(&dstring, Tk_PathName(wPtr->dispData.tkwin));
1917
    } else {
1918
        Tcl_AppendResult(interp, "unknown option \"", argv[0],
1919
                "\", must be apply or set", NULL);
1920
        return TCL_ERROR;
1921
    }
1922
 
1923
    code = Tcl_GlobalEval(interp, dstring.string);
1924
    Tcl_DStringFree(&dstring);
1925
 
1926
    return code;
1927
}
1928
 
1929
/*----------------------------------------------------------------------
1930
 * "entrycget" sub command
1931
 *----------------------------------------------------------------------
1932
 */
1933
static int
1934
Tix_GrEntryCget(clientData, interp, argc, argv)
1935
    ClientData clientData;
1936
    Tcl_Interp *interp;         /* Current interpreter. */
1937
    int argc;                   /* Number of arguments. */
1938
    char **argv;                /* Argument strings. */
1939
{
1940
    WidgetPtr wPtr = (WidgetPtr) clientData;
1941
    int x, y;
1942
    TixGrEntry * chPtr;
1943
 
1944
    if (TixGridDataGetIndex(interp, wPtr, argv[0], argv[1], &x, &y)!=TCL_OK) {
1945
        return TCL_ERROR;
1946
    }
1947
 
1948
    chPtr = Tix_GrFindElem(interp, wPtr, x, y);
1949
    if (!chPtr) {
1950
        Tcl_AppendResult(interp, "entry \"", argv[0], ",", argv[1],
1951
            "\" does not exist", NULL);
1952
        return TCL_ERROR;
1953
    }
1954
 
1955
    return Tix_ConfigureValue2(interp, wPtr->dispData.tkwin, (char *)chPtr,
1956
        entryConfigSpecs, chPtr->iPtr, argv[2], 0);
1957
}
1958
 
1959
/*----------------------------------------------------------------------
1960
 * "entryconfigure" sub command
1961
 *----------------------------------------------------------------------
1962
 */
1963
static int
1964
Tix_GrEntryConfig(clientData, interp, argc, argv)
1965
    ClientData clientData;
1966
    Tcl_Interp *interp;         /* Current interpreter. */
1967
    int argc;                   /* Number of arguments. */
1968
    char **argv;                /* Argument strings. */
1969
{
1970
    WidgetPtr wPtr = (WidgetPtr) clientData;
1971
    int x, y;
1972
    TixGrEntry * chPtr;
1973
 
1974
    if (TixGridDataGetIndex(interp, wPtr, argv[0], argv[1], &x, &y)!=TCL_OK) {
1975
        return TCL_ERROR;
1976
    }
1977
 
1978
    chPtr = Tix_GrFindElem(interp, wPtr, x, y);
1979
    if (!chPtr) {
1980
        Tcl_AppendResult(interp, "entry \"", argv[0], ",", argv[1],
1981
            "\" does not exist", NULL);
1982
        return TCL_ERROR;
1983
    }
1984
 
1985
    if (argc == 2) {
1986
        return Tix_ConfigureInfo2(interp, wPtr->dispData.tkwin,
1987
            (char*)chPtr, entryConfigSpecs, chPtr->iPtr, (char *) NULL, 0);
1988
    } else if (argc == 3) {
1989
        return Tix_ConfigureInfo2(interp, wPtr->dispData.tkwin,
1990
            (char*)chPtr, entryConfigSpecs, chPtr->iPtr, (char *) argv[2], 0);
1991
    } else {
1992
        return ConfigElement(wPtr, chPtr, argc-2, argv+2,
1993
            TK_CONFIG_ARGV_ONLY, 0);
1994
    }
1995
}
1996
 
1997
/*----------------------------------------------------------------------
1998
 * "geometryinfo" sub command
1999
 *----------------------------------------------------------------------
2000
 */
2001
static int
2002
Tix_GrGeometryInfo(clientData, interp, argc, argv)
2003
    ClientData clientData;
2004
    Tcl_Interp *interp;         /* Current interpreter. */
2005
    int argc;                   /* Number of arguments. */
2006
    char **argv;                /* Argument strings. */
2007
{
2008
    WidgetPtr wPtr = (WidgetPtr) clientData;
2009
    int qSize[2];
2010
    double first[2], last[2];
2011
    char string[80];
2012
    int i;
2013
    Tix_GridScrollInfo scrollInfo[2];
2014
 
2015
    if (argc == 2) {
2016
        if (Tcl_GetInt(interp, argv[0], &qSize[0]) != TCL_OK) {
2017
            return TCL_ERROR;
2018
        }
2019
        if (Tcl_GetInt(interp, argv[1], &qSize[1]) != TCL_OK) {
2020
            return TCL_ERROR;
2021
        }
2022
    } else {
2023
        qSize[0] = Tk_Width (wPtr->dispData.tkwin);
2024
        qSize[1] = Tk_Height(wPtr->dispData.tkwin);
2025
    }
2026
    qSize[0] -= 2*wPtr->borderWidth + 2*wPtr->highlightWidth;
2027
    qSize[1] -= 2*wPtr->borderWidth + 2*wPtr->highlightWidth;
2028
 
2029
    RecalScrollRegion(wPtr, qSize[0], qSize[1], scrollInfo);
2030
 
2031
    for (i=0; i<2; i++) {
2032
        qSize[i] -= 2*wPtr->borderWidth + 2*wPtr->highlightWidth;
2033
        GetScrollFractions(wPtr, &scrollInfo[i],
2034
            &first[i], &last[i]);
2035
    }
2036
 
2037
    sprintf(string, "{%f %f} {%f %f}", first[0], last[0], first[1], last[1]);
2038
    Tcl_AppendResult(interp, string, NULL);
2039
 
2040
    return TCL_OK;
2041
}
2042
 
2043
/*----------------------------------------------------------------------
2044
 * "index" sub command
2045
 *----------------------------------------------------------------------
2046
 */
2047
static int
2048
Tix_GrIndex(clientData, interp, argc, argv)
2049
    ClientData clientData;
2050
    Tcl_Interp *interp;         /* Current interpreter. */
2051
    int argc;                   /* Number of arguments. */
2052
    char **argv;                /* Argument strings. */
2053
{
2054
    WidgetPtr wPtr = (WidgetPtr) clientData;
2055
    int x, y;
2056
    char buff[100];
2057
 
2058
    if (TixGridDataGetIndex(interp, wPtr, argv[0], argv[1], &x, &y)!=TCL_OK) {
2059
        return TCL_ERROR;
2060
    }
2061
 
2062
    sprintf(buff, "%d %d", x, y);
2063
    Tcl_ResetResult(interp);
2064
    Tcl_AppendResult(interp, buff, NULL);
2065
    return TCL_OK;
2066
}
2067
 
2068
/*----------------------------------------------------------------------
2069
 * "info" sub command
2070
 *----------------------------------------------------------------------
2071
 */
2072
static int
2073
Tix_GrInfo(clientData, interp, argc, argv)
2074
    ClientData clientData;
2075
    Tcl_Interp *interp;         /* Current interpreter. */
2076
    int argc;                   /* Number of arguments. */
2077
    char **argv;                /* Argument strings. */
2078
{
2079
    WidgetPtr wPtr = (WidgetPtr) clientData;
2080
    size_t len = strlen(argv[0]);
2081
    int x, y;
2082
 
2083
    if (strncmp(argv[0], "bbox", len)==0) {
2084
        if (argc != 3) {
2085
            return Tix_ArgcError(interp, argc+2, argv-2, 3, "x y");
2086
        }
2087
        if (TixGridDataGetIndex(interp, wPtr, argv[1], argv[2], &x, &y)
2088
                !=TCL_OK) {
2089
            return TCL_ERROR;
2090
        }
2091
 
2092
        return Tix_GrBBox(interp, wPtr, x, y);
2093
    }
2094
    else if (strncmp(argv[0], "exists", len)==0) {
2095
        if (argc != 3) {
2096
            return Tix_ArgcError(interp, argc+2, argv-2, 3, "x y");
2097
        }
2098
        if (TixGridDataGetIndex(interp, wPtr, argv[1], argv[2], &x, &y)
2099
                !=TCL_OK) {
2100
            return TCL_ERROR;
2101
        }
2102
        if (Tix_GrFindElem(interp, wPtr, x, y)) {
2103
            Tcl_SetResult(interp, "1", TCL_STATIC);
2104
        } else {
2105
            Tcl_SetResult(interp, "0", TCL_STATIC);
2106
        }
2107
        return TCL_OK;
2108
    }
2109
    else {
2110
        Tcl_AppendResult(interp, "unknown option \"", argv[0],
2111
            "\": must be bbox or exists",
2112
            NULL);
2113
        return TCL_ERROR;
2114
    }
2115
}
2116
 
2117
/*----------------------------------------------------------------------
2118
 * "move" sub command
2119
 *----------------------------------------------------------------------
2120
 */
2121
static int
2122
Tix_GrMove(clientData, interp, argc, argv)
2123
    ClientData clientData;
2124
    Tcl_Interp *interp;         /* Current interpreter. */
2125
    int argc;                   /* Number of arguments. */
2126
    char **argv;                /* Argument strings. */
2127
{
2128
    WidgetPtr wPtr = (WidgetPtr) clientData;
2129
    int from, to, which, by;
2130
 
2131
    if (TranslateFromTo(interp, wPtr, 3, argv, &from, &to, &which)!=TCL_OK){
2132
        return TCL_ERROR;
2133
    }
2134
    if (Tcl_GetInt(interp, argv[3], &by) != TCL_OK) {
2135
        return TCL_ERROR;
2136
    }
2137
 
2138
TixGridDataMoveRange(wPtr, wPtr->dataSet, which, from, to, by);
2139
 
2140
    return TCL_OK;
2141
}
2142
 
2143
/*----------------------------------------------------------------------
2144
 * "nearest" sub command
2145
 *----------------------------------------------------------------------
2146
 */
2147
static int
2148
Tix_GrNearest(clientData, interp, argc, argv)
2149
    ClientData clientData;
2150
    Tcl_Interp *interp;         /* Current interpreter. */
2151
    int argc;                   /* Number of arguments. */
2152
    char **argv;                /* Argument strings. */
2153
{
2154
    WidgetPtr wPtr = (WidgetPtr) clientData;
2155
    Tk_Window tkwin = wPtr->dispData.tkwin;
2156
    int i, k, screenPos[2], rbPos[2];
2157
    char buf[100];
2158
    RenderBlockElem* rePtr;
2159
 
2160
    if (Tcl_GetInt(interp, argv[0], &screenPos[0]) != TCL_OK) {
2161
        return TCL_ERROR;
2162
    }
2163
    if (Tcl_GetInt(interp, argv[1], &screenPos[1]) != TCL_OK) {
2164
        return TCL_ERROR;
2165
    }
2166
 
2167
    if (!Tk_IsMapped(tkwin)) {
2168
        Tcl_ResetResult(interp);
2169
        return TCL_OK;
2170
    }
2171
 
2172
    if (wPtr->mainRB == NULL || wPtr->toResetRB) {
2173
        Tix_GrResetRenderBlocks(wPtr);
2174
        wPtr->toResetRB = 0;
2175
    }
2176
 
2177
    screenPos[0] -= wPtr->highlightWidth - wPtr->borderWidth;
2178
    screenPos[1] -= wPtr->highlightWidth - wPtr->borderWidth;
2179
 
2180
    for (i=0; i<2; i++) {
2181
        for (k=0; k<wPtr->mainRB->size[i]; k++) {
2182
            screenPos[i] -=  wPtr->mainRB->dispSize[i][k].total;
2183
            if (screenPos[i]<=0) {
2184
                break;
2185
            }
2186
        }
2187
        if (k >= wPtr->mainRB->size[i]) {
2188
            k = wPtr->mainRB->size[i] - 1;
2189
        }
2190
        rbPos[i] = k;
2191
    }
2192
    rePtr = &(wPtr->mainRB->elms[rbPos[0]][rbPos[1]]);
2193
 
2194
    sprintf(buf, "%d %d", rePtr->index[0], rePtr->index[1]);
2195
    Tcl_ResetResult(interp);
2196
    Tcl_AppendResult(interp, buf, NULL);
2197
 
2198
    return TCL_OK;
2199
}
2200
 
2201
/*----------------------------------------------------------------------
2202
 * "anchor", "dragsite" and "dropsire" sub commands --
2203
 *
2204
 *      Set/remove the anchor element
2205
 *----------------------------------------------------------------------
2206
 */
2207
static int
2208
Tix_GrSetSite(clientData, interp, argc, argv)
2209
    ClientData clientData;
2210
    Tcl_Interp *interp;         /* Current interpreter. */
2211
    int argc;                   /* Number of arguments. */
2212
    char **argv;                /* Argument strings. */
2213
{
2214
    int changed = 0;
2215
    WidgetPtr wPtr = (WidgetPtr) clientData;
2216
    int * changePtr;
2217
    size_t len;
2218
    int changedRect[2][2];
2219
 
2220
    /*
2221
     * Determine which site should be changed (the last else clause
2222
     * doesn't need to check the string because HandleSubCommand
2223
     * already ensures that only the valid options can be specified.
2224
     */
2225
    len = strlen(argv[-1]);
2226
    if (strncmp(argv[-1], "anchor", len)==0) {
2227
        changePtr = wPtr->anchor;
2228
    }
2229
    else if (strncmp(argv[-1], "dragsite", len)==0) {
2230
        changePtr = wPtr->dragSite;
2231
    }
2232
    else {
2233
        changePtr = wPtr->dropSite;
2234
    }
2235
 
2236
    len = strlen(argv[0]);
2237
    if (strncmp(argv[0], "get", len)==0) {
2238
        char buf[100];
2239
 
2240
        sprintf(buf, "%d %d", changePtr[0], changePtr[1]);
2241
        Tcl_SetResult(interp, buf, TCL_VOLATILE);
2242
 
2243
        return TCL_OK;
2244
    } else if (strncmp(argv[0], "set", len)==0) {
2245
        if (argc == 3) {
2246
            int x, y;
2247
 
2248
            if (TixGridDataGetIndex(interp, wPtr, argv[1], argv[2],
2249
                     &x, &y)!=TCL_OK) {
2250
                return TCL_ERROR;
2251
            }
2252
            if (x != changePtr[0] || y != changePtr[1]) {
2253
                changedRect[0][0] = x;
2254
                changedRect[1][0] = y;
2255
                changedRect[0][1] = changePtr[0];
2256
                changedRect[1][1] = changePtr[1];
2257
                changed = 1;
2258
 
2259
                changePtr[0] = x;
2260
                changePtr[1] = y;
2261
            }
2262
        } else {
2263
            Tcl_AppendResult(interp, "wrong # of arguments, must be: ",
2264
                Tk_PathName(wPtr->dispData.tkwin), " ", argv[-1],
2265
                " set x y", NULL);
2266
            return TCL_ERROR;
2267
        }
2268
    }
2269
    else if (strncmp(argv[0], "clear", len)==0) {
2270
        if (argc == 1) {
2271
            if (changePtr[0] !=TIX_SITE_NONE || changePtr[1] !=TIX_SITE_NONE) {
2272
                changedRect[0][0] = TIX_SITE_NONE;
2273
                changedRect[1][0] = TIX_SITE_NONE;
2274
                changedRect[0][1] = changePtr[0];
2275
                changedRect[1][1] = changePtr[1];
2276
                changed = 1;
2277
 
2278
                changePtr[0] = TIX_SITE_NONE;
2279
                changePtr[1] = TIX_SITE_NONE;
2280
            }
2281
        } else {
2282
            Tcl_AppendResult(interp, "wrong # of arguments, must be: ",
2283
                Tk_PathName(wPtr->dispData.tkwin), " ", argv[-1],
2284
                " clear", NULL);
2285
            return TCL_ERROR;
2286
        }
2287
    }
2288
    else {
2289
        Tcl_AppendResult(interp, "wrong option \"", argv[0], "\", ",
2290
            "must be clear, get or set", NULL);
2291
        return TCL_ERROR;
2292
    }
2293
 
2294
    if (changed) {
2295
        Tix_GrAddChangedRect(wPtr, changedRect, 1);
2296
    }
2297
 
2298
    return TCL_OK;
2299
}
2300
 
2301
/*----------------------------------------------------------------------
2302
 * Tix_GrAddChangedRect --
2303
 *
2304
 *      Add the "changed" region to the exposedArea structure.
2305
 *----------------------------------------------------------------------
2306
 */
2307
void
2308
Tix_GrAddChangedRect(wPtr, changedRect, isSite)
2309
    WidgetPtr wPtr;
2310
    int changedRect[2][2];
2311
    int isSite;
2312
{
2313
    int rect[2][2];
2314
    int visible;
2315
    int i;
2316
    int changed = 0;
2317
 
2318
    if (wPtr->mainRB == NULL) {
2319
        /*
2320
         * The grid will be completely refreshed. Don't do anything
2321
         */
2322
        return;
2323
    }
2324
 
2325
    for (i=0; i<2; i++) {
2326
        visible = Tix_GrGetElementPosn(wPtr, changedRect[0][i],
2327
            changedRect[1][i], rect, 1, isSite, 1, 1);
2328
        if (!visible) {
2329
            continue;
2330
        }
2331
        if (wPtr->expArea.x1 > rect[0][0]) {
2332
            wPtr->expArea.x1 = rect[0][0];
2333
            changed = 1;
2334
        }
2335
        if (wPtr->expArea.x2 < rect[0][1]) {
2336
            wPtr->expArea.x2 = rect[0][1];
2337
            changed = 1;
2338
        }
2339
        if (wPtr->expArea.y1 > rect[1][0]) {
2340
            wPtr->expArea.y1 = rect[1][0];
2341
            changed = 1;
2342
        }
2343
        if (wPtr->expArea.y2 < rect[1][1]) {
2344
            wPtr->expArea.y2 = rect[1][1];
2345
            changed = 1;
2346
        }
2347
    }
2348
    if (changed) {
2349
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
2350
    }
2351
}
2352
 
2353
void Tix_GrScrollPage(wPtr, count, axis)
2354
    WidgetPtr wPtr;
2355
    int count;
2356
    int axis;
2357
{
2358
    int k, i = axis;
2359
    int winSize, sz, start, num;
2360
    int pad0, pad1;
2361
 
2362
    Tix_GridScrollInfo * siPtr = &wPtr->scrollInfo[axis];
2363
    int gridSize[2];
2364
 
2365
    if (count == 0) {
2366
        return;
2367
    }
2368
 
2369
    TixGridDataGetGridSize(wPtr->dataSet, &gridSize[0],
2370
        &gridSize[1]);
2371
 
2372
    if (gridSize[i] < wPtr->hdrSize[i]) {        /* no scrollable data */
2373
        return;
2374
    }
2375
 
2376
    if (axis == 0) {
2377
        winSize = Tk_Width(wPtr->dispData.tkwin);
2378
    } else {
2379
        winSize = Tk_Height(wPtr->dispData.tkwin);
2380
    }
2381
    winSize -= 2*wPtr->highlightWidth + 2*wPtr->borderWidth;
2382
 
2383
    for (k=0; k<wPtr->hdrSize[i] && k<gridSize[i]; k++) {
2384
        winSize -= TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
2385
                k, &wPtr->defSize[i], &pad0, &pad1);
2386
        winSize -= pad0 + pad1;
2387
    }
2388
 
2389
    if (winSize <= 0) {
2390
        return;
2391
    }
2392
 
2393
    if (count > 0) {
2394
        start = siPtr->offset + wPtr->hdrSize[i];
2395
        for (; count > 0; count--) {
2396
            sz = winSize;
2397
 
2398
            for (num=0,k=start; k<gridSize[i]; k++,num++) {
2399
                sz -= TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
2400
                    k, &wPtr->defSize[i], &pad0, &pad1);
2401
                sz -= pad0 + pad1;
2402
                if (sz == 0) {
2403
                    num++;
2404
                    break;
2405
                }
2406
                if (sz < 0) {
2407
                    break;
2408
                }
2409
            }
2410
            if (num==0) {
2411
                num++;
2412
            }
2413
            start += num;
2414
        }
2415
        siPtr->offset = start - wPtr->hdrSize[i];
2416
    }
2417
    else {
2418
        start = siPtr->offset + wPtr->hdrSize[i];
2419
 
2420
        for (; count < 0; count++) {
2421
            sz = winSize;
2422
 
2423
            for (num=0,k=start-1; k>=wPtr->hdrSize[i]; k--,num++) {
2424
                sz -= TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
2425
                    k, &wPtr->defSize[i], &pad0, &pad1);
2426
                sz -= pad0 + pad1;
2427
                if (sz == 0) {
2428
                    num++;
2429
                    break;
2430
                }
2431
                if (sz < 0) {
2432
                    break;
2433
                }
2434
            }
2435
            if (num==0) {
2436
                num++;
2437
            }
2438
            start -= num;
2439
        }
2440
        siPtr->offset = start - wPtr->hdrSize[i];
2441
    }
2442
}
2443
 
2444
/*----------------------------------------------------------------------
2445
 * "xview" and "yview" sub command
2446
 *----------------------------------------------------------------------
2447
 */
2448
static int
2449
Tix_GrView(clientData, interp, argc, argv)
2450
    ClientData clientData;
2451
    Tcl_Interp *interp;         /* Current interpreter. */
2452
    int argc;                   /* Number of arguments. */
2453
    char **argv;                /* Argument strings. */
2454
{
2455
    WidgetPtr wPtr = (WidgetPtr) clientData;
2456
    int axis, oldXOff, oldYOff;
2457
    Tix_GridScrollInfo * siPtr;
2458
 
2459
    if (argv[-1][0] == 'x') {
2460
        axis = 0;
2461
    } else {
2462
        axis = 1;
2463
    }
2464
 
2465
    oldXOff = wPtr->scrollInfo[0].offset;
2466
    oldYOff = wPtr->scrollInfo[1].offset;
2467
 
2468
    if (argc == 0) {
2469
        char string[100];
2470
        double first, last;
2471
 
2472
        GetScrollFractions(wPtr, &wPtr->scrollInfo[axis], &first, &last);
2473
        sprintf(string, "%f %f", first, last);
2474
        Tcl_AppendResult(interp, string, NULL);
2475
        return TCL_OK;
2476
    }
2477
    else {
2478
        int offset;
2479
        siPtr = &wPtr->scrollInfo[axis];
2480
 
2481
        if (Tcl_GetInt(interp, argv[0], &offset) == TCL_OK) {
2482
            /* backward-compatible mode */
2483
            siPtr->offset = offset;
2484
        } else {
2485
            int type, count;
2486
            double fraction;
2487
 
2488
            Tcl_ResetResult(interp);
2489
 
2490
            /* Tk_GetScrollInfo () wants strange argc,argv combinations .. */
2491
            type = Tk_GetScrollInfo(interp, argc+2, argv-2, &fraction, &count);
2492
 
2493
            switch (type) {
2494
              case TK_SCROLL_ERROR:
2495
                return TCL_ERROR;
2496
 
2497
              case TK_SCROLL_MOVETO:
2498
                if (siPtr->window < 1.0) {
2499
                    fraction /= (1.0 - siPtr->window);
2500
                }
2501
 
2502
                siPtr->offset = (int)(fraction * (siPtr->max+1));
2503
                break;
2504
 
2505
              case TK_SCROLL_PAGES:
2506
                Tix_GrScrollPage(wPtr, count, axis);
2507
                break;
2508
 
2509
              case TK_SCROLL_UNITS:
2510
                siPtr->offset += count * siPtr->unit;
2511
                break;
2512
            }
2513
        }
2514
        /* check ... */
2515
        if (siPtr->offset < 0) {
2516
            siPtr->offset  = 0;
2517
        }
2518
        if (siPtr->offset > siPtr->max) {
2519
            siPtr->offset = siPtr->max;
2520
        }
2521
    }
2522
 
2523
#if 0
2524
    printf("Configing Scrollbars: (%d %f %d) (%d %f %d)\n",
2525
        wPtr->scrollInfo[0].max,
2526
        wPtr->scrollInfo[0].window,
2527
        wPtr->scrollInfo[0].offset,
2528
        wPtr->scrollInfo[1].max,
2529
        wPtr->scrollInfo[1].window,
2530
        wPtr->scrollInfo[1].offset);
2531
#endif
2532
 
2533
    if (oldXOff != wPtr->scrollInfo[0].offset ||
2534
        oldYOff != wPtr->scrollInfo[1].offset) {
2535
        wPtr->toResetRB    = 1;
2536
        wPtr->toComputeSel = 1;
2537
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
2538
    }
2539
    return TCL_OK;
2540
}
2541
/*----------------------------------------------------------------------
2542
 *
2543
 *
2544
 *                      Memory Management Section
2545
 *
2546
 *
2547
 *----------------------------------------------------------------------
2548
 */
2549
static int
2550
ConfigElement(wPtr, chPtr, argc, argv, flags, forced)
2551
    WidgetPtr wPtr;
2552
    TixGrEntry *chPtr;
2553
    int argc;
2554
    char ** argv;
2555
    int flags;
2556
    int forced;
2557
{
2558
    int sizeChanged;
2559
 
2560
    if (Tix_WidgetConfigure2(wPtr->dispData.interp, wPtr->dispData.tkwin,
2561
        (char*)chPtr, entryConfigSpecs, chPtr->iPtr, argc, argv, flags,
2562
        forced, &sizeChanged) != TCL_OK) {
2563
        return TCL_ERROR;
2564
    }
2565
 
2566
    if (sizeChanged) {
2567
        /* %% be smart here: sometimes the size request doesn't need to
2568
         * be changed
2569
         */
2570
        Tix_GrDoWhenIdle(wPtr, TIX_GR_RESIZE);
2571
    } else {
2572
        /* set the exposed area */
2573
        Tix_GrDoWhenIdle(wPtr, TIX_GR_REDRAW);
2574
    }
2575
    return TCL_OK;
2576
}
2577
 
2578
static char * areaNames[4] = {
2579
    "s-margin",
2580
    "x-margin",
2581
    "y-margin",
2582
    "main"
2583
};
2584
 
2585
static int
2586
Tix_GrCallFormatCmd(wPtr, which)
2587
    WidgetPtr wPtr;
2588
    int which;
2589
{
2590
    int size;
2591
    int code;
2592
    char * p;
2593
    char preAlloc[1000];
2594
 
2595
    size = strlen(wPtr->formatCmd) + 20*4;
2596
    if (size > 1000) {
2597
        p = (char*)ckalloc(size);
2598
    } else {
2599
        p = preAlloc;
2600
    }
2601
 
2602
    wPtr->renderInfo->fmt.whichArea = which;
2603
    sprintf(p, "%s %s %d %d %d %d", wPtr->formatCmd, areaNames[which],
2604
        wPtr->renderInfo->fmt.x1,
2605
        wPtr->renderInfo->fmt.y1,
2606
        wPtr->renderInfo->fmt.x2,
2607
        wPtr->renderInfo->fmt.y2);
2608
    code = Tcl_GlobalEval(wPtr->dispData.interp, p);
2609
 
2610
    if (code != TCL_OK) {
2611
        Tcl_AddErrorInfo(wPtr->dispData.interp,
2612
            "\n    (format command executed by tixGrid)");
2613
        Tk_BackgroundError(wPtr->dispData.interp);
2614
    }
2615
 
2616
    if (p != preAlloc) {
2617
        ckfree((char*)p);
2618
    }
2619
 
2620
    return code;
2621
}
2622
 
2623
 
2624
static void Tix_GrDrawBackground(wPtr, riPtr, drawable)
2625
    WidgetPtr wPtr;
2626
    RenderInfo * riPtr;
2627
    Drawable drawable;
2628
{
2629
    int mainSize[2];
2630
    int visibleHdr[2];
2631
 
2632
    if (wPtr->formatCmd == NULL) {
2633
        return;
2634
    }
2635
 
2636
    /* The visible size of the main area
2637
     */
2638
    mainSize[0] = wPtr->mainRB->size[0] - wPtr->hdrSize[0];
2639
    mainSize[1] = wPtr->mainRB->size[1] - wPtr->hdrSize[1];
2640
    if (mainSize[0] < 0) {
2641
        mainSize[0] = 0;
2642
    }
2643
    if (mainSize[1] < 0) {
2644
        mainSize[1] = 0;
2645
    }
2646
 
2647
    /* the visible header size
2648
     */
2649
    if (wPtr->mainRB->size[0] < wPtr->hdrSize[0]) {
2650
        visibleHdr[0] = wPtr->mainRB->size[0];
2651
    } else {
2652
        visibleHdr[0] = wPtr->hdrSize[0];
2653
    }
2654
    if (wPtr->mainRB->size[1] < wPtr->hdrSize[1]) {
2655
        visibleHdr[1] = wPtr->mainRB->size[1];
2656
    } else {
2657
        visibleHdr[1] = wPtr->hdrSize[1];
2658
    }
2659
 
2660
 
2661
    /* the horizontal margin
2662
     */
2663
    if (wPtr->hdrSize[1] > 0 && mainSize[0] > 0) {
2664
        wPtr->renderInfo->fmt.x1 =
2665
          wPtr->scrollInfo[0].offset + wPtr->hdrSize[0];
2666
        wPtr->renderInfo->fmt.x2 =
2667
          wPtr->renderInfo->fmt.x1 + mainSize[0] - 1;
2668
        wPtr->renderInfo->fmt.y1 = 0;
2669
        wPtr->renderInfo->fmt.y2 = visibleHdr[1] - 1;
2670
 
2671
        Tix_GrCallFormatCmd(wPtr, TIX_X_MARGIN);
2672
    }
2673
 
2674
    /* the vertical margin
2675
     */
2676
    if (wPtr->hdrSize[0] > 0 && mainSize[1] > 0) {
2677
        wPtr->renderInfo->fmt.x1 = 0;
2678
        wPtr->renderInfo->fmt.x2 = visibleHdr[0] - 1;
2679
        wPtr->renderInfo->fmt.y1 =
2680
          wPtr->scrollInfo[1].offset + wPtr->hdrSize[1];
2681
        wPtr->renderInfo->fmt.y2 =
2682
          wPtr->renderInfo->fmt.y1 + mainSize[1] - 1;
2683
 
2684
        Tix_GrCallFormatCmd(wPtr, TIX_Y_MARGIN);
2685
    }
2686
 
2687
    /* the stationary part of the margin
2688
     */
2689
    if (visibleHdr[0] > 0 && visibleHdr[1] > 0) {
2690
        wPtr->renderInfo->fmt.x1 = 0;
2691
        wPtr->renderInfo->fmt.x2 = visibleHdr[0] - 1;
2692
        wPtr->renderInfo->fmt.y1 = 0;
2693
        wPtr->renderInfo->fmt.y2 = visibleHdr[1] - 1;
2694
 
2695
        Tix_GrCallFormatCmd(wPtr, TIX_S_MARGIN);
2696
    }
2697
 
2698
    /* the main area
2699
     */
2700
    if (mainSize[0] > 0 && mainSize[1] > 0) {
2701
        wPtr->renderInfo->fmt.x1 =
2702
          wPtr->scrollInfo[0].offset + wPtr->hdrSize[0];
2703
        wPtr->renderInfo->fmt.x2 =
2704
          wPtr->renderInfo->fmt.x1 + mainSize[0] - 1;
2705
        wPtr->renderInfo->fmt.y1 =
2706
          wPtr->scrollInfo[1].offset + wPtr->hdrSize[1];
2707
        wPtr->renderInfo->fmt.y2 =
2708
          wPtr->renderInfo->fmt.y1 + mainSize[1] - 1;
2709
 
2710
        Tix_GrCallFormatCmd(wPtr, TIX_MAIN);
2711
    }
2712
}
2713
 
2714
static void
2715
Tix_GrComputeSubSelection(wPtr, rect, offs)
2716
    WidgetPtr wPtr;
2717
    int rect[2][2];
2718
    int offs[2];
2719
{
2720
    int iMin, iMax, jMin, jMax;
2721
    Tix_ListIterator li;
2722
    SelectBlock * sbPtr;
2723
    int i, j, x, y;
2724
 
2725
    Tix_SimpleListIteratorInit(&li);
2726
    for (Tix_SimpleListStart(&wPtr->selList, &li);
2727
         !Tix_SimpleListDone(&li);
2728
         Tix_SimpleListNext (&wPtr->selList, &li)) {
2729
 
2730
        sbPtr = (SelectBlock *)li.curr;
2731
 
2732
        /* clip the X direction
2733
         */
2734
        if (rect[0][0] > sbPtr->range[0][0]) {
2735
            iMin = rect[0][0];
2736
        } else {
2737
            iMin = sbPtr->range[0][0];
2738
        }
2739
 
2740
        if (rect[0][1]<sbPtr->range[0][1] || sbPtr->range[0][1]==TIX_GR_MAX) {
2741
            iMax = rect[0][1];
2742
        } else {
2743
            iMax = sbPtr->range[0][1];
2744
        }
2745
        if (iMin > iMax) {
2746
            continue;
2747
        }
2748
 
2749
        /* clip the Y direction
2750
         */
2751
        if (rect[1][0] > sbPtr->range[1][0]) {
2752
            jMin = rect[1][0];
2753
        } else {
2754
            jMin = sbPtr->range[1][0];
2755
        }
2756
        if (rect[1][1]<sbPtr->range[1][1] || sbPtr->range[1][1]==TIX_GR_MAX) {
2757
            jMax = rect[1][1];
2758
        } else {
2759
            jMax = sbPtr->range[1][1];
2760
        }
2761
        if (jMin > jMax) {
2762
            continue;
2763
        }
2764
 
2765
        for (i=iMin; i<=iMax; i++) {
2766
            for (j=jMin; j<=jMax; j++) {
2767
                x = i - offs[0];
2768
                y = j - offs[1];
2769
 
2770
                switch (sbPtr->type) {
2771
                  case TIX_GR_CLEAR:
2772
                    wPtr->mainRB->elms[x][y].selected = 0;
2773
                    break;
2774
                  case TIX_GR_SET:
2775
                    wPtr->mainRB->elms[x][y].selected = 1;
2776
                    break;
2777
                  case TIX_GR_TOGGLE:
2778
                    wPtr->mainRB->elms[x][y].selected =
2779
                      !wPtr->mainRB->elms[x][y].selected;
2780
                    break;
2781
 
2782
                }
2783
            }
2784
        }
2785
    }
2786
}
2787
 
2788
static void Tix_GrComputeSelection(wPtr)
2789
    WidgetPtr wPtr;
2790
{
2791
    int rect[2][2], offs[2];
2792
    int i, j;
2793
    int mainSize[2];
2794
    int visibleHdr[2];
2795
 
2796
    for (i=0; i<wPtr->mainRB->size[0]; i++) {
2797
        for (j=0; j<wPtr->mainRB->size[1]; j++) {
2798
            wPtr->mainRB->elms[i][j].selected = 0;
2799
        }
2800
    }
2801
 
2802
    /* Get the visible size of the main area
2803
     */
2804
    mainSize[0] = wPtr->mainRB->size[0] - wPtr->hdrSize[0];
2805
    mainSize[1] = wPtr->mainRB->size[1] - wPtr->hdrSize[1];
2806
    if (mainSize[0] < 0) {
2807
        mainSize[0] = 0;
2808
    }
2809
    if (mainSize[1] < 0) {
2810
        mainSize[1] = 0;
2811
    }
2812
 
2813
    /* Get the visible header size
2814
     */
2815
    if (wPtr->mainRB->size[0] < wPtr->hdrSize[0]) {
2816
        visibleHdr[0] = wPtr->mainRB->size[0];
2817
    } else {
2818
        visibleHdr[0] = wPtr->hdrSize[0];
2819
    }
2820
    if (wPtr->mainRB->size[1] < wPtr->hdrSize[1]) {
2821
        visibleHdr[1] = wPtr->mainRB->size[1];
2822
    } else {
2823
        visibleHdr[1] = wPtr->hdrSize[1];
2824
    }
2825
 
2826
    /* Compute selection on the stationary part of the margin
2827
     */
2828
    if (visibleHdr[0] > 0 && visibleHdr[1] > 0) {
2829
        rect[0][0] = 0;
2830
        rect[0][1] = visibleHdr[0] - 1;
2831
        rect[1][0] = 0;
2832
        rect[1][1] = visibleHdr[1] - 1;
2833
        offs[0]    = 0;
2834
        offs[1]    = 0;
2835
 
2836
        Tix_GrComputeSubSelection(wPtr, rect, offs);
2837
    }
2838
 
2839
    /* Compute selection on the horizontal margin
2840
     */
2841
    if (wPtr->hdrSize[1] > 0 && mainSize[0] > 0) {
2842
        rect[0][0] = wPtr->scrollInfo[0].offset + wPtr->hdrSize[0];
2843
        rect[0][1] = rect[0][0] + mainSize[0] - 1;
2844
        rect[1][0] = 0;
2845
        rect[1][1] = visibleHdr[1] - 1;
2846
        offs[0]    = wPtr->scrollInfo[0].offset;;
2847
        offs[1]    = 0;
2848
 
2849
        Tix_GrComputeSubSelection(wPtr, rect, offs);
2850
    }
2851
 
2852
    /* Compute selection on the vertical margin
2853
     */
2854
    if (wPtr->hdrSize[0] > 0 && mainSize[1] > 0) {
2855
        rect[0][0] = 0;
2856
        rect[0][1] = visibleHdr[0] - 1;
2857
        rect[1][0] = wPtr->scrollInfo[1].offset + wPtr->hdrSize[1];
2858
        rect[1][1] = rect[1][0] + mainSize[1] - 1;
2859
        offs[0]    = 0;
2860
        offs[1]    = wPtr->scrollInfo[1].offset;;
2861
 
2862
        Tix_GrComputeSubSelection(wPtr, rect, offs);
2863
    }
2864
 
2865
    /* Compute selection on the main area
2866
     */
2867
    if (mainSize[0] > 0 && mainSize[1] > 0) {
2868
        rect[0][0] = wPtr->scrollInfo[0].offset + wPtr->hdrSize[0];
2869
        rect[0][1] = rect[0][0] + mainSize[0] - 1;
2870
        rect[1][0] = wPtr->scrollInfo[1].offset + wPtr->hdrSize[1];
2871
        rect[1][1] = rect[1][0] + mainSize[1] - 1;
2872
        offs[0]    = wPtr->scrollInfo[0].offset;;
2873
        offs[1]    = wPtr->scrollInfo[1].offset;;
2874
 
2875
        Tix_GrComputeSubSelection(wPtr, rect, offs);
2876
    }
2877
}
2878
 
2879
/*----------------------------------------------------------------------
2880
 *  UpdateScrollBars
2881
 *----------------------------------------------------------------------
2882
 */
2883
static void
2884
GetScrollFractions(wPtr, siPtr, first_ret, last_ret)
2885
    WidgetPtr wPtr;
2886
    Tix_GridScrollInfo *siPtr;
2887
    double * first_ret;
2888
    double * last_ret;
2889
{
2890
    double first, last;
2891
    double usuable;
2892
 
2893
    usuable = 1.0 - siPtr->window;
2894
 
2895
    if (siPtr->max > 0) {
2896
        first = usuable * (double)(siPtr->offset) / (double)(siPtr->max);
2897
        last  = first + siPtr->window;
2898
    } else {
2899
        first = 0.0;
2900
        last  = 1.0;
2901
    }
2902
 
2903
    *first_ret = first;
2904
    *last_ret  = last;
2905
}
2906
 
2907
static void UpdateScrollBars(wPtr, sizeChanged)
2908
    WidgetPtr wPtr;
2909
    int sizeChanged;
2910
{
2911
    int i;
2912
    Tix_GridScrollInfo *siPtr;
2913
    Tcl_Interp * interp = wPtr->dispData.interp;
2914
 
2915
    for (i=0; i<2; i++) {
2916
        double first, last;
2917
        double usuable;
2918
 
2919
        siPtr = &wPtr->scrollInfo[i];
2920
 
2921
        usuable = 1.0 - siPtr->window;
2922
 
2923
        if (siPtr->max > 0) {
2924
            first = usuable * (double)(siPtr->offset) / (double)(siPtr->max);
2925
            last  = first + siPtr->window;
2926
        } else {
2927
            first = 0.0;
2928
            last  = 1.0;
2929
        }
2930
 
2931
        if (siPtr->command) {
2932
            char buff[60];
2933
 
2934
            sprintf(buff, " %f %f", first, last);
2935
            if (Tcl_VarEval(interp, siPtr->command, buff,
2936
                (char *) NULL) != TCL_OK) {
2937
                Tcl_AddErrorInfo(interp,
2938
                    "\n    (scrolling command executed by tixGrid)");
2939
                Tk_BackgroundError(interp);
2940
            }
2941
        }
2942
    }
2943
 
2944
    if (wPtr->sizeCmd && sizeChanged) {
2945
        if (Tcl_GlobalEval(wPtr->dispData.interp, wPtr->sizeCmd) != TCL_OK) {
2946
            Tcl_AddErrorInfo(wPtr->dispData.interp,
2947
                "\n    (size command executed by tixGrid)");
2948
            Tk_BackgroundError(wPtr->dispData.interp);
2949
        }
2950
    }
2951
}
2952
 
2953
/*----------------------------------------------------------------------
2954
 * Tix_GrFindCreateElem --
2955
 *
2956
 *      Returns the element. If it doesn't exist, create a new one
2957
 *      and return it.
2958
 *----------------------------------------------------------------------
2959
 */
2960
 
2961
static TixGrEntry *
2962
Tix_GrFindCreateElem(interp, wPtr, x, y)
2963
    Tcl_Interp * interp;
2964
    WidgetPtr wPtr;
2965
    int x;
2966
    int y;
2967
{
2968
    static TixGrEntry * defaultEntry = NULL;
2969
    TixGrEntry * chPtr;
2970
 
2971
    if (defaultEntry == NULL) {
2972
        defaultEntry = (TixGrEntry*)ckalloc(sizeof(TixGrEntry));
2973
        defaultEntry->iPtr     = NULL;
2974
    }
2975
 
2976
    chPtr = (TixGrEntry*)TixGridDataCreateEntry(wPtr->dataSet, x, y,
2977
        (char*)defaultEntry);
2978
 
2979
    if (chPtr == defaultEntry) {
2980
        defaultEntry = NULL;
2981
    }
2982
 
2983
    return chPtr;
2984
}
2985
 
2986
/*----------------------------------------------------------------------
2987
 * Tix_GrFindElem --
2988
 *
2989
 *      Return the element if it exists. Otherwise returns 0.
2990
 *----------------------------------------------------------------------
2991
 */
2992
static TixGrEntry *
2993
Tix_GrFindElem(interp, wPtr, x, y)
2994
    Tcl_Interp * interp;        /* Used for error reporting */
2995
    WidgetPtr wPtr;             /* The grid widget */
2996
    int x;                      /* X coord of the entry */
2997
    int y;                      /* Y coord of the entry */
2998
{
2999
    return (TixGrEntry*)TixGridDataFindEntry(wPtr->dataSet, x, y);
3000
}
3001
 
3002
/*----------------------------------------------------------------------
3003
 * Tix_GrFreeElem --
3004
 *
3005
 *      Frees the element.
3006
 *
3007
 *----------------------------------------------------------------------
3008
 */
3009
 
3010
void
3011
Tix_GrFreeElem(chPtr)
3012
    TixGrEntry * chPtr;         /* The element fo free */
3013
{
3014
    if (chPtr->iPtr) {
3015
        Tix_DItemFree(chPtr->iPtr);
3016
    }
3017
    ckfree((char*)chPtr);
3018
}
3019
 
3020
static void
3021
Tix_GrPropagateSize(wPtr, chPtr)
3022
    WidgetPtr wPtr;
3023
    TixGrEntry * chPtr;
3024
{
3025
#if 0
3026
    int i;
3027
 
3028
    for (i=0; i<2; i++) {
3029
        TreeListRoot * rPtr;
3030
        GridHeader * hdr;
3031
 
3032
        rPtr = chPtr->nodes[i].root;
3033
        hdr = (GridHeader*) rPtr->data;
3034
 
3035
        if (hdr->size < chPtr->size[i]) {
3036
            hdr->size = chPtr->size[i];
3037
            hdr->recalSize = 0;
3038
        }
3039
    }
3040
#endif
3041
}
3042
 
3043
static RenderBlock * Tix_GrAllocateRenderBlock(wPtr, winW, winH, exactW,exactH)
3044
    WidgetPtr wPtr;
3045
    int winW;
3046
    int winH;
3047
    int * exactW;
3048
    int * exactH;
3049
{
3050
    RenderBlock * rbPtr;
3051
    int i, j, k;
3052
    int offset[2];              /* how much the entries were scrolled */
3053
    int winSize[2];
3054
    int exactSize[2];           /* BOOL: are all the visible coloums and rows
3055
                                 * displayed in whole */
3056
    int pad0, pad1;
3057
 
3058
    offset[0] = wPtr->scrollInfo[0].offset + wPtr->hdrSize[0];
3059
    offset[1] = wPtr->scrollInfo[1].offset + wPtr->hdrSize[1];
3060
 
3061
    winSize[0] = winW;
3062
    winSize[1] = winH;
3063
 
3064
    rbPtr = (RenderBlock*)ckalloc(sizeof(RenderBlock));
3065
 
3066
    rbPtr->size[0]=0;
3067
    rbPtr->size[1]=0;
3068
    rbPtr->visArea[0] = winW;
3069
    rbPtr->visArea[1] = winH;
3070
 
3071
    /* (1) find out the size requirement of each row and column.
3072
     *     The results are stored in rbPtr->size[i] and
3073
     *     rbPtr->dispSize[i][0 .. (rbPtr->size[i]-1)]
3074
     */
3075
    for (i=0; i<2; i++) {
3076
        /* i=0 : handle the column sizes;
3077
         * i=1 : handle the row    sizes;
3078
         */
3079
        int index;
3080
        int pixelSize = 0;
3081
 
3082
        /* The margins */
3083
        for (index=0; index<wPtr->hdrSize[i] && pixelSize<winSize[i]; index++){
3084
            pixelSize += TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
3085
                index, &wPtr->defSize[i], &pad0, &pad1);
3086
            pixelSize += pad0 + pad1;
3087
            rbPtr->size[i] ++;
3088
        }
3089
 
3090
        for (index=offset[i]; pixelSize<winSize[i]; index++) {
3091
            pixelSize += TixGridDataGetRowColSize(wPtr, wPtr->dataSet, i,
3092
                index, &wPtr->defSize[i], &pad0, &pad1);
3093
            pixelSize += pad0 + pad1;
3094
            rbPtr->size[i] ++;
3095
        }
3096
        if (pixelSize == winSize[i]) {
3097
            exactSize[i] = 1;
3098
        } else {
3099
            exactSize[i] = 0;
3100
        }
3101
    }
3102
 
3103
    /* return values */
3104
 
3105
    *exactW = exactSize[0];
3106
    *exactH = exactSize[1];
3107
 
3108
    rbPtr->dispSize[0] = (ElmDispSize*)
3109
        ckalloc(sizeof(ElmDispSize)*rbPtr->size[0]);
3110
    rbPtr->dispSize[1] = (ElmDispSize*)
3111
        ckalloc(sizeof(ElmDispSize)*rbPtr->size[1]);
3112
 
3113
    /*
3114
     * (2) fill the size info of all the visible rows and cols into
3115
     *     the dispSize arrays;
3116
     */
3117
 
3118
    for (i=0; i<2; i++) {
3119
        /*
3120
         * i=0 : handle the column sizes;
3121
         * i=1 : handle the row    sizes;
3122
         */
3123
        int index;
3124
 
3125
        for (k=0; k<rbPtr->size[i]; k++) {
3126
            if (k < wPtr->hdrSize[i]) {                 /* The margins */
3127
                index = k;
3128
            } else {
3129
                index = k + offset[i] - wPtr->hdrSize[i];
3130
            }
3131
 
3132
            rbPtr->dispSize[i][k].size = TixGridDataGetRowColSize(wPtr,
3133
                wPtr->dataSet, i, index, &wPtr->defSize[i], &pad0, &pad1);
3134
            rbPtr->dispSize[i][k].preBorder  = pad0;
3135
            rbPtr->dispSize[i][k].postBorder = pad1;
3136
        }
3137
    }
3138
 
3139
    /*
3140
     * (3) Put the visible elements into the render block array,
3141
     *     rbPtr->elms[*][*].
3142
     */
3143
    rbPtr->elms = (RenderBlockElem**)
3144
        ckalloc(sizeof(RenderBlockElem*)*rbPtr->size[0]);
3145
 
3146
    for (i=0; i<rbPtr->size[0]; i++) {
3147
        rbPtr->elms[i] = (RenderBlockElem*)
3148
            ckalloc(sizeof(RenderBlockElem) * rbPtr->size[1]);
3149
        for (j=0; j<rbPtr->size[1]; j++) {
3150
            rbPtr->elms[i][j].chPtr = NULL;
3151
            rbPtr->elms[i][j].selected = 0;
3152
        }
3153
    }
3154
 
3155
    for (i=0; i<rbPtr->size[0]; i++) {
3156
        for (j=0; j<rbPtr->size[1]; j++) {
3157
            int x, y;
3158
 
3159
            if (i<wPtr->hdrSize[0]) {
3160
                x = i;
3161
            } else {
3162
                x = i+offset[0]-wPtr->hdrSize[0];
3163
            }
3164
 
3165
            if (j<wPtr->hdrSize[1]) {
3166
                y = j;
3167
            } else {
3168
                y = j+offset[1]-wPtr->hdrSize[1];
3169
            }
3170
 
3171
            rbPtr->elms[i][j].chPtr = (TixGrEntry*) TixGridDataFindEntry(
3172
                wPtr->dataSet, x, y);
3173
            rbPtr->elms[i][j].index[0] = x;
3174
            rbPtr->elms[i][j].index[1] = y;
3175
        }
3176
    }
3177
 
3178
    for (k=0; k<2; k++) {
3179
        for (i=0; i<rbPtr->size[k]; i++) {
3180
            rbPtr->dispSize[k][i].total =
3181
                  rbPtr->dispSize[k][i].preBorder
3182
                + rbPtr->dispSize[k][i].size
3183
                + rbPtr->dispSize[k][i].postBorder;
3184
        }
3185
    }
3186
 
3187
    return rbPtr;
3188
}
3189
 
3190
static void
3191
Tix_GrFreeRenderBlock(wPtr, rbPtr)
3192
    WidgetPtr wPtr;
3193
    RenderBlock * rbPtr;
3194
{
3195
    int i;
3196
 
3197
    for (i=0; i<rbPtr->size[0]; i++) {
3198
        ckfree((char*)rbPtr->elms[i]);
3199
    }
3200
    ckfree((char*)rbPtr->elms);
3201
    ckfree((char*)rbPtr->dispSize[0]);
3202
    ckfree((char*)rbPtr->dispSize[1]);
3203
    ckfree((char*)rbPtr);
3204
}
3205
 
3206
/*----------------------------------------------------------------------
3207
 * Tix_GrBBox --
3208
 *
3209
 *      Returns the visible bounding box of a entry.
3210
 *
3211
 * Return value:
3212
 *      See user documenetation.
3213
 *
3214
 * Side effects:
3215
 *      None.
3216
 *----------------------------------------------------------------------
3217
 */
3218
 
3219
static int Tix_GrBBox(interp, wPtr, x, y)
3220
    Tcl_Interp * interp;        /* Interpreter to report the bbox. */
3221
    WidgetPtr wPtr;             /* HList widget. */
3222
    int x;                      /* X coordinate of the entry.*/
3223
    int y;                      /* Y coordinate of the entry.*/
3224
{
3225
    int rect[2][2];
3226
    int visible;
3227
    char buff[100];
3228
 
3229
    if (!Tk_IsMapped(wPtr->dispData.tkwin)) {
3230
        return TCL_OK;
3231
    }
3232
 
3233
    visible = Tix_GrGetElementPosn(wPtr, wPtr->anchor[0], wPtr->anchor[1],
3234
        rect, 0, 0, 1, 0);
3235
    if (!visible) {
3236
        return TCL_OK;
3237
    }
3238
 
3239
    sprintf(buff, "%d %d %d %d", rect[0][0], rect[1][0],
3240
        rect[0][1] - rect[0][0] + 1,
3241
        rect[1][1] - rect[1][0] + 1);
3242
 
3243
    Tcl_AppendResult(interp, buff, NULL);
3244
    return TCL_OK;
3245
}
3246
 
3247
/*
3248
 *----------------------------------------------------------------------
3249
 * TranslateFromTo --
3250
 *
3251
 *      Translate the "option from ?to?" arguments from string to integer.
3252
 *
3253
 * Results:
3254
 *      Standard Tcl results.
3255
 *
3256
 * Side effects:
3257
 *      On success, *from and *to contains the from and to values.
3258
 *----------------------------------------------------------------------
3259
 */
3260
 
3261
static int
3262
TranslateFromTo(interp, wPtr, argc, argv, from, to, which)
3263
    Tcl_Interp * interp;
3264
    WidgetPtr wPtr;
3265
    int argc;
3266
    char **argv;
3267
    int *from;
3268
    int *to;
3269
    int * which;
3270
{
3271
    int dummy;
3272
    size_t len = strlen(argv[0]);
3273
 
3274
    if (strncmp(argv[0], "row", len) == 0) {
3275
        *which = 1;
3276
 
3277
        if (TixGridDataGetIndex(interp, wPtr, "0", argv[1], &dummy, from)
3278
                !=TCL_OK) {
3279
            return TCL_ERROR;
3280
        }
3281
        if (argc == 3) {
3282
            if (TixGridDataGetIndex(interp, wPtr, "0", argv[2], &dummy, to)
3283
                    !=TCL_OK) {
3284
                return TCL_ERROR;
3285
            }
3286
        } else {
3287
            *to = *from;
3288
        }
3289
    } else if (strncmp(argv[0], "column", len) == 0) {
3290
        *which = 0;
3291
        if (TixGridDataGetIndex(interp, wPtr, argv[1], "0", from, &dummy)
3292
                !=TCL_OK) {
3293
            return TCL_ERROR;
3294
        }
3295
 
3296
        if (argc == 3) {
3297
            if (TixGridDataGetIndex(interp, wPtr, argv[2], "0", to, &dummy)
3298
                    !=TCL_OK) {
3299
                return TCL_ERROR;
3300
            }
3301
        } else {
3302
            *to = *from;
3303
        }
3304
    }
3305
 
3306
    return TCL_OK;
3307
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.