~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qmon/Xbae/Methods.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
 
3
 * Copyright(c) 1995-99 Andrew Lister
 
4
 *                        All rights reserved
 
5
 * Permission to use, copy, modify and distribute this material for
 
6
 * any purpose and without fee is hereby granted, provided that the
 
7
 * above copyright notice and this permission notice appear in all
 
8
 * copies, and that the name of Bellcore not be used in advertising
 
9
 * or publicity pertaining to this material without the specific,
 
10
 * prior written permission of an authorized representative of
 
11
 * Bellcore.
 
12
 *
 
13
 * BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
 
14
 * PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
 
15
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 
16
 * FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
 
17
 * FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS.  THE
 
18
 * SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
 
19
 * ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
 
20
 * LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
 
21
 * ING TO THE SOFTWARE.
 
22
 *
 
23
 * $Id$
 
24
 */
 
25
 
 
26
/*
 
27
 * Methods.c created by Andrew Lister (7 August, 1995)
 
28
 */
 
29
 
 
30
#ifdef HAVE_CONFIG_H
 
31
#include <config.h>
 
32
#endif
 
33
 
 
34
#include <Xm/Xm.h>
 
35
#include <X11/Intrinsic.h>
 
36
#include "MatrixP.h"
 
37
#include "Methods.h"
 
38
#include "Actions.h"
 
39
#include "ScrollMgr.h"
 
40
#include "Utils.h"
 
41
#include "Shadow.h"
 
42
#include "Draw.h"
 
43
#include "MCreate.h"
 
44
#include "ClipP.h"
 
45
#include "Input.h"
 
46
#include <Xm/XmP.h>
 
47
#include <Xm/Text.h>
 
48
#include <Xm/TextP.h>
 
49
 
 
50
/* For memmove/bcopy */
 
51
#include <string.h>
 
52
 
 
53
#if !defined(HAVE_MEMMOVE) && !defined(XBAE_NEED_BCOPY)
 
54
#define XBAE_NEED_BCOPY
 
55
#endif
 
56
 
 
57
/* Earl R.
 
58
 * Added another BCOPY macro for porting purposes. Porting to 15+ UNIX
 
59
 * platforms. Renamed bcopy to BCOPY and typecast to fix compiler warnings
 
60
 * on some platforms.
 
61
 */
 
62
#if !defined(XBAE_NEED_BCOPY) || defined(SVR4) || defined(VMS) || defined(__EMX__)
 
63
#define BCOPY(src, dest, n)        memmove((void *)(dest), (void *)(src), (n))
 
64
#else
 
65
#define BCOPY(src, dest, n)     bcopy((void *)(src), (void *)(dest), (n))
 
66
#endif
 
67
 
 
68
static void AddRowsToTable P((XbaeMatrixWidget, int, String *, String *,
 
69
                               Pixel *, Pixel *, int));
 
70
static void DeleteRowsFromTable P((XbaeMatrixWidget, int, int));
 
71
static void AddColumnsToTable P((XbaeMatrixWidget, int, String *, String *,
 
72
                                  short *, int *, unsigned char *,
 
73
                                  unsigned char *, Pixel *, Pixel *, int));
 
74
static void DeleteColumnsFromTable P((XbaeMatrixWidget, int, int));
 
75
static Boolean DoCommitEdit P((XbaeMatrixWidget, XEvent *));
 
76
 
 
77
/*
 
78
 * Add rows to the internal cells data structure.
 
79
 * If rows or labels is NULL, add empty rows.
 
80
 */
 
81
static void
 
82
AddRowsToTable(mw, position, rows, labels, colors, backgrounds, num_rows)
 
83
XbaeMatrixWidget mw;
 
84
int position;
 
85
String *rows;
 
86
String *labels;
 
87
Pixel *colors;
 
88
Pixel *backgrounds;
 
89
int num_rows;
 
90
{
 
91
    int i, j;
 
92
 
 
93
    /*
 
94
     * Realloc a larger array of row pointers and a larger label arrays
 
95
     */
 
96
    if (mw->matrix.cells || rows)
 
97
        mw->matrix.cells = (String **) XtRealloc((char *) mw->matrix.cells,
 
98
                                                 (mw->matrix.rows + num_rows) *
 
99
                                                 sizeof(String *));
 
100
    if (mw->matrix.row_labels || labels)
 
101
        mw->matrix.row_labels =
 
102
            (String *) XtRealloc((char *) mw->matrix.row_labels,
 
103
                                 (mw->matrix.rows + num_rows) *
 
104
                                 sizeof(String));
 
105
 
 
106
    if (mw->matrix.row_button_labels)
 
107
        mw->matrix.row_button_labels =
 
108
            (Boolean *) XtRealloc((char *) mw->matrix.
 
109
                                  row_button_labels,
 
110
                                  (mw->matrix.rows + num_rows) *
 
111
                                  sizeof(Boolean));
 
112
 
 
113
    if (mw->matrix.colors || colors)
 
114
        mw->matrix.colors = (Pixel **) XtRealloc((char *) mw->matrix.colors,
 
115
                                                 (mw->matrix.rows + num_rows) *
 
116
                                                 sizeof(Pixel *));
 
117
 
 
118
    if (mw->matrix.cell_background || backgrounds)
 
119
        mw->matrix.cell_background =
 
120
            (Pixel **) XtRealloc((char *) mw->matrix.cell_background,
 
121
                                 (mw->matrix.rows + num_rows) *
 
122
                                 sizeof(Pixel *));
 
123
 
 
124
    if (mw->matrix.cell_user_data)
 
125
        mw->matrix.cell_user_data = (XtPointer **)
 
126
            XtRealloc((char*) mw->matrix.cell_user_data,
 
127
                      (mw->matrix.rows + num_rows) *
 
128
                      sizeof(XtPointer *));
 
129
 
 
130
#if CELL_WIDGETS
 
131
    if (mw->matrix.cell_widgets)
 
132
        mw->matrix.cell_widgets = (Widget **)
 
133
            XtRealloc((char*) mw->matrix.cell_widgets,
 
134
                      (mw->matrix.rows + num_rows) *
 
135
                      sizeof(Widget *));
 
136
#endif
 
137
 
 
138
    if (mw->matrix.row_user_data)
 
139
        mw->matrix.row_user_data = (XtPointer*)
 
140
            XtRealloc((char*) mw->matrix.row_user_data,
 
141
                      (mw->matrix.rows + num_rows) *
 
142
                      sizeof(XtPointer));
 
143
 
 
144
    if (mw->matrix.cell_shadow_types)
 
145
        mw->matrix.cell_shadow_types = (unsigned char **)
 
146
            XtRealloc((char*) mw->matrix.cell_shadow_types,
 
147
                      (mw->matrix.rows + num_rows) *
 
148
                      sizeof(unsigned char *));
 
149
 
 
150
    if (mw->matrix.row_shadow_types)
 
151
        mw->matrix.row_shadow_types = (unsigned char *)
 
152
            XtRealloc((char*) mw->matrix.row_shadow_types,
 
153
                      (mw->matrix.rows + num_rows) *
 
154
                      sizeof(unsigned char));
 
155
 
 
156
    if (mw->matrix.selected_cells)
 
157
        mw->matrix.selected_cells =
 
158
            (Boolean **) XtRealloc((char *) mw->matrix.selected_cells,
 
159
                                   (mw->matrix.rows + num_rows) *
 
160
                                   sizeof(Boolean *));
 
161
 
 
162
#if XmVersion >= 1002
 
163
    if (mw->matrix.highlighted_cells)
 
164
        mw->matrix.highlighted_cells =
 
165
            (unsigned char **) XtRealloc((char *) mw->matrix.highlighted_cells,
 
166
                                         (mw->matrix.rows + num_rows) *
 
167
                                         sizeof(unsigned char *));
 
168
#endif
 
169
    /*
 
170
     * If we are inserting rows into the middle, we need to make room.
 
171
     */
 
172
    if (position < mw->matrix.rows)
 
173
    {
 
174
        if (mw->matrix.cells)
 
175
            BCOPY(&mw->matrix.cells[position],
 
176
                  &mw->matrix.cells[position + num_rows],
 
177
                  (mw->matrix.rows - position) * sizeof(String *));
 
178
        if (mw->matrix.row_labels)
 
179
            BCOPY(&mw->matrix.row_labels[position],
 
180
                  &mw->matrix.row_labels[position + num_rows],
 
181
                  (mw->matrix.rows - position) * sizeof(String));
 
182
        if (mw->matrix.row_button_labels)
 
183
            BCOPY(&mw->matrix.row_button_labels[position],
 
184
                  &mw->matrix.row_button_labels[position + num_rows],
 
185
                  (mw->matrix.rows - position) * sizeof(Boolean));
 
186
        if (mw->matrix.colors)
 
187
            BCOPY(&mw->matrix.colors[position],
 
188
                  &mw->matrix.colors[position + num_rows],
 
189
                  (mw->matrix.rows - position) * sizeof(Pixel *));
 
190
        if (mw->matrix.cell_background)
 
191
            BCOPY(&mw->matrix.cell_background[position],
 
192
                  &mw->matrix.cell_background[position + num_rows],
 
193
                  (mw->matrix.rows - position) * sizeof(Pixel *));
 
194
#if CELL_WIDGETS
 
195
        if (mw->matrix.cell_widgets)
 
196
            BCOPY(&mw->matrix.cell_widgets[position],
 
197
                  &mw->matrix.cell_widgets[position + num_rows],
 
198
                  (mw->matrix.rows - position) * sizeof(Widget *));
 
199
#endif
 
200
        if (mw->matrix.cell_user_data)
 
201
            BCOPY(&mw->matrix.cell_user_data[position],
 
202
                  &mw->matrix.cell_user_data[position + num_rows],
 
203
                  (mw->matrix.rows - position) * sizeof(XtPointer *));
 
204
        if (mw->matrix.row_user_data)
 
205
            BCOPY(&mw->matrix.row_user_data[position],
 
206
                  &mw->matrix.row_user_data[position + num_rows],
 
207
                  (mw->matrix.rows - position) * sizeof(XtPointer));
 
208
        if (mw->matrix.cell_shadow_types)
 
209
            BCOPY(&mw->matrix.cell_shadow_types[position],
 
210
                  &mw->matrix.cell_shadow_types[position + num_rows],
 
211
                  (mw->matrix.rows - position) * sizeof(unsigned char *));
 
212
        if (mw->matrix.row_shadow_types)
 
213
            BCOPY(&mw->matrix.row_shadow_types[position],
 
214
                  &mw->matrix.row_shadow_types[position + num_rows],
 
215
                  (mw->matrix.rows - position) * sizeof(unsigned char));
 
216
        if (mw->matrix.selected_cells)
 
217
            BCOPY(&mw->matrix.selected_cells[position],
 
218
                  &mw->matrix.selected_cells[position + num_rows],
 
219
                  (mw->matrix.rows - position) * sizeof(Boolean *));
 
220
#if XmVersion >= 1002
 
221
        if (mw->matrix.highlighted_cells)
 
222
            BCOPY(&mw->matrix.highlighted_cells[position],
 
223
                  &mw->matrix.highlighted_cells[position + num_rows],
 
224
                  (mw->matrix.rows - position) * sizeof(unsigned char *));
 
225
#endif
 
226
    }
 
227
 
 
228
    /*
 
229
     * Malloc a new row array for each new row. Copy the label for each row.
 
230
     * If no label was passed in, use a NULL String. Malloc a new Pixel
 
231
     * and Boolean row array for each new row.
 
232
     * Use False for new  button label flags.
 
233
     */
 
234
    for (i = 0; i < num_rows; i++)
 
235
    {
 
236
        if (mw->matrix.cells)
 
237
            mw->matrix.cells[i + position] =
 
238
                (String *) XtMalloc(mw->matrix.columns * sizeof(String));
 
239
        if (mw->matrix.row_labels)
 
240
            mw->matrix.row_labels[i + position] =
 
241
                labels ? XtNewString(labels[i]) : XtNewString("");
 
242
        if (mw->matrix.row_button_labels)
 
243
            mw->matrix.row_button_labels[i + position] = False;
 
244
        if (mw->matrix.colors)
 
245
            mw->matrix.colors[i + position] =
 
246
                (Pixel *) XtMalloc(mw->matrix.columns * sizeof(Pixel));
 
247
        if (mw->matrix.cell_background)
 
248
            mw->matrix.cell_background[i + position] =
 
249
                (Pixel *) XtMalloc(mw->matrix.columns * sizeof(Pixel));
 
250
#if CELL_WIDGETS
 
251
        if (mw->matrix.cell_widgets)
 
252
            mw->matrix.cell_widgets[i + position] =
 
253
                (Widget *) XtMalloc(mw->matrix.columns * sizeof(Widget));
 
254
#endif
 
255
        if (mw->matrix.cell_user_data)
 
256
            mw->matrix.cell_user_data[i + position] =
 
257
                (XtPointer *) XtMalloc(mw->matrix.columns * sizeof(XtPointer));
 
258
        if (mw->matrix.row_user_data)
 
259
            mw->matrix.row_user_data[i + position] = (XtPointer) NULL;
 
260
        if (mw->matrix.cell_shadow_types)
 
261
            mw->matrix.cell_shadow_types[i + position] =
 
262
                (unsigned char *) XtMalloc(mw->matrix.columns *
 
263
                                           sizeof(unsigned char));
 
264
        if (mw->matrix.row_shadow_types)
 
265
            mw->matrix.row_shadow_types[i + position] =
 
266
                mw->matrix.cell_shadow_type;
 
267
        if (mw->matrix.selected_cells)
 
268
            mw->matrix.selected_cells[i + position] =
 
269
                (Boolean *) XtMalloc(mw->matrix.columns * sizeof(Boolean));
 
270
#if XmVersion >= 1002
 
271
        if (mw->matrix.highlighted_cells)
 
272
            mw->matrix.highlighted_cells[i + position] =
 
273
                (unsigned char *) XtMalloc(mw->matrix.columns *
 
274
                                           sizeof(unsigned char));
 
275
#endif
 
276
    }
 
277
 
 
278
    /*
 
279
     * Copy the rows arrays passed in into each new row, or if NULL
 
280
     * was passed in initialize each row to NULL Strings. Copy the colors
 
281
     * arrays passed in into each new row, if NULL was passed use foreground.
 
282
     */
 
283
    for (i = 0; i < num_rows; i++)
 
284
        for (j = 0; j < mw->matrix.columns; j++)
 
285
        {
 
286
            if (mw->matrix.cells) /* NULL row[j] is empty string. Earl R. */
 
287
                mw->matrix.cells[i + position][j] = rows ?
 
288
                    XtNewString((rows[i * mw->matrix.columns + j] ?
 
289
                                 rows[i * mw->matrix.columns + j] : "")) :
 
290
                XtNewString("");
 
291
            if (mw->matrix.colors)
 
292
                mw->matrix.colors[i + position][j] =
 
293
                    colors ? colors[i] : mw->manager.foreground;
 
294
            if (mw->matrix.cell_background)
 
295
                mw->matrix.cell_background[i + position][j] =
 
296
                    backgrounds ? backgrounds[i] : mw->core.background_pixel;
 
297
#if CELL_WIDGETS
 
298
            if (mw->matrix.cell_widgets)
 
299
                mw->matrix.cell_widgets[i + position][j] = NULL;
 
300
#endif
 
301
            if (mw->matrix.cell_user_data)
 
302
                mw->matrix.cell_user_data[i + position][j] = (XtPointer) NULL;
 
303
            if (mw->matrix.cell_shadow_types)
 
304
                mw->matrix.cell_shadow_types[i + position][j] =
 
305
                    mw->matrix.cell_shadow_type;
 
306
            if (mw->matrix.selected_cells)
 
307
                mw->matrix.selected_cells[i + position][j] = False;
 
308
#if XmVersion >= 1002
 
309
            if (mw->matrix.highlighted_cells)
 
310
                mw->matrix.highlighted_cells[i + position][j] = HighlightNone;
 
311
#endif
 
312
        }
 
313
 
 
314
    mw->matrix.rows += num_rows;
 
315
}
 
316
 
 
317
/*
 
318
 * Delete rows from the internal cells data structure.
 
319
 */
 
320
static void
 
321
DeleteRowsFromTable(mw, position, num_rows)
 
322
XbaeMatrixWidget mw;
 
323
int position;
 
324
int num_rows;
 
325
{
 
326
    int i, j;
 
327
 
 
328
    /*
 
329
     * We don't bother to realloc, we will just have some wasted space.
 
330
     * XXX is this a problem?
 
331
     */
 
332
 
 
333
    /*
 
334
     * Free all the cells in the rows being deleted and the rows themselves.
 
335
     * Also free the String row labels and label button flags.  Free the color
 
336
     * arrays for the rows being deleted.
 
337
     */
 
338
    for (i = position; i < position + num_rows; i++)
 
339
    {
 
340
        /* Fixed a crash I was getting, Since I allow NULL cells. Earl R. */
 
341
        if (mw->matrix.cells && mw->matrix.cells[i])
 
342
        {
 
343
            for (j = 0; j < mw->matrix.columns; j++)
 
344
                if (mw->matrix.cells[i][j])
 
345
                    XtFree((XtPointer) mw->matrix.cells[i][j]);
 
346
            XtFree((XtPointer) mw->matrix.cells[i]);
 
347
            mw->matrix.cells[i] = NULL;
 
348
        }
 
349
        if (mw->matrix.row_labels) {
 
350
            XtFree((XtPointer) mw->matrix.row_labels[i]);
 
351
            mw->matrix.row_labels[i] = NULL;
 
352
        }    
 
353
        if (mw->matrix.colors) {
 
354
            XtFree((XtPointer) mw->matrix.colors[i]);
 
355
            mw->matrix.colors[i] = NULL;
 
356
        }    
 
357
        if (mw->matrix.cell_background) {
 
358
            XtFree((XtPointer) mw->matrix.cell_background[i]);
 
359
            mw->matrix.cell_background[i] = NULL;
 
360
        }    
 
361
#if CELL_WIDGETS
 
362
        if (mw->matrix.cell_widgets) {
 
363
            XtFree((XtPointer) mw->matrix.cell_widgets[i]);
 
364
            mw->matrix.cell_widgets[i] = NULL;
 
365
        }    
 
366
#endif
 
367
        if (mw->matrix.cell_user_data) {
 
368
            XtFree((XtPointer) mw->matrix.cell_user_data[i]);
 
369
            mw->matrix.cell_user_data[i] = NULL;
 
370
        }    
 
371
        if (mw->matrix.cell_shadow_types) {
 
372
            XtFree((XtPointer) mw->matrix.cell_shadow_types[i]);
 
373
            mw->matrix.cell_shadow_types[i] = NULL;
 
374
        }    
 
375
        if (mw->matrix.selected_cells) {
 
376
            /*
 
377
             * Deselect the row so num_selected_cells gets updated
 
378
             */
 
379
            xbaeDeselectRow(mw, i);
 
380
            XtFree((XtPointer) mw->matrix.selected_cells[i]);
 
381
            mw->matrix.selected_cells[i] = NULL;
 
382
        }
 
383
#if XmVersion >= 1002
 
384
        if (mw->matrix.highlighted_cells) {
 
385
            XtFree((XtPointer) mw->matrix.highlighted_cells[i]);
 
386
            mw->matrix.highlighted_cells[i] = NULL;
 
387
        }    
 
388
#endif
 
389
    }
 
390
 
 
391
    /*
 
392
     * Copy those rows which are below the ones deleted, up.
 
393
     * (unless we deleted rows from the bottom).
 
394
     */
 
395
    if (position + num_rows < mw->matrix.rows)
 
396
    {
 
397
        if (mw->matrix.cells)        
 
398
            BCOPY(&mw->matrix.cells[position + num_rows],
 
399
                  &mw->matrix.cells[position],
 
400
                  (mw->matrix.rows - position - num_rows) * sizeof(String *));
 
401
        if (mw->matrix.row_labels)
 
402
            BCOPY(&mw->matrix.row_labels[position + num_rows],
 
403
                  &mw->matrix.row_labels[position],
 
404
                  (mw->matrix.rows - position - num_rows) * sizeof(String));
 
405
        if (mw->matrix.row_button_labels)
 
406
            BCOPY(&mw->matrix.row_button_labels[position + num_rows],
 
407
                  &mw->matrix.row_button_labels[position],
 
408
                  (mw->matrix.rows - position - num_rows) * sizeof(Boolean));
 
409
        if (mw->matrix.colors)
 
410
            BCOPY(&mw->matrix.colors[position + num_rows],
 
411
                  &mw->matrix.colors[position],
 
412
                  (mw->matrix.rows - position - num_rows) * sizeof(Pixel *));
 
413
        if (mw->matrix.cell_background)
 
414
            BCOPY(&mw->matrix.cell_background[position + num_rows],
 
415
                  &mw->matrix.cell_background[position],
 
416
                  (mw->matrix.rows - position - num_rows) * sizeof(Pixel *));
 
417
#if CELL_WIDGETS
 
418
        if (mw->matrix.cell_widgets)
 
419
            BCOPY(&mw->matrix.cell_widgets[position + num_rows],
 
420
                  &mw->matrix.cell_widgets[position],
 
421
                  (mw->matrix.rows - position - num_rows) * sizeof(Widget *));
 
422
#endif
 
423
        if (mw->matrix.cell_user_data)
 
424
            BCOPY(&mw->matrix.cell_user_data[position + num_rows],
 
425
                  &mw->matrix.cell_user_data[position],
 
426
                  (mw->matrix.rows - position - num_rows) *
 
427
                  sizeof(XtPointer *));
 
428
        if (mw->matrix.row_user_data)
 
429
            BCOPY(&mw->matrix.row_user_data[position + num_rows],
 
430
                  &mw->matrix.row_user_data[position],
 
431
                  (mw->matrix.rows - position - num_rows) * sizeof(XtPointer *));
 
432
        if (mw->matrix.cell_shadow_types)
 
433
            BCOPY(&mw->matrix.cell_shadow_types[position + num_rows],
 
434
                  &mw->matrix.cell_shadow_types[position],
 
435
                  (mw->matrix.rows - position - num_rows) *
 
436
                  sizeof(unsigned char *));
 
437
        if (mw->matrix.row_shadow_types)
 
438
            BCOPY(&mw->matrix.row_shadow_types[position + num_rows],
 
439
                  &mw->matrix.row_shadow_types[position],
 
440
                  (mw->matrix.rows - position - num_rows) *
 
441
                  sizeof(unsigned char *));
 
442
        if (mw->matrix.selected_cells)
 
443
            BCOPY(&mw->matrix.selected_cells[position + num_rows],
 
444
                  &mw->matrix.selected_cells[position],
 
445
                  (mw->matrix.rows - position - num_rows) * sizeof(Boolean *));
 
446
#if XmVersion >= 1002
 
447
        if (mw->matrix.highlighted_cells)
 
448
            BCOPY(&mw->matrix.highlighted_cells[position + num_rows],
 
449
                  &mw->matrix.highlighted_cells[position],
 
450
                  (mw->matrix.rows - position - num_rows) *
 
451
                  sizeof(unsigned char *));
 
452
#endif
 
453
    }
 
454
 
 
455
    mw->matrix.rows -= num_rows;
 
456
}
 
457
 
 
458
/*
 
459
 * Add columns to the internal cells data structure.
 
460
 * If columns or labels is NULL, add empty columns.
 
461
 * If max_lengths is NULL, widths will be used.
 
462
 * If alignments is NULL, use XmALIGNMENT_BEGINNING.
 
463
 * If label_alignments is NULL, use alignments, or if it is NULL
 
464
 *   XmALIGNMENT_BEGINNING.
 
465
 * widths must not be NULL.
 
466
 */
 
467
static void
 
468
AddColumnsToTable(mw, position, columns, labels, widths, max_lengths,
 
469
                  alignments, label_alignments, colors, backgrounds,
 
470
                  num_columns)
 
471
XbaeMatrixWidget mw;
 
472
int position;
 
473
String *columns;
 
474
String *labels;
 
475
short *widths;
 
476
int *max_lengths;
 
477
unsigned char *alignments;
 
478
unsigned char *label_alignments;
 
479
Pixel *colors;
 
480
Pixel *backgrounds;
 
481
int num_columns;
 
482
{
 
483
    int i, j;
 
484
 
 
485
    /*
 
486
     * Realloc larger cells, widths, max_lengths, alignments, colors,
 
487
     * highlighted_cells, selected_cells, labels and label lines arrays.
 
488
     */
 
489
 
 
490
    if (mw->matrix.rows == 0)
 
491
    {
 
492
        XtAppWarningMsg(
 
493
            XtWidgetToApplicationContext((Widget) mw),
 
494
            "AddColumns", "noRows", "XbaeMatrix",
 
495
            "XbaeMatrix: Attempting to add columns with no rows.",
 
496
            NULL, 0);
 
497
        return;
 
498
    }
 
499
 
 
500
    for (i = 0; i < mw->matrix.rows; i++)
 
501
    {
 
502
        if (mw->matrix.cells || columns)
 
503
        {
 
504
            if (!mw->matrix.cells)
 
505
            {
 
506
                mw->matrix.columns += num_columns;
 
507
                xbaeCopyCells(mw);
 
508
                mw->matrix.columns -= num_columns;
 
509
            }
 
510
            else
 
511
                mw->matrix.cells[i] =
 
512
                    (String *) XtRealloc((char *) mw->matrix.cells[i],
 
513
                                         (mw->matrix.columns + num_columns) *
 
514
                                         sizeof(String));
 
515
        }
 
516
        if (mw->matrix.colors || colors)
 
517
        {
 
518
            if (!mw->matrix.colors)
 
519
            {
 
520
                mw->matrix.columns += num_columns;
 
521
                xbaeCopyColors(mw);
 
522
                mw->matrix.columns -= num_columns;
 
523
            }
 
524
            else
 
525
                mw->matrix.colors[i] =
 
526
                    (Pixel *) XtRealloc((char *) mw->matrix.colors[i],
 
527
                                        (mw->matrix.columns + num_columns) *
 
528
                                        sizeof(Pixel));
 
529
        }
 
530
        if (mw->matrix.cell_background || backgrounds)
 
531
        {
 
532
            if (!mw->matrix.cell_background)
 
533
            {
 
534
                mw->matrix.columns += num_columns;
 
535
                xbaeCopyBackgrounds(mw);
 
536
                mw->matrix.columns -= num_columns;
 
537
            }
 
538
            else
 
539
                mw->matrix.cell_background[i] =
 
540
                    (Pixel *) XtRealloc((char *) mw->matrix.cell_background[i],
 
541
                                        (mw->matrix.columns + num_columns) *
 
542
                                        sizeof(Pixel));
 
543
        }
 
544
#if CELL_WIDGETS
 
545
        if (mw->matrix.cell_widgets)
 
546
            mw->matrix.cell_widgets[i] =
 
547
                (Widget *) XtRealloc((char *) mw->matrix.cell_widgets[i],
 
548
                                     (mw->matrix.columns + num_columns) *
 
549
                                     sizeof(Widget));
 
550
#endif
 
551
        if (mw->matrix.cell_user_data)
 
552
            mw->matrix.cell_user_data[i] = (XtPointer *)
 
553
                XtRealloc((char*) mw->matrix.cell_user_data[i],
 
554
                          (mw->matrix.columns + num_columns) *
 
555
                          sizeof(XtPointer));
 
556
        if (mw->matrix.cell_shadow_types)
 
557
            mw->matrix.cell_shadow_types[i] = (unsigned char *)
 
558
                XtRealloc((char*) mw->matrix.cell_shadow_types[i],
 
559
                          (mw->matrix.columns + num_columns) *
 
560
                          sizeof(unsigned char));
 
561
        if (mw->matrix.selected_cells)
 
562
            mw->matrix.selected_cells[i] =
 
563
                (Boolean *) XtRealloc((char *) mw->matrix.selected_cells[i],
 
564
                                      (mw->matrix.columns + num_columns) *
 
565
                                      sizeof(Boolean));
 
566
#if XmVersion >= 1002
 
567
        if (mw->matrix.highlighted_cells)
 
568
            mw->matrix.highlighted_cells[i] =
 
569
                (unsigned char *) XtRealloc(
 
570
                    (char *) mw->matrix.highlighted_cells[i],
 
571
                    (mw->matrix.columns + num_columns) *
 
572
                    sizeof(unsigned char));
 
573
#endif
 
574
    }
 
575
 
 
576
    mw->matrix.column_widths =
 
577
        (short *) XtRealloc((char *) mw->matrix.column_widths,
 
578
                            (mw->matrix.columns + num_columns) *
 
579
                            sizeof(short));
 
580
 
 
581
    if (mw->matrix.column_max_lengths)
 
582
        mw->matrix.column_max_lengths =
 
583
            (int *) XtRealloc((char *) mw->matrix.column_max_lengths,
 
584
                              (mw->matrix.columns + num_columns) *
 
585
                              sizeof(int));
 
586
 
 
587
    if (mw->matrix.column_alignments)
 
588
        mw->matrix.column_alignments =
 
589
            (unsigned char *)
 
590
            XtRealloc((char *) mw->matrix.column_alignments,
 
591
                      (mw->matrix.columns + num_columns) *
 
592
                      sizeof(unsigned char));
 
593
 
 
594
    if (mw->matrix.column_button_labels)
 
595
        mw->matrix.column_button_labels =
 
596
            (Boolean *) XtRealloc((char *) mw->matrix.
 
597
                                  column_button_labels,
 
598
                                  (mw->matrix.columns + num_columns) *
 
599
                                  sizeof(Boolean));
 
600
 
 
601
    if (mw->matrix.column_label_alignments)
 
602
        mw->matrix.column_label_alignments =
 
603
            (unsigned char *) XtRealloc((char *) mw->matrix.
 
604
                                        column_label_alignments,
 
605
                                        (mw->matrix.columns + num_columns) *
 
606
                                        sizeof(unsigned char));
 
607
 
 
608
    if (mw->matrix.column_user_data)
 
609
        mw->matrix.column_user_data = (XtPointer*)
 
610
            XtRealloc((char*) mw->matrix.column_user_data,
 
611
                      (mw->matrix.columns + num_columns) *
 
612
                      sizeof(XtPointer));
 
613
 
 
614
    if (mw->matrix.column_shadow_types)
 
615
        mw->matrix.column_shadow_types = (unsigned char *)
 
616
            XtRealloc((char*) mw->matrix.column_shadow_types,
 
617
                      (mw->matrix.columns + num_columns) *
 
618
                      sizeof(unsigned char));
 
619
 
 
620
    if (mw->matrix.column_labels)
 
621
    {
 
622
        mw->matrix.column_labels =
 
623
            (String *) XtRealloc((char *) mw->matrix.column_labels,
 
624
                                 (mw->matrix.columns + num_columns) *
 
625
                                 sizeof(String));
 
626
        mw->matrix.column_label_lines =
 
627
            (ColumnLabelLines) XtRealloc(
 
628
                (char *) mw->matrix.column_label_lines, (mw->matrix.columns +
 
629
                                                         num_columns) *
 
630
                sizeof(ColumnLabelLinesRec));
 
631
    }
 
632
 
 
633
    /*
 
634
     * If we are inserting columns into the middle, we need to make room.
 
635
     */
 
636
    if (position < mw->matrix.columns)
 
637
    {
 
638
        BCOPY(&mw->matrix.column_widths[position],
 
639
              &mw->matrix.column_widths[position + num_columns],
 
640
              (mw->matrix.columns - position) * sizeof(short));
 
641
 
 
642
        if (mw->matrix.column_max_lengths)
 
643
            BCOPY(&mw->matrix.column_max_lengths[position],
 
644
                  &mw->matrix.column_max_lengths[position + num_columns],
 
645
                  (mw->matrix.columns - position) * sizeof(int));
 
646
 
 
647
        if (mw->matrix.column_alignments)
 
648
            BCOPY(&mw->matrix.column_alignments[position],
 
649
                  &mw->matrix.column_alignments[position + num_columns],
 
650
                  (mw->matrix.columns - position) * sizeof(unsigned char));
 
651
 
 
652
        if (mw->matrix.column_button_labels)
 
653
            BCOPY(&mw->matrix.column_button_labels[position],
 
654
                  &mw->matrix.column_button_labels[position + num_columns],
 
655
                  (mw->matrix.columns - position) * sizeof(Boolean));
 
656
 
 
657
        if (mw->matrix.column_label_alignments)
 
658
            BCOPY(&mw->matrix.column_label_alignments[position],
 
659
                  &mw->matrix.column_label_alignments[position + num_columns],
 
660
                  (mw->matrix.columns - position) * sizeof(unsigned char));
 
661
 
 
662
        if (mw->matrix.column_user_data)
 
663
            BCOPY(&mw->matrix.column_user_data[position],
 
664
                  &mw->matrix.column_user_data[position + num_columns],
 
665
                  (mw->matrix.columns - position) * sizeof(XtPointer));
 
666
 
 
667
        if (mw->matrix.column_shadow_types)
 
668
            BCOPY(&mw->matrix.column_shadow_types[position],
 
669
                  &mw->matrix.column_shadow_types[position + num_columns],
 
670
                  (mw->matrix.columns - position) * sizeof(unsigned char));
 
671
        
 
672
        if (mw->matrix.column_labels)
 
673
        {
 
674
            BCOPY(&mw->matrix.column_labels[position],
 
675
                  &mw->matrix.column_labels[position + num_columns],
 
676
                  (mw->matrix.columns - position) * sizeof(String));
 
677
            BCOPY(&mw->matrix.column_label_lines[position],
 
678
                  &mw->matrix.column_label_lines[position + num_columns],
 
679
                  (mw->matrix.columns - position) *
 
680
                  sizeof(ColumnLabelLinesRec));
 
681
        }
 
682
 
 
683
        /*
 
684
         * Shift the columns in each row.
 
685
         */
 
686
        for (i = 0; i < mw->matrix.rows; i++)
 
687
        {
 
688
            if (mw->matrix.cells)
 
689
                BCOPY(&mw->matrix.cells[i][position],
 
690
                      &mw->matrix.cells[i][position + num_columns],
 
691
                      (mw->matrix.columns - position) * sizeof(String));
 
692
            if (mw->matrix.colors)
 
693
                BCOPY(&mw->matrix.colors[i][position],
 
694
                      &mw->matrix.colors[i][position + num_columns],
 
695
                      (mw->matrix.columns - position) * sizeof(Pixel));
 
696
            if (mw->matrix.cell_background)
 
697
                BCOPY(&mw->matrix.cell_background[i][position],
 
698
                      &mw->matrix.cell_background[i][position + num_columns],
 
699
                      (mw->matrix.columns - position) * sizeof(Pixel));
 
700
#if CELL_WIDGETS
 
701
            if (mw->matrix.cell_widgets)
 
702
                BCOPY(&mw->matrix.cell_widgets[i][position],
 
703
                      &mw->matrix.cell_widgets[i][position + num_columns],
 
704
                      (mw->matrix.columns - position) * sizeof(Widget));
 
705
#endif
 
706
            if (mw->matrix.cell_user_data)
 
707
                BCOPY(&mw->matrix.cell_user_data[i][position],
 
708
                      &mw->matrix.cell_user_data[i][position + num_columns],
 
709
                      (mw->matrix.columns - position) * sizeof(XtPointer));
 
710
            if (mw->matrix.cell_shadow_types)
 
711
                BCOPY(&mw->matrix.cell_shadow_types[i][position],
 
712
                      &mw->matrix.cell_shadow_types[i][position + num_columns],
 
713
                      (mw->matrix.columns - position) * sizeof(unsigned char));
 
714
            if (mw->matrix.selected_cells)
 
715
                BCOPY(&mw->matrix.selected_cells[i][position],
 
716
                      &mw->matrix.selected_cells[i][position + num_columns],
 
717
                      (mw->matrix.columns - position) * sizeof(Boolean));
 
718
#if XmVersion >= 1002
 
719
            if (mw->matrix.highlighted_cells)
 
720
                BCOPY(&mw->matrix.highlighted_cells[i][position],
 
721
                      &mw->matrix.highlighted_cells[i][position + num_columns],
 
722
                      (mw->matrix.columns - position) * sizeof(unsigned char));
 
723
#endif
 
724
        }
 
725
    }
 
726
 
 
727
    /*
 
728
     * Copy all of the passed in info into each new column
 
729
     * (except column_positions which will be recalculated below).
 
730
     * If columns or labels is NULL, add empty columns.
 
731
     * If max_lengths is NULL, widths will be used.
 
732
     * If alignments is NULL, use XmALIGNMENT_BEGINNING.
 
733
     * If label_alignments is NULL, use XmALIGNMENT_BEGINNING
 
734
     * If labels is NULL, use NULL strings.
 
735
     * If colors is NULL, use foreground.
 
736
     * Use False for new  button label flags.
 
737
     */
 
738
    for (j = 0; j < num_columns; j++)
 
739
    {
 
740
        mw->matrix.column_widths[j + position] = widths[j];
 
741
 
 
742
        if (mw->matrix.column_max_lengths)
 
743
            mw->matrix.column_max_lengths[j + position] =
 
744
                max_lengths ? max_lengths[j] : (int) widths[j];
 
745
 
 
746
        if (mw->matrix.column_alignments)
 
747
            mw->matrix.column_alignments[j + position] =
 
748
                alignments ? alignments[j] : XmALIGNMENT_BEGINNING;
 
749
 
 
750
        if (mw->matrix.column_button_labels)
 
751
            mw->matrix.column_button_labels[j + position] = False;
 
752
        
 
753
        if (mw->matrix.column_label_alignments)
 
754
            mw->matrix.column_label_alignments[j + position] =
 
755
                label_alignments ? label_alignments[j] : XmALIGNMENT_BEGINNING;
 
756
        
 
757
        if (mw->matrix.column_user_data)
 
758
            mw->matrix.column_user_data[j + position] = (XtPointer) NULL;
 
759
 
 
760
#if CELL_WIDGETS
 
761
        if (mw->matrix.cell_widgets)
 
762
            mw->matrix.cell_widgets[j + position] = NULL;
 
763
#endif
 
764
 
 
765
        if (mw->matrix.column_shadow_types)
 
766
            mw->matrix.column_shadow_types[j + position] =
 
767
                mw->matrix.cell_shadow_type;
 
768
 
 
769
        if (mw->matrix.column_labels)
 
770
        {
 
771
            mw->matrix.column_labels[j + position] =
 
772
                labels ? XtNewString(labels[j]) : XtNewString("");
 
773
            xbaeParseColumnLabel(mw->matrix.column_labels[j + position],
 
774
                                 &mw->matrix.column_label_lines[j + position]);
 
775
        }
 
776
 
 
777
        /*
 
778
         * Add this new column to each row.
 
779
         */
 
780
        for (i = 0; i < mw->matrix.rows; i++)
 
781
        {
 
782
            if (mw->matrix.cells)
 
783
                mw->matrix.cells[i][j + position] = columns ?
 
784
                    XtNewString(columns[i * num_columns + j]) :
 
785
                XtNewString("");
 
786
            if (mw->matrix.colors)
 
787
                mw->matrix.colors[i][j + position] =
 
788
                    colors ? colors[j] : mw->manager.foreground;
 
789
            if (mw->matrix.cell_background)
 
790
                mw->matrix.cell_background[i][j + position] =
 
791
                    backgrounds ? backgrounds[j] : mw->core.background_pixel;
 
792
#if CELL_WIDGETS
 
793
            if (mw->matrix.cell_widgets)
 
794
                mw->matrix.cell_widgets[i][j + position] = (Widget) NULL;
 
795
#endif
 
796
            if (mw->matrix.cell_user_data)
 
797
                mw->matrix.cell_user_data[i][j + position] = (XtPointer) NULL;
 
798
            if (mw->matrix.cell_shadow_types)
 
799
                mw->matrix.cell_shadow_types[i][j + position] =
 
800
                    mw->matrix.cell_shadow_type;
 
801
            if (mw->matrix.selected_cells)
 
802
                mw->matrix.selected_cells[i][j + position] = False;
 
803
#if XmVersion >= 1002
 
804
            if (mw->matrix.highlighted_cells)
 
805
                mw->matrix.highlighted_cells[i][j + position] = HighlightNone;
 
806
#endif
 
807
        }
 
808
    }
 
809
 
 
810
    mw->matrix.columns += num_columns;
 
811
    xbaeGetCellTotalWidth(mw);
 
812
 
 
813
    /*
 
814
     * See if the max number of column label lines changed
 
815
     */
 
816
    if (mw->matrix.column_labels)
 
817
    {
 
818
        int end;
 
819
 
 
820
        end = position + num_columns;
 
821
        for (i = position; i < end; i++)
 
822
            if (mw->matrix.column_label_lines[i].lines >
 
823
                mw->matrix.column_label_maxlines)
 
824
                mw->matrix.column_label_maxlines =
 
825
                    mw->matrix.column_label_lines[i].lines;
 
826
    }
 
827
 
 
828
    /*
 
829
     * Recalculate the column positions
 
830
     */
 
831
    xbaeFreeColumnPositions(mw);
 
832
    mw->matrix.column_positions = CreateColumnPositions(mw);
 
833
    xbaeGetColumnPositions(mw);
 
834
}
 
835
 
 
836
/*
 
837
 * Delete columns from the internal cells data structure.
 
838
 */
 
839
static void
 
840
DeleteColumnsFromTable(mw, position, num_columns)
 
841
XbaeMatrixWidget mw;
 
842
int position;
 
843
int num_columns;
 
844
{
 
845
    int i, j;
 
846
 
 
847
    /*
 
848
     * Free all the cells in the columns being deleted.
 
849
     * Also free the String column labels and the associated ColumnLabelLines
 
850
     * lengths arrays, and the column button label flags.
 
851
     */
 
852
    for (j = position; j < position + num_columns; j++)
 
853
    {
 
854
        if (mw->matrix.cells)
 
855
            for (i = 0; i < mw->matrix.rows; i++) {
 
856
                XtFree((XtPointer) mw->matrix.cells[i][j]);
 
857
                mw->matrix.cells[i][j] = NULL;
 
858
            }    
 
859
        if (mw->matrix.column_labels)
 
860
        {
 
861
            XtFree((XtPointer) mw->matrix.column_labels[j]);
 
862
            mw->matrix.column_labels[j] = NULL;
 
863
            XtFree((XtPointer) mw->matrix.column_label_lines[j].lengths);
 
864
            mw->matrix.column_label_lines[j].lengths = NULL;
 
865
        }
 
866
    }
 
867
 
 
868
    /*
 
869
     * Shift those columns after the ones being deleted, left.
 
870
     * (unless we deleted columns from the right).
 
871
     */
 
872
    if (position + num_columns < mw->matrix.columns)
 
873
    {
 
874
        BCOPY(&mw->matrix.column_widths[position + num_columns],
 
875
              &mw->matrix.column_widths[position],
 
876
              (mw->matrix.columns - position - num_columns) * sizeof(short));
 
877
 
 
878
        if (mw->matrix.column_max_lengths)
 
879
            BCOPY(&mw->matrix.column_max_lengths[position + num_columns],
 
880
                  &mw->matrix.column_max_lengths[position],
 
881
                  (mw->matrix.columns - position - num_columns) * sizeof(int));
 
882
 
 
883
        if (mw->matrix.column_alignments)
 
884
            BCOPY(&mw->matrix.column_alignments[position + num_columns],
 
885
                  &mw->matrix.column_alignments[position],
 
886
                  (mw->matrix.columns - position - num_columns) *
 
887
                  sizeof(unsigned char));
 
888
 
 
889
        if (mw->matrix.column_button_labels)
 
890
            BCOPY(&mw->matrix.column_button_labels[position + num_columns],
 
891
                  &mw->matrix.column_button_labels[position],
 
892
                  (mw->matrix.columns - position - num_columns) *
 
893
                  sizeof(Boolean));
 
894
 
 
895
        if (mw->matrix.column_label_alignments)
 
896
            BCOPY(&mw->matrix.column_label_alignments[position + num_columns],
 
897
                  &mw->matrix.column_label_alignments[position],
 
898
                  (mw->matrix.columns - position - num_columns) *
 
899
                  sizeof(unsigned char));
 
900
 
 
901
        if (mw->matrix.column_user_data)
 
902
            BCOPY(&mw->matrix.column_user_data[position + num_columns],
 
903
                  &mw->matrix.column_user_data[position],
 
904
                  (mw->matrix.columns - position - num_columns) *
 
905
                  sizeof(XtPointer));
 
906
 
 
907
#if CELL_WIDGETS
 
908
        if (mw->matrix.cell_widgets)
 
909
            BCOPY(&mw->matrix.cell_widgets[position + num_columns],
 
910
                  &mw->matrix.cell_widgets[position],
 
911
                  (mw->matrix.columns - position - num_columns) *
 
912
                  sizeof(Widget));
 
913
#endif
 
914
 
 
915
        if (mw->matrix.column_shadow_types)
 
916
            BCOPY(&mw->matrix.column_shadow_types[position + num_columns],
 
917
                  &mw->matrix.column_shadow_types[position],
 
918
                  (mw->matrix.columns - position - num_columns) *
 
919
                  sizeof(unsigned char));
 
920
 
 
921
        if (mw->matrix.column_labels)
 
922
        {
 
923
            BCOPY(&mw->matrix.column_labels[position + num_columns],
 
924
                  &mw->matrix.column_labels[position],
 
925
                  (mw->matrix.columns - position - num_columns) *
 
926
                  sizeof(String));
 
927
            BCOPY(&mw->matrix.column_label_lines[position + num_columns],
 
928
                  &mw->matrix.column_label_lines[position],
 
929
                  (mw->matrix.columns - position - num_columns) *
 
930
                  sizeof(ColumnLabelLinesRec));
 
931
        }
 
932
 
 
933
        /*
 
934
         * Shift the columns in each row.
 
935
         */
 
936
        for (i = 0; i < mw->matrix.rows; i++)
 
937
        {
 
938
            if (mw->matrix.cells)
 
939
                BCOPY(&mw->matrix.cells[i][position + num_columns],
 
940
                      &mw->matrix.cells[i][position],
 
941
                      (mw->matrix.columns - position - num_columns) *
 
942
                      sizeof(String));
 
943
            if (mw->matrix.colors)
 
944
                BCOPY(&mw->matrix.colors[i][position + num_columns],
 
945
                      &mw->matrix.colors[i][position],
 
946
                      (mw->matrix.columns - position - num_columns) *
 
947
                      sizeof(Pixel));
 
948
            if (mw->matrix.cell_background)
 
949
                BCOPY(&mw->matrix.cell_background[i][position + num_columns],
 
950
                      &mw->matrix.cell_background[i][position],
 
951
                      (mw->matrix.columns - position - num_columns) *
 
952
                      sizeof(Pixel));
 
953
#if CELL_WIDGETS
 
954
            if (mw->matrix.cell_widgets)
 
955
                BCOPY(&mw->matrix.cell_widgets[i][position + num_columns],
 
956
                      &mw->matrix.cell_widgets[i][position],
 
957
                      (mw->matrix.columns - position - num_columns) *
 
958
                      sizeof(Widget));
 
959
#endif
 
960
            if (mw->matrix.cell_user_data)
 
961
                BCOPY(&mw->matrix.cell_user_data[i][position + num_columns],
 
962
                      &mw->matrix.cell_user_data[i][position],
 
963
                      (mw->matrix.columns - position - num_columns) *
 
964
                      sizeof(XtPointer));
 
965
            if (mw->matrix.cell_shadow_types)
 
966
                BCOPY(&mw->matrix.cell_shadow_types[i][position + num_columns],
 
967
                      &mw->matrix.cell_shadow_types[i][position],
 
968
                      (mw->matrix.columns - position - num_columns) *
 
969
                      sizeof(unsigned char));
 
970
            if (mw->matrix.selected_cells)
 
971
                BCOPY(&mw->matrix.selected_cells[i][position + num_columns],
 
972
                      &mw->matrix.selected_cells[i][position],
 
973
                      (mw->matrix.columns - position - num_columns) *
 
974
                      sizeof(Boolean));
 
975
#if XmVersion >= 1002
 
976
            if (mw->matrix.highlighted_cells)
 
977
                BCOPY(&mw->matrix.highlighted_cells[i][position + num_columns],
 
978
                      &mw->matrix.highlighted_cells[i][position],
 
979
                      (mw->matrix.columns - position - num_columns) *
 
980
                      sizeof(unsigned char));
 
981
#endif
 
982
        }
 
983
    }
 
984
 
 
985
    mw->matrix.columns -= num_columns;
 
986
    xbaeGetCellTotalWidth(mw);
 
987
 
 
988
    /*
 
989
     * See if the max number of column label lines changed
 
990
     */
 
991
    if (mw->matrix.column_labels)
 
992
    {
 
993
        mw->matrix.column_label_maxlines =
 
994
            mw->matrix.column_label_lines[0].lines;
 
995
        for (i = 1; i < mw->matrix.columns; i++)
 
996
            if (mw->matrix.column_label_lines[i].lines >
 
997
                mw->matrix.column_label_maxlines)
 
998
                mw->matrix.column_label_maxlines =
 
999
                    mw->matrix.column_label_lines[i].lines;
 
1000
    }
 
1001
 
 
1002
    /*
 
1003
     * Recalculate the column positions
 
1004
     */
 
1005
    xbaeFreeColumnPositions(mw);
 
1006
    mw->matrix.column_positions = CreateColumnPositions(mw);
 
1007
    xbaeGetColumnPositions(mw);
 
1008
}
 
1009
 
 
1010
/*
 
1011
 * Matrix set_cell method
 
1012
 */
 
1013
void
 
1014
#if NeedFunctionPrototypes
 
1015
xbaeSetCell(XbaeMatrixWidget mw, int row, int column, const String value,
 
1016
            Boolean update_text)
 
1017
#else
 
1018
xbaeSetCell(mw, row, column, value, update_text)
 
1019
XbaeMatrixWidget mw;
 
1020
int row;
 
1021
int column;
 
1022
const String value;
 
1023
Boolean update_text;
 
1024
#endif
 
1025
{
 
1026
    if (row >= mw->matrix.rows || row < 0 ||
 
1027
        column >= mw->matrix.columns || column < 0)
 
1028
    {
 
1029
        XtAppWarningMsg(
 
1030
            XtWidgetToApplicationContext((Widget) mw),
 
1031
            "xbaeSetCell", "badIndex", "XbaeMatrix",
 
1032
            "XbaeMatrix: Row or column out of bounds for xbaeSetCell.",
 
1033
            NULL, 0);
 
1034
        return;
 
1035
    }
 
1036
 
 
1037
    /*
 
1038
     * If we have a draw cell callback, we must have a write cell callback
 
1039
     * also if we want to set the data.  Use this callback to write the
 
1040
     * new data back to the application.
 
1041
     */
 
1042
    if (mw->matrix.draw_cell_callback)
 
1043
    {
 
1044
         XbaeMatrixWriteCellCallbackStruct call_data;
 
1045
 
 
1046
        if (mw->matrix.write_cell_callback)
 
1047
        {
 
1048
            call_data.reason = XbaeWriteCellReason;
 
1049
            call_data.event = (XEvent *)NULL;
 
1050
            call_data.row = row;
 
1051
            call_data.column = column;
 
1052
            call_data.string = value;
 
1053
            call_data.type = XbaeString;
 
1054
            call_data.pixmap = (Pixmap)NULL;
 
1055
            call_data.mask = (Pixmap)NULL;
 
1056
 
 
1057
            XtCallCallbackList((Widget)mw, mw->matrix.write_cell_callback,
 
1058
                               (XtPointer) &call_data);
 
1059
        }
 
1060
    }
 
1061
    else
 
1062
    {
 
1063
        /*
 
1064
         * Store the new value in the cell.
 
1065
         */
 
1066
        if (!mw->matrix.cells && value[0] != 0)
 
1067
            /*
 
1068
             * The user typed something, there is no drawCellCallback and
 
1069
             * our cells have not been allocated :-(
 
1070
             * The typed value must be stored, so allocate the cells array
 
1071
             * now.
 
1072
             */
 
1073
            xbaeCopyCells(mw);
 
1074
        /*
 
1075
         * Now we are free to store the value in the widget's cell array
 
1076
         */
 
1077
        if (mw->matrix.cells &&        /* It's OK to store the value */
 
1078
            strcmp(mw->matrix.cells[row][column], value))
 
1079
        {
 
1080
            /*
 
1081
             * I'm not particularly keen on this code - ie. checking twice
 
1082
             * for mw->matrix.cells but it seemed like the only way around
 
1083
             * the problem AL (Nov 5, 1995).
 
1084
             */
 
1085
            XtFree((XtPointer) mw->matrix.cells[row][column]);
 
1086
            mw->matrix.cells[row][column] = XtNewString(value);
 
1087
        }
 
1088
        else
 
1089
            return;
 
1090
            
 
1091
    }
 
1092
    /*
 
1093
     * Draw the cell.
 
1094
     */
 
1095
    if (xbaeIsCellVisible(mw, row, column))
 
1096
    {
 
1097
        xbaeClearCell(mw, row, column);
 
1098
        xbaeDrawCell(mw, row, column);
 
1099
    }
 
1100
 
 
1101
    /*
 
1102
     * If we are editing this cell, load the textField too if update_text set.
 
1103
     */
 
1104
    if (update_text && XtIsManaged(TextChild(mw)) &&
 
1105
        mw->matrix.current_row == row && mw->matrix.current_column == column)
 
1106
    {
 
1107
        String string;
 
1108
 
 
1109
        /* Remove the modify verify callback when the text field is set.
 
1110
           It thinks we are modifying the value - Motif thinks that
 
1111
           it knows best but we know better! */
 
1112
        XtRemoveCallback(TextChild(mw), XmNmodifyVerifyCallback,
 
1113
                         xbaeModifyVerifyCB, (XtPointer)mw);
 
1114
 
 
1115
        /*
 
1116
         * We need to get the value to put back into the textField if the
 
1117
         * application has a draw cell callback so that any reformatting will
 
1118
         * be displayed. -cg May 13, 1999.
 
1119
         */
 
1120
        if (mw->matrix.draw_cell_callback)
 
1121
        {
 
1122
            Pixmap pixmap, mask;
 
1123
            Pixel bg, fg;
 
1124
            int width, height, depth;
 
1125
 
 
1126
            xbaeGetDrawCellValue(mw, mw->matrix.current_row,
 
1127
                                 mw->matrix.current_column, &string,
 
1128
                                 &pixmap, &mask, &width, &height,
 
1129
                                 &bg, &fg, &depth);
 
1130
        }
 
1131
        else
 
1132
            string = value;
 
1133
 
 
1134
        if (string[0] == '\0')
 
1135
            XtVaSetValues(TextChild(mw),
 
1136
                          XmNvalue, string,
 
1137
                          NULL);
 
1138
        else
 
1139
            XmTextSetString(TextChild(mw), string);
 
1140
 
 
1141
        XtAddCallback(TextChild(mw), XmNmodifyVerifyCallback,
 
1142
                      xbaeModifyVerifyCB, (XtPointer)mw);
 
1143
    }
 
1144
}
 
1145
 
 
1146
static Boolean
 
1147
DoCommitEdit(mw, event)
 
1148
XbaeMatrixWidget mw;
 
1149
XEvent *event;
 
1150
{
 
1151
    String cell;
 
1152
 
 
1153
    if (!XtIsManaged(TextChild(mw)))
 
1154
        return True;
 
1155
 
 
1156
    /*
 
1157
     * Get the value the user entered in the textField (this is a copy)
 
1158
     */
 
1159
    cell = XmTextGetString(TextChild(mw));
 
1160
 
 
1161
    /*
 
1162
     * Call the leaveCellCallback to see if we can leave the current cell.
 
1163
     */
 
1164
    if (mw->matrix.leave_cell_callback)
 
1165
    {
 
1166
        XbaeMatrixLeaveCellCallbackStruct call_data;
 
1167
 
 
1168
        call_data.reason = XbaeLeaveCellReason;
 
1169
        call_data.event = event;
 
1170
        call_data.row = mw->matrix.current_row;
 
1171
        call_data.column = mw->matrix.current_column;
 
1172
        call_data.value = cell;
 
1173
        call_data.doit = True;
 
1174
 
 
1175
        XtCallCallbackList((Widget) mw, mw->matrix.leave_cell_callback,
 
1176
                           (XtPointer)&call_data);
 
1177
 
 
1178
        /*
 
1179
         * Application doesn't want to leave this cell. Make the cell visible
 
1180
         * and traverse to it so the user can see where they screwed up.
 
1181
         */
 
1182
        if (!call_data.doit)
 
1183
        {
 
1184
            xbaeMakeCellVisible(
 
1185
                mw, mw->matrix.current_row, mw->matrix.current_column);
 
1186
            XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
 
1187
            XtFree((XtPointer) cell);
 
1188
            return False;
 
1189
        }
 
1190
 
 
1191
        /*
 
1192
         * Use the applications value if it is different.
 
1193
         * If the application modified the string inplace, we will pick that
 
1194
         * up automatically.
 
1195
         */
 
1196
        if (call_data.value != cell)
 
1197
        {
 
1198
            XtFree((XtPointer) cell);
 
1199
            cell = call_data.value;
 
1200
        }
 
1201
    }
 
1202
 
 
1203
    /*
 
1204
     * Call the set_cell method to store the new value in the cell and redraw.
 
1205
     */
 
1206
    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.set_cell)
 
1207
        (mw, mw->matrix.current_row, mw->matrix.current_column, cell, True);
 
1208
 
 
1209
    XtFree((XtPointer) cell);
 
1210
 
 
1211
    return True;
 
1212
}
 
1213
 
 
1214
/*
 
1215
 * Position and size the scrollbars and clip widget for our new size.
 
1216
 */
 
1217
void
 
1218
xbaeResize(mw)
 
1219
XbaeMatrixWidget mw;
 
1220
{
 
1221
    int cell_width, cell_height, rows_visible;
 
1222
    Boolean has_horiz, has_vert;
 
1223
    Boolean scrollbar_top;
 
1224
    Boolean scrollbar_left;
 
1225
    int width = mw->core.width;
 
1226
    int height = mw->core.height;
 
1227
 
 
1228
    /*
 
1229
     * Full size of widget (no SBs needed) - may be very large
 
1230
     */
 
1231
    long int full_width = NON_FIXED_TOTAL_WIDTH(mw) + FIXED_COLUMN_WIDTH(mw) +
 
1232
        TRAILING_FIXED_COLUMN_WIDTH(mw) + ROW_LABEL_WIDTH(mw) +
 
1233
        2 * mw->manager.shadow_thickness;
 
1234
    long int full_height = CELL_TOTAL_HEIGHT(mw) + FIXED_ROW_HEIGHT(mw) +
 
1235
        TRAILING_FIXED_ROW_HEIGHT(mw) + COLUMN_LABEL_HEIGHT(mw) +
 
1236
        2 * mw->manager.shadow_thickness;
 
1237
 
 
1238
    /*
 
1239
     * Portion of cells which are visible in clip widget
 
1240
     */
 
1241
    int horiz_visible = NON_FIXED_TOTAL_WIDTH(mw) - HORIZ_ORIGIN(mw);
 
1242
    int vert_visible = CELL_TOTAL_HEIGHT(mw) -
 
1243
        VERT_ORIGIN(mw) * ROW_HEIGHT(mw);
 
1244
    
 
1245
    /*
 
1246
     * Check the location of the scrollbars
 
1247
     */
 
1248
    scrollbar_top = (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
1249
                     mw->matrix.scrollbar_placement == XmTOP_RIGHT);
 
1250
    scrollbar_left = (mw->matrix.scrollbar_placement == XmBOTTOM_LEFT ||
 
1251
                      mw->matrix.scrollbar_placement == XmTOP_LEFT);
 
1252
    /*
 
1253
     * If our horizontal scrollbar display policy is constant,
 
1254
     * then we always have the horizontal scrollbar. If it is
 
1255
     * none, then we never have it. Otherwise, check if it
 
1256
     * is needed: if we are wider than the matrix's width,
 
1257
     * then we don't need it; if we are smaller, we do.
 
1258
     */
 
1259
    if (mw->matrix.hsb_display_policy == XmDISPLAY_STATIC)
 
1260
        has_horiz = TRUE;
 
1261
    else if (mw->matrix.hsb_display_policy == XmDISPLAY_NONE)
 
1262
        has_horiz = FALSE;
 
1263
    else
 
1264
    {
 
1265
        if (width >= full_width)
 
1266
            has_horiz = False;
 
1267
        else
 
1268
            has_horiz = True;
 
1269
    }
 
1270
    if (has_horiz)
 
1271
        height -= HORIZ_SB_HEIGHT(mw);
 
1272
    
 
1273
    /*
 
1274
     * Same reasoning for the vertical scrollbar.
 
1275
     */
 
1276
    if (mw->matrix.vsb_display_policy == XmDISPLAY_STATIC)
 
1277
        has_vert = TRUE;
 
1278
    else if (mw->matrix.vsb_display_policy == XmDISPLAY_NONE)
 
1279
        has_vert = FALSE;
 
1280
    else
 
1281
    {
 
1282
        if (height >= full_height)
 
1283
            has_vert = False;
 
1284
        else
 
1285
            has_vert = True;
 
1286
    }
 
1287
 
 
1288
    /*
 
1289
     * If we have a vertical scrollbar, adjust the width and
 
1290
     * recheck if we need the horizontal scrollbar.
 
1291
     */
 
1292
    if (has_vert)
 
1293
    {
 
1294
        width -= VERT_SB_WIDTH(mw);
 
1295
        if ((XmDISPLAY_NONE != mw->matrix.hsb_display_policy) &&
 
1296
            (! has_horiz) && (width < full_width))
 
1297
        {
 
1298
            has_horiz = True;
 
1299
            height -= HORIZ_SB_HEIGHT(mw);
 
1300
        }
 
1301
    }
 
1302
 
 
1303
    /*
 
1304
     * If widget is smaller than full size, move/resize the scrollbar and
 
1305
     * set sliderSize, also if cell_width/cell_height is greater than
 
1306
     * the amount of cell area visible, then we need to drag the cells
 
1307
     * back into the visible part of the clip widget and set the
 
1308
     * scrollbar value.
 
1309
     *
 
1310
     * Otherwise, the widget is larger than full size, so set
 
1311
     * cell_width/cell_height to size of cells and set origin to 0
 
1312
     * to force full cell area to be displayed
 
1313
     *
 
1314
     * We also need to move the textField correspondingly
 
1315
     */
 
1316
 
 
1317
    /*
 
1318
     * We were resized smaller than our max width.
 
1319
     */
 
1320
    if (width < full_width)
 
1321
    {
 
1322
        int HSBwidth;
 
1323
        
 
1324
        /*
 
1325
         * Calculate the width of the non-fixed visible cells.
 
1326
         */
 
1327
        cell_width = mw->core.width - (FIXED_COLUMN_WIDTH(mw) +
 
1328
                                       TRAILING_FIXED_COLUMN_WIDTH(mw) +
 
1329
                                       ROW_LABEL_WIDTH(mw) +
 
1330
                                       2 * mw->manager.shadow_thickness);
 
1331
 
 
1332
        /*
 
1333
         * Subtract the VSB if we have one.
 
1334
         */
 
1335
        if (has_vert)
 
1336
            cell_width -= VERT_SB_WIDTH(mw);
 
1337
 
 
1338
        if (cell_width <= 0)
 
1339
            cell_width = 1;
 
1340
            
 
1341
        /*
 
1342
         * Adjust for shadow thickness.
 
1343
         */
 
1344
        HSBwidth = cell_width + mw->manager.shadow_thickness *
 
1345
            (mw->matrix.fixed_columns ||
 
1346
             mw->matrix.trailing_fixed_columns ?
 
1347
             (mw->matrix.fixed_columns &&
 
1348
              mw->matrix.trailing_fixed_columns ? 0 : 1) : 2);
 
1349
        
 
1350
        /*
 
1351
         * If the window is not full height, then place the HSB at the edge
 
1352
         * of the window.  Is the window is larger than full height, then
 
1353
         * place the HSB immediately below the cell region.
 
1354
         */
 
1355
        XtConfigureWidget(
 
1356
            HorizScrollChild(mw),
 
1357
            HSB_X_POSITION(mw),
 
1358
            (scrollbar_top && has_horiz) ? (Position) 0 :
 
1359
            ((height < full_height) || mw->matrix.fill ?
 
1360
             (Position) (mw->core.height -
 
1361
                         (HorizScrollChild(mw)->core.height +
 
1362
                          2 * HorizScrollChild(mw)->core.border_width)) :
 
1363
             (Position) (full_height + mw->matrix.space)), HSBwidth,
 
1364
            HorizScrollChild(mw)->core.height,
 
1365
            HorizScrollChild(mw)->core.border_width);
 
1366
 
 
1367
        /*
 
1368
         * If the cells are scrolled off to the left, then drag them
 
1369
         * back onto the screen.
 
1370
         */
 
1371
        if (cell_width > horiz_visible)
 
1372
        {
 
1373
            if ((HORIZ_ORIGIN(mw) -= (cell_width - horiz_visible)) < 0)
 
1374
            {
 
1375
                HORIZ_ORIGIN(mw) = 0;
 
1376
                mw->matrix.left_column = 0;
 
1377
            }
 
1378
 
 
1379
            if (XtIsManaged(TextChild(mw)))
 
1380
                XtMoveWidget(TextChild(mw),
 
1381
                             TextChild(mw)->core.x +
 
1382
                             (cell_width - horiz_visible),
 
1383
                             TextChild(mw)->core.y);
 
1384
        }
 
1385
 
 
1386
        /*
 
1387
         * Setup the HSB to reflect our new size.
 
1388
         */
 
1389
        XtVaSetValues(HorizScrollChild(mw),
 
1390
                      XmNpageIncrement, cell_width,
 
1391
                      XmNsliderSize, cell_width,
 
1392
                      XmNvalue, HORIZ_ORIGIN(mw),
 
1393
                      NULL);
 
1394
    }
 
1395
 
 
1396
    /*
 
1397
     * We were resized larger than the our max width.  Drag the cells back
 
1398
     * onto the screen if they were scrolled off to the left.
 
1399
     */
 
1400
    else
 
1401
    {
 
1402
        if (XtIsManaged(TextChild(mw)))
 
1403
            XtMoveWidget(TextChild(mw),
 
1404
                         TextChild(mw)->core.x + HORIZ_ORIGIN(mw),
 
1405
                         TextChild(mw)->core.y);
 
1406
 
 
1407
        cell_width = NON_FIXED_TOTAL_WIDTH(mw);
 
1408
        if (cell_width <= 0) cell_width = 1;
 
1409
        
 
1410
        HORIZ_ORIGIN(mw) = 0;
 
1411
        mw->matrix.left_column = 0;
 
1412
 
 
1413
        if (has_horiz)
 
1414
        {
 
1415
            XtConfigureWidget(
 
1416
                HorizScrollChild(mw),
 
1417
                HSB_X_POSITION(mw),
 
1418
                (scrollbar_top && has_horiz) ? (Position) 0 :
 
1419
                ((height < full_height) || mw->matrix.fill ?
 
1420
                 (Position) (mw->core.height -
 
1421
                             (HorizScrollChild(mw)->core.height +
 
1422
                              2 * HorizScrollChild(mw)->core.border_width)) :
 
1423
                 (Position) (full_height + mw->matrix.space)),
 
1424
                HSB_WIDTH(mw),
 
1425
                HorizScrollChild(mw)->core.height,
 
1426
                HorizScrollChild(mw)->core.border_width);
 
1427
 
 
1428
            XtVaSetValues(HorizScrollChild(mw),
 
1429
                          XmNpageIncrement, cell_width,
 
1430
                          XmNsliderSize, cell_width,
 
1431
                          XmNvalue, HORIZ_ORIGIN(mw),
 
1432
                          NULL);
 
1433
        }
 
1434
    }
 
1435
 
 
1436
    /*
 
1437
     * We were resized smaller than our max height.
 
1438
     */
 
1439
    if (height < full_height)
 
1440
    {
 
1441
        int VSBheight;
 
1442
 
 
1443
        /*
 
1444
         * Calculate the height of the non-fixed visible cells.
 
1445
         */
 
1446
        cell_height = mw->core.height -
 
1447
            (FIXED_ROW_HEIGHT(mw) +  TRAILING_FIXED_ROW_HEIGHT(mw) +
 
1448
             COLUMN_LABEL_HEIGHT(mw) + 2 * mw->manager.shadow_thickness);
 
1449
 
 
1450
        /*
 
1451
         * Subtract the HSB if we have one.
 
1452
         */
 
1453
        if (has_horiz)
 
1454
            cell_height -= HORIZ_SB_HEIGHT(mw);
 
1455
 
 
1456
        if (cell_height <= 0)
 
1457
            cell_height = 1;
 
1458
 
 
1459
        /*
 
1460
         * Adjust for shadow thickness.
 
1461
         */
 
1462
        if (TRAILING_FIXED_ROW_HEIGHT(mw) > 0)
 
1463
            VSBheight = (cell_height / ROW_HEIGHT(mw)) * ROW_HEIGHT(mw) +
 
1464
                (mw->matrix.fixed_rows ? 0 : mw->manager.shadow_thickness);
 
1465
        else
 
1466
            VSBheight = cell_height +
 
1467
               ((mw->matrix.fixed_rows ? 1 : 2) *
 
1468
                mw->manager.shadow_thickness);
 
1469
 
 
1470
        /*
 
1471
         * If the window is not full width, then place the VSB at the edge
 
1472
         * of the window.  Is the window is larger than full width, then
 
1473
         * place the VSB immediately to the right of the cell region.
 
1474
         */
 
1475
        XtConfigureWidget(
 
1476
            VertScrollChild(mw),
 
1477
            (scrollbar_left && has_vert) ? (Position) 0 :
 
1478
            ((width < full_width) || mw->matrix.fill ?
 
1479
             (Position) (mw->core.width -
 
1480
                         (VertScrollChild(mw)->core.width + 2 *
 
1481
                          VertScrollChild(mw)->core.border_width)) :
 
1482
             (Position) full_width + mw->matrix.space),
 
1483
            VSB_Y_POSITION(mw), 
 
1484
            VertScrollChild(mw)->core.width, VSBheight > 0 ? VSBheight : 1,
 
1485
            VertScrollChild(mw)->core.border_width);
 
1486
        /*
 
1487
         * If the cells are scrolled off the top, then drag them
 
1488
         * back onto the screen.
 
1489
         */
 
1490
        if (cell_height > vert_visible)
 
1491
        {
 
1492
            int rows = (cell_height - vert_visible) / ROW_HEIGHT(mw);
 
1493
 
 
1494
            VERT_ORIGIN(mw) -= rows;
 
1495
 
 
1496
            if (XtIsManaged(TextChild(mw)))
 
1497
                XtMoveWidget(TextChild(mw),
 
1498
                             TextChild(mw)->core.x,
 
1499
                             TextChild(mw)->core.y + rows * ROW_HEIGHT(mw));
 
1500
        }
 
1501
 
 
1502
        /*
 
1503
         * Setup the VSB to reflect our new size.
 
1504
         */
 
1505
        rows_visible = cell_height / ROW_HEIGHT(mw);
 
1506
        XtVaSetValues(VertScrollChild(mw),
 
1507
                      XmNpageIncrement, rows_visible <= 0 ? 1 : rows_visible,
 
1508
                      XmNsliderSize, rows_visible <= 0 ? 1 : rows_visible,
 
1509
                      XmNvalue, VERT_ORIGIN(mw),
 
1510
                      NULL);
 
1511
    }
 
1512
 
 
1513
    /*
 
1514
     * We were resized larger than the our max height.        Drag the cells back
 
1515
     * onto the screen if they were scrolled off the top.
 
1516
     */
 
1517
    else
 
1518
    {
 
1519
        if (XtIsManaged(TextChild(mw)))
 
1520
            XtMoveWidget(TextChild(mw),
 
1521
                         TextChild(mw)->core.x,
 
1522
                         TextChild(mw)->core.y +
 
1523
                         VERT_ORIGIN(mw) * ROW_HEIGHT(mw));
 
1524
 
 
1525
        cell_height = CELL_TOTAL_HEIGHT(mw);
 
1526
 
 
1527
        if (cell_height <= 0)
 
1528
            cell_height = 1;
 
1529
        
 
1530
        rows_visible = mw->matrix.rows - mw->matrix.fixed_rows -
 
1531
            mw->matrix.trailing_fixed_rows;
 
1532
        VERT_ORIGIN(mw) = 0;
 
1533
 
 
1534
        if (has_vert)
 
1535
        {
 
1536
            XtConfigureWidget(
 
1537
                VertScrollChild(mw),
 
1538
                (scrollbar_left && has_vert) ? (Position) 0 :
 
1539
                ((width < full_width) || mw->matrix.fill ?
 
1540
                 (Position)(mw->core.width -
 
1541
                            (VertScrollChild(mw)->core.width +
 
1542
                             2 * VertScrollChild(mw)->core.border_width)) :
 
1543
                 (Position)full_width + mw->matrix.space),
 
1544
                VSB_Y_POSITION(mw),
 
1545
                VertScrollChild(mw)->core.width,
 
1546
                VSB_HEIGHT(mw),
 
1547
                VertScrollChild(mw)->core.border_width);
 
1548
            
 
1549
            XtVaSetValues(
 
1550
                VertScrollChild(mw),
 
1551
                XmNpageIncrement, rows_visible <= 0 ? 1 : rows_visible,
 
1552
                XmNsliderSize, rows_visible <= 0 ? 1 : rows_visible,
 
1553
                XmNvalue, VERT_ORIGIN(mw),
 
1554
                NULL);
 
1555
        }
 
1556
    }
 
1557
 
 
1558
    /*
 
1559
     * Map/unmap scrollbars based on flags set above
 
1560
     */
 
1561
    if (has_horiz && !HorizScrollChild(mw)->core.managed)
 
1562
    {
 
1563
        XtManageChild(HorizScrollChild(mw));
 
1564
        /*
 
1565
         * Generate an expose over the horizontal scrollbar to ensure it gets
 
1566
         * drawn properly
 
1567
         */
 
1568
        if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
1569
            XClearArea(XtDisplay(mw), XtWindow(mw), 0, HORIZ_SB_POSITION(mw),
 
1570
                       mw->core.width, scrollbar_top ? HORIZ_SB_HEIGHT(mw) :
 
1571
                       mw->core.height - HORIZ_SB_POSITION(mw), True);
 
1572
        /*
 
1573
         * Take into account the little bit at the bottom of the screen
 
1574
         * if the scrollbar is in the top location.
 
1575
         */
 
1576
        if (scrollbar_top && XtIsRealized((Widget)mw))
 
1577
            XClearArea(XtDisplay(mw), XtWindow(mw), 0,
 
1578
                       TRAILING_FIXED_ROW_LABEL_OFFSET(mw), mw->core.width,
 
1579
                       mw->core.height - TRAILING_FIXED_ROW_LABEL_OFFSET(mw),
 
1580
                       True);
 
1581
    }
 
1582
    else if (!has_horiz && HorizScrollChild(mw)->core.managed)
 
1583
    {
 
1584
        /*
 
1585
         * Generate an expose over the horizontal scrollbar to ensure it gets
 
1586
         * drawn properly
 
1587
         */
 
1588
        XtUnmanageChild(HorizScrollChild(mw));
 
1589
        if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
1590
            XClearArea(XtDisplay(mw), XtWindow(mw), 0, HORIZ_SB_POSITION(mw),
 
1591
                       mw->core.width, scrollbar_top ? HORIZ_SB_HEIGHT(mw) :
 
1592
                       mw->core.height - HORIZ_SB_POSITION(mw), True);
 
1593
        /*
 
1594
         * Take into account the little bit at the bottom of the screen
 
1595
         * if the scrollbar is in the top location.
 
1596
         */
 
1597
        if (scrollbar_top && XtIsRealized((Widget)mw))
 
1598
            XClearArea(XtDisplay(mw), XtWindow(mw), 0,
 
1599
                       TRAILING_FIXED_ROW_LABEL_OFFSET(mw), mw->core.width,
 
1600
                       mw->core.height - TRAILING_FIXED_ROW_LABEL_OFFSET(mw),
 
1601
                       True);
 
1602
 
 
1603
    }
 
1604
    if (has_vert && !VertScrollChild(mw)->core.managed)
 
1605
    {
 
1606
        /*
 
1607
         * Generate an expose over the vertical scrollbar region to ensure
 
1608
         * it gets drawn properly
 
1609
         */
 
1610
        XtManageChild(VertScrollChild(mw));
 
1611
        if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
1612
            XClearArea(XtDisplay(mw), XtWindow(mw), VERT_SB_POSITION(mw), 0,
 
1613
                       VERT_SB_POSITION(mw) + VERT_SB_WIDTH(mw),
 
1614
                       mw->core.height, True);
 
1615
        /*
 
1616
         * This one's a bit trickier!  If the scrollbar appears on the
 
1617
         * left hand side then it's possible to have some area *under* the
 
1618
         * matrix that isn't redrawn properly.  This will be most
 
1619
         * noticeable at the top and bottom of the matrix.  As the matrix
 
1620
         * will move to the right by it's width, this width is the area
 
1621
         * that needs to be redrawn.
 
1622
         */
 
1623
        if (scrollbar_left && XtIsRealized((Widget)mw))
 
1624
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
1625
                       FIXED_COLUMN_LABEL_OFFSET(mw) -
 
1626
                       TRAILING_FIXED_COLUMN_WIDTH(mw), 0,
 
1627
                       TRAILING_FIXED_COLUMN_WIDTH(mw) + VERT_SB_WIDTH(mw),
 
1628
                       mw->core.height, True);
 
1629
        /*
 
1630
         * Also clear the area below the matrix as it can get a little
 
1631
         * confused too
 
1632
         */
 
1633
        if(XtIsRealized((Widget)mw))
 
1634
            XClearArea(XtDisplay(mw), XtWindow(mw), 0,
 
1635
                       TRAILING_FIXED_ROW_LABEL_OFFSET(mw), mw->core.width,
 
1636
                       mw->core.height - TRAILING_FIXED_ROW_LABEL_OFFSET(mw),
 
1637
                       True);
 
1638
    }
 
1639
    else if (!has_vert && VertScrollChild(mw)->core.managed)
 
1640
    {
 
1641
        /*
 
1642
         * Generate an expose over the vertical scrollbar region to ensure
 
1643
         * it gets drawn properly
 
1644
         */
 
1645
        XtUnmanageChild(VertScrollChild(mw));
 
1646
        if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
1647
            XClearArea(XtDisplay(mw), XtWindow(mw), VERT_SB_POSITION(mw), 0,
 
1648
                       VERT_SB_POSITION(mw) + VERT_SB_WIDTH(mw),
 
1649
                       mw->core.height, True);
 
1650
        /*
 
1651
         * Similar to the case above but we need to clear the are to the
 
1652
         * right of the matrix and only the width of the scrollbar itself
 
1653
         */
 
1654
        if (scrollbar_left && XtIsRealized((Widget)mw))
 
1655
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
1656
                       TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw) +
 
1657
                       TRAILING_FIXED_COLUMN_WIDTH(mw), 0,
 
1658
                       VERT_SB_WIDTH(mw) + mw->manager.shadow_thickness,
 
1659
                       mw->core.height, True);
 
1660
        /*
 
1661
         * And also clear the area below the matrix as it can get a little
 
1662
         * confused too
 
1663
         */
 
1664
        if (XtIsRealized((Widget)mw))
 
1665
            XClearArea(XtDisplay(mw), XtWindow(mw), 0,
 
1666
                       TRAILING_FIXED_ROW_LABEL_OFFSET(mw), mw->core.width,
 
1667
                       mw->core.height - TRAILING_FIXED_ROW_LABEL_OFFSET(mw),
 
1668
                       True);
 
1669
    }
 
1670
    /*
 
1671
     * Now that we have cell_width & cell_height,
 
1672
     * make the clip widget this size.        Height is truncated to the
 
1673
     * nearest row.
 
1674
     */
 
1675
    XtConfigureWidget(ClipChild(mw),
 
1676
                      FIXED_COLUMN_LABEL_OFFSET(mw),
 
1677
                      FIXED_ROW_LABEL_OFFSET(mw),
 
1678
                      cell_width, cell_height, 0);
 
1679
 
 
1680
    /* Resize all the other clips */
 
1681
    if (mw->matrix.fixed_columns <= 0)
 
1682
    {
 
1683
        if (XtIsManaged(LeftClip(mw)))
 
1684
            XtUnmanageChild(LeftClip(mw));
 
1685
    }
 
1686
    else
 
1687
    {
 
1688
        XtConfigureWidget(LeftClip(mw),
 
1689
                          COLUMN_LABEL_OFFSET(mw), FIXED_ROW_LABEL_OFFSET(mw),
 
1690
                          FIXED_COLUMN_WIDTH(mw), cell_height, 0);
 
1691
        if (!XtIsManaged(LeftClip(mw)))
 
1692
            XtManageChild(LeftClip(mw));
 
1693
    }
 
1694
    if (mw->matrix.trailing_fixed_columns <= 0)
 
1695
    {
 
1696
               if (XtIsManaged(RightClip(mw)))
 
1697
            XtUnmanageChild(RightClip(mw));
 
1698
    }
 
1699
    else
 
1700
    {
 
1701
        XtConfigureWidget(RightClip(mw),
 
1702
                          cell_width + FIXED_COLUMN_LABEL_OFFSET(mw),
 
1703
                          FIXED_ROW_LABEL_OFFSET(mw),
 
1704
                          TRAILING_FIXED_COLUMN_WIDTH(mw),
 
1705
                          cell_height, 0);
 
1706
        if (!XtIsManaged(RightClip(mw)))
 
1707
            XtManageChild(RightClip(mw));
 
1708
    }
 
1709
    if (mw->matrix.fixed_rows <= 0)
 
1710
    {
 
1711
               if (XtIsManaged(TopClip(mw)))
 
1712
            XtUnmanageChild(TopClip(mw));
 
1713
    }
 
1714
    else
 
1715
    {
 
1716
        XtConfigureWidget(TopClip(mw),
 
1717
                          FIXED_COLUMN_LABEL_OFFSET(mw), ROW_LABEL_OFFSET(mw),
 
1718
                          cell_width, FIXED_ROW_HEIGHT(mw), 0);
 
1719
        if (!XtIsManaged(TopClip(mw)))
 
1720
            XtManageChild(TopClip(mw));
 
1721
    }
 
1722
    if (mw->matrix.trailing_fixed_rows <= 0)
 
1723
    {
 
1724
               if (XtIsManaged(BottomClip(mw)))
 
1725
            XtUnmanageChild(BottomClip(mw));
 
1726
    }
 
1727
    else
 
1728
    {
 
1729
        XtConfigureWidget(BottomClip(mw),
 
1730
                          FIXED_COLUMN_LABEL_OFFSET(mw),
 
1731
                          TRAILING_FIXED_ROW_LABEL_OFFSET(mw),
 
1732
                          cell_width, TRAILING_FIXED_ROW_HEIGHT(mw), 0);
 
1733
        if (!XtIsManaged(BottomClip(mw)))
 
1734
            XtManageChild(BottomClip(mw));
 
1735
    }
 
1736
 
 
1737
    /*
 
1738
     * The text field needs to be moved manually as we don't have
 
1739
     * the convenience of a clip widget to do it for us.
 
1740
     */
 
1741
    if (mw->matrix.current_column >= TRAILING_HORIZ_ORIGIN(mw) &&
 
1742
        mw->matrix.current_parent == (Widget)mw &&
 
1743
        XtIsManaged(TextChild(mw)))
 
1744
        XtMoveWidget(TextChild(mw), RightClip(mw)->core.x +
 
1745
                     mw->matrix.cell_shadow_thickness, TextChild(mw)->core.y);
 
1746
    /*
 
1747
     * Save the non-truncated height.  We need this so we can draw
 
1748
     * the shadow correctly.
 
1749
     */
 
1750
    mw->matrix.cell_visible_height = cell_height;
 
1751
 
 
1752
    /*
 
1753
     * Set the clip_mask in our clipping GCs.  This function relies on
 
1754
     * the Clip widget being the correct size (above).
 
1755
     */
 
1756
    if (XtIsRealized((Widget)mw))
 
1757
        xbaeSetClipMask(mw, CLIP_NONE);
 
1758
 
 
1759
    if (mw->matrix.resize_callback != NULL)
 
1760
    {
 
1761
        XbaeMatrixResizeCallbackStruct call_data;
 
1762
 
 
1763
        call_data.reason = XbaeResizeReason;
 
1764
        call_data.event = (XEvent *)NULL;
 
1765
        call_data.row = mw->matrix.rows;
 
1766
        call_data.column = mw->matrix.columns;
 
1767
        call_data.width  = mw->core.width;
 
1768
        call_data.height = mw->core.height;
 
1769
        XtCallCallbackList ((Widget)mw, mw->matrix.resize_callback,
 
1770
                            (XtPointer) &call_data);
 
1771
    }
 
1772
}
 
1773
 
 
1774
/*
 
1775
 * This is the modifyVerifyCallback we added to textField. We need to
 
1776
 * call Matrix's modifyVerifyCallback list with the textField info
 
1777
 * and the row/col that is changing.
 
1778
 */
 
1779
/* ARGSUSED */
 
1780
void
 
1781
xbaeModifyVerifyCB(w, client, call)
 
1782
Widget w;
 
1783
XtPointer client;
 
1784
XtPointer call;
 
1785
{
 
1786
    XbaeMatrixWidget mw = (XbaeMatrixWidget)client;
 
1787
    XmTextVerifyCallbackStruct *verify = (XmTextVerifyCallbackStruct *)call;
 
1788
    XbaeMatrixModifyVerifyCallbackStruct call_data;
 
1789
 
 
1790
    if (!mw->matrix.modify_verify_callback)
 
1791
        return;
 
1792
 
 
1793
    call_data.reason = XbaeModifyVerifyReason;
 
1794
    call_data.row = mw->matrix.current_row;
 
1795
    call_data.column = mw->matrix.current_column;
 
1796
    call_data.event = (XEvent *)NULL;
 
1797
    call_data.verify = verify;
 
1798
 
 
1799
    call_data.prev_text = ((XmTextRec*)w)->text.value;
 
1800
 
 
1801
    XtCallCallbackList((Widget) mw, mw->matrix.modify_verify_callback,
 
1802
                       (XtPointer) & call_data);
 
1803
}
 
1804
 
 
1805
 
 
1806
/*
 
1807
 * Matrix edit_cell method
 
1808
 */
 
1809
void
 
1810
xbaeEditCell(mw, event, row, column, params, nparams)
 
1811
XbaeMatrixWidget mw;
 
1812
XEvent *event;
 
1813
int row;
 
1814
int column;
 
1815
String *params;
 
1816
Cardinal nparams;
 
1817
{
 
1818
    XbaeMatrixEnterCellCallbackStruct call_data;
 
1819
    Window newWin, oldWin;
 
1820
    int x, y;
 
1821
    Pixel fgcolor, bgcolor;
 
1822
    Boolean alt;
 
1823
    String string;
 
1824
    Widget oldWidget, newWidget;
 
1825
#if CELL_WIDGETS
 
1826
    Widget userWidget;
 
1827
#endif
 
1828
 
 
1829
    if (row >= mw->matrix.rows || row < 0 ||
 
1830
        column >= mw->matrix.columns || column < 0)
 
1831
    {
 
1832
        /*
 
1833
         * If we have zero rows or columns, there are no cells
 
1834
         * available on which to place the text field so just return
 
1835
         */
 
1836
        if (mw->matrix.rows == 0 || mw->matrix.columns == 0)
 
1837
            return;
 
1838
 
 
1839
        XtAppWarningMsg(
 
1840
            XtWidgetToApplicationContext((Widget) mw),
 
1841
            "editCell", "badIndex", "XbaeMatrix",
 
1842
            "XbaeMatrix: Row or column out of bounds for EditCell.",
 
1843
            NULL, 0);
 
1844
        return;
 
1845
    }
 
1846
 
 
1847
    /*
 
1848
     * Attempt to commit the edit in the current cell. Return if we fail.
 
1849
     */
 
1850
    if (!DoCommitEdit(mw, event))
 
1851
        return;
 
1852
 
 
1853
    /*
 
1854
     * Scroll the cell onto the screen
 
1855
     */
 
1856
    xbaeMakeCellVisible(mw, row, column);
 
1857
 
 
1858
    /*
 
1859
     * Fixed cells may not be editable.
 
1860
     */
 
1861
    if (IS_FIXED(mw, row, column) && !mw->matrix.traverse_fixed)
 
1862
        return;
 
1863
 
 
1864
    /* get the window of the new cell position */
 
1865
    newWin = xbaeGetCellWindow(mw, &newWidget, row, column);
 
1866
 
 
1867
    /*
 
1868
     * If we have an enterCellCallback, call it to see if the cell is
 
1869
     * editable.
 
1870
     */
 
1871
    call_data.map = True;
 
1872
    call_data.doit = True;
 
1873
    call_data.position = -1;
 
1874
    call_data.pattern = NULL;
 
1875
    
 
1876
    XtVaGetValues(TextChild(mw),
 
1877
                  XmNoverwriteMode, &call_data.overwrite_mode,
 
1878
                  XmNautoFill, &call_data.auto_fill,
 
1879
                  XmNconvertCase, &call_data.convert_case,
 
1880
                  NULL);
 
1881
 
 
1882
    call_data.select_text = False;
 
1883
 
 
1884
    if (mw->matrix.enter_cell_callback)
 
1885
    {
 
1886
        call_data.reason = XbaeEnterCellReason;
 
1887
        call_data.event = event;
 
1888
        call_data.row = row;
 
1889
        call_data.column = column;
 
1890
        call_data.map = True;
 
1891
        call_data.num_params = nparams;
 
1892
        call_data.params = params;
 
1893
 
 
1894
        XtCallCallbackList((Widget) mw, mw->matrix.enter_cell_callback,
 
1895
                           (XtPointer) & call_data);
 
1896
    }
 
1897
 
 
1898
    /* Get the window of the current cell so we can see if we need to move. */
 
1899
    oldWin = xbaeGetCellWindow(mw, &oldWidget, mw->matrix.current_row,
 
1900
                               mw->matrix.current_column);
 
1901
    mw->matrix.current_row = row;
 
1902
    mw->matrix.current_column = column;
 
1903
 
 
1904
    /*
 
1905
     * Unmap the textField to avoid flashing.
 
1906
     */
 
1907
    if (XtIsManaged(TextChild(mw)) && XtIsRealized(TextChild(mw)))
 
1908
        XtUnmapWidget(TextChild(mw));
 
1909
 
 
1910
    /*
 
1911
     * Convert the row/column to an xy position and move the textField
 
1912
     * to this position. (the xy position will be relative to the Clip
 
1913
     * widget if a non-fixed cells is being edited, relative to Matrix if
 
1914
     * a totally fixed cell is being edited (one of the corners), or one of
 
1915
     * the other clips otherwise.
 
1916
     */
 
1917
    xbaeRowColToXY(mw, row, column, &x, &y);
 
1918
 
 
1919
#if CELL_WIDGETS
 
1920
    userWidget = mw->matrix.cell_widgets[row][column];
 
1921
    
 
1922
    if (!userWidget)
 
1923
    {
 
1924
#endif
 
1925
        /*
 
1926
         * We actually don't check for traverse_fixed here even though
 
1927
         * it looks like it might be needed. The reason is that we may
 
1928
         * need to reparent back onto the clip in case we were on the
 
1929
         * fixed area and then traverse_fixed has been set to False
 
1930
         * via SetValues. Doing this on the next traversal is probably
 
1931
         * preferable to magically warping the textField off the
 
1932
         * matrix on to the clip when traverseFixedCells changes. It
 
1933
         * also allows the user to finish editing the existing cell,
 
1934
         * but won't allow continued traversal on the fixed area. -CG
 
1935
         */
 
1936
        
 
1937
        /*
 
1938
         * The old check (oldWin != newWin) as criteria to reparent
 
1939
         * wasn't quite correct in the case of editable fixed columns;
 
1940
         * In this case the first time the cell was edited 'oldWin'
 
1941
         * and 'newWin' where both the left clip widget (which was correct)
 
1942
         * but the 'current_parent' was still the initial parent set in the
 
1943
         * 'Reslize' function (I think the clip widget).
 
1944
         * The result was that the text field was moved relative to wrong
 
1945
         * window and therefore appearing at a complete different position;
 
1946
         * I check now as additional criteria if the 'current_parent' widget
 
1947
         * is the same as 'newWidget'.
 
1948
         * It should fix the my problem without breaking anything else.
 
1949
         * The check (oldWin && newWin) for apps which call on startup
 
1950
         * editCell() without a realized widget tree. Without this check
 
1951
         * X errors would be the result.
 
1952
         *
 
1953
         * donato petrino, 1997/11/
 
1954
         */
 
1955
        if ((oldWin != newWin ||
 
1956
             mw->matrix.current_parent != newWidget) &&
 
1957
            (oldWin && newWin))
 
1958
        {
 
1959
            XReparentWindow(XtDisplay(mw), XtWindow(TextChild(mw)), newWin,
 
1960
                            x + mw->matrix.cell_shadow_thickness,
 
1961
                            y + mw->matrix.cell_shadow_thickness);
 
1962
            mw->matrix.current_parent = newWidget;
 
1963
            /*
 
1964
             * Widget still needs moving, because all we have done
 
1965
             * above is redraw it's window. The widget itself doesn't
 
1966
             * know where it is and must be repositioned relative to
 
1967
             * it's (possibly new) window.
 
1968
             */
 
1969
        }
 
1970
        XtMoveWidget(TextChild(mw), 
 
1971
                     x + mw->matrix.cell_shadow_thickness,
 
1972
                     y + mw->matrix.cell_shadow_thickness);
 
1973
#if CELL_WIDGETS
 
1974
    }
 
1975
    else
 
1976
    {
 
1977
        /*
 
1978
         * A user defined widget does not take into account the
 
1979
         * cell_highlight_thickness, so we must do it!
 
1980
         */         
 
1981
        XtMoveWidget(userWidget,
 
1982
                     x + mw->matrix.cell_shadow_thickness +
 
1983
                     mw->matrix.cell_highlight_thickness,
 
1984
                     y + mw->matrix.cell_shadow_thickness +
 
1985
                     mw->matrix.cell_highlight_thickness);
 
1986
        /* Force editing to be disabled */
 
1987
        call_data.doit = False;
 
1988
    }
 
1989
#endif
 
1990
    /*
 
1991
     * Compute the foreground and background of the text widget
 
1992
     */
 
1993
    alt = mw->matrix.alt_row_count ?
 
1994
        (row / mw->matrix.alt_row_count) % 2 : False;
 
1995
 
 
1996
    if (mw->matrix.colors)
 
1997
        fgcolor = mw->matrix.colors[row][column];
 
1998
    else
 
1999
        fgcolor = mw->manager.foreground;
 
2000
 
 
2001
    if (mw->matrix.text_background != mw->core.background_pixel)
 
2002
        bgcolor = mw->matrix.text_background;
 
2003
    else if (mw->matrix.cell_background && 
 
2004
             mw->matrix.cell_background[row][column] != mw->core.background_pixel)
 
2005
        bgcolor = mw->matrix.cell_background[row][column];
 
2006
    else
 
2007
    {
 
2008
        if (alt)
 
2009
            bgcolor = mw->matrix.odd_row_background;
 
2010
        else
 
2011
            bgcolor = mw->matrix.even_row_background;
 
2012
    }
 
2013
    /*
 
2014
     * If we're doing a drawCell, go ask the app what to put there.
 
2015
     */
 
2016
    if (mw->matrix.draw_cell_callback)
 
2017
    {
 
2018
        Pixmap pixmap;
 
2019
        Pixmap mask;
 
2020
        int width, height, depth;
 
2021
        Pixel orig_bg, orig_fg;
 
2022
        
 
2023
        orig_bg = bgcolor;
 
2024
        orig_fg = fgcolor;
 
2025
        if (xbaeGetDrawCellValue(
 
2026
            mw, row, column, &string, &pixmap, &mask, &width, &height,
 
2027
            &bgcolor, &fgcolor, &depth) == XbaePixmap)
 
2028
        {
 
2029
            /*
 
2030
             * If we're showing a pixmap, we don't want the TextField.
 
2031
             */
 
2032
            return;
 
2033
        }
 
2034
        /*
 
2035
         * If we reverse selected then we would have reversed things we
 
2036
         * shouldn't have. We can detect this by checking bgcolor against
 
2037
         * orig_fg and fgcolor against orig_bg and setting the colors back
 
2038
         * to their non-selected values (as with an ordinary selected when
 
2039
         * it is being edited). -cg 23/7/99
 
2040
         */
 
2041
        if (mw->matrix.reverse_select && mw->matrix.selected_cells &&
 
2042
            mw->matrix.selected_cells[row][column])
 
2043
        {
 
2044
            int new_fg = fgcolor;
 
2045
            int new_bg = bgcolor;
 
2046
 
 
2047
            /* callback changed bg */
 
2048
            if (orig_fg != fgcolor)
 
2049
                new_bg = fgcolor;
 
2050
            else        /* reset it */
 
2051
                new_bg = orig_bg;
 
2052
            /* callback changed fg */
 
2053
            if (orig_bg != bgcolor)
 
2054
                new_fg = bgcolor;
 
2055
            else        /* reset it */
 
2056
                new_fg = orig_fg;
 
2057
            bgcolor = new_bg;
 
2058
            fgcolor = new_fg;
 
2059
        }
 
2060
    }
 
2061
    else
 
2062
        string = mw->matrix.cells ? mw->matrix.cells[row][column] : "";
 
2063
 
 
2064
 
 
2065
    /*
 
2066
     * Setup the textField for the new cell. If the modifyVerify CB
 
2067
     * rejects the new value, then it is the applications fault for
 
2068
     * loading the cell with a bad value to begin with.
 
2069
     */
 
2070
#if CELL_WIDGETS
 
2071
    if (!mw->matrix.cell_widgets[row][column])
 
2072
    {
 
2073
#endif
 
2074
        /*
 
2075
         * Remove the modify verify callback when the text field is set.
 
2076
         * It thinks we are modifying the value but Motif thinks that
 
2077
         * it knows best and we know better!
 
2078
         */
 
2079
        XtRemoveCallback(TextChild(mw), XmNmodifyVerifyCallback,
 
2080
                         xbaeModifyVerifyCB, (XtPointer)mw);
 
2081
        
 
2082
        XtVaSetValues(TextChild(mw),
 
2083
                      XmNwidth, COLUMN_WIDTH(mw, column) -
 
2084
                      mw->matrix.cell_shadow_thickness * 2,
 
2085
                      XmNheight, (ROW_HEIGHT(mw) -
 
2086
                                  mw->matrix.cell_shadow_thickness * 2),
 
2087
                      XmNmaxLength, (mw->matrix.column_max_lengths ?
 
2088
                                     mw->matrix.column_max_lengths[column] :
 
2089
                                     (int) mw->matrix.column_widths[column]),
 
2090
                      XmNeditable, call_data.doit,
 
2091
                      XmNcursorPositionVisible, call_data.doit,
 
2092
                      XmNbackground, bgcolor,
 
2093
                      XmNforeground, fgcolor,
 
2094
                      XmNpattern, call_data.pattern,
 
2095
                      XmNoverwriteMode, call_data.overwrite_mode,
 
2096
                      XmNautoFill, call_data.auto_fill,
 
2097
                      XmNconvertCase, call_data.convert_case,
 
2098
                      NULL);
 
2099
 
 
2100
        XtVaSetValues(TextChild(mw), XmNvalue, string, NULL);
 
2101
 
 
2102
        XtAddCallback(TextChild(mw), XmNmodifyVerifyCallback,
 
2103
                      xbaeModifyVerifyCB, (XtPointer)mw);
 
2104
#if CELL_WIDGETS
 
2105
    }
 
2106
    else
 
2107
        XtVaSetValues(userWidget,
 
2108
                      XmNwidth, COLUMN_WIDTH(mw, column) -
 
2109
                      mw->matrix.cell_shadow_thickness * 2,
 
2110
                      XmNheight, ROW_HEIGHT(mw)
 
2111
                      - mw->matrix.cell_shadow_thickness * 2,
 
2112
                      XmNbackground, bgcolor,
 
2113
                      XmNforeground, fgcolor,
 
2114
                      NULL);
 
2115
#endif
 
2116
 
 
2117
    /*
 
2118
     * No need to do anything else if the text field is not going to
 
2119
     * be mapped
 
2120
     */
 
2121
    if (!call_data.map)
 
2122
        return;
 
2123
 
 
2124
    /*
 
2125
     * Manage and map the textField
 
2126
     */
 
2127
#if CELL_WIDGETS
 
2128
    if (userWidget)
 
2129
    {
 
2130
        XtUnmanageChild(TextChild(mw));
 
2131
        XtManageChild(userWidget);
 
2132
    }
 
2133
    else
 
2134
#endif
 
2135
        XtManageChild(TextChild(mw));
 
2136
 
 
2137
    if (XtIsRealized(TextChild(mw))
 
2138
#if CELL_WIDGETS
 
2139
        && !userWidget
 
2140
#endif
 
2141
        )
 
2142
        XtMapWidget(TextChild(mw));
 
2143
#if CELL_WIDGETS
 
2144
    else if (XtIsRealized(userWidget) && userWidget)
 
2145
        XtMapWidget(userWidget);
 
2146
 
 
2147
    if (call_data.doit && !userWidget) 
 
2148
#endif
 
2149
        /*
 
2150
         * Set the insert position of the cursor
 
2151
         */
 
2152
        if (call_data.doit)
 
2153
        {
 
2154
            int position = call_data.position;
 
2155
            int length = strlen(string);
 
2156
 
 
2157
            if (event && (event->type == ButtonPress ||
 
2158
                          event->type == ButtonRelease ) &&
 
2159
                position < 0 && mw->matrix.calc_cursor_position)
 
2160
            {
 
2161
                /*
 
2162
                 * The location of the pointer click needs to be calculated
 
2163
                 * so the cursor can be positioned.  If position is >= 0,
 
2164
                 * it has been set in the enterCellCallback and must
 
2165
                 * be honoured elsewhere.
 
2166
                 */
 
2167
                CellType cell;
 
2168
                int r, c;
 
2169
                
 
2170
                /*
 
2171
                 * The event must have occurred in a legal position
 
2172
                 * otherwise control wouldn't have made it here
 
2173
                 */
 
2174
                (void)xbaeEventToXY(mw, event, &x, &y, &cell);
 
2175
                (void)xbaeXYToRowCol(mw, &x, &y, &r, &c, cell);
 
2176
                x -= mw->matrix.cell_shadow_thickness;
 
2177
                y = ROW_HEIGHT(mw) / 2; /* XXX should be real y! */
 
2178
                position = XmTextXYToPos(TextChild(mw), x, y);
 
2179
            }
 
2180
            
 
2181
            if (call_data.select_text)
 
2182
                XmTextSetSelection(TextChild(mw), 0, length,
 
2183
                                        CurrentTime);            
 
2184
            if (position < 0)
 
2185
                XmTextSetInsertionPosition(TextChild(mw), length);
 
2186
            else
 
2187
                XmTextSetInsertionPosition(
 
2188
                    TextChild(mw), position > length ? length : position);
 
2189
        }
 
2190
        
 
2191
}
 
2192
 
 
2193
/*
 
2194
 * Matrix select_cell method
 
2195
 */
 
2196
void
 
2197
xbaeSelectCell(mw, row, column)
 
2198
XbaeMatrixWidget mw;
 
2199
int row, column;
 
2200
{
 
2201
    Boolean visible;
 
2202
 
 
2203
    if (row >= mw->matrix.rows || row < 0 ||
 
2204
        column >= mw->matrix.columns || column < 0)
 
2205
    {
 
2206
        XtAppWarningMsg(
 
2207
            XtWidgetToApplicationContext((Widget) mw),
 
2208
            "selectCell", "badIndex", "XbaeMatrix",
 
2209
            "XbaeMatrix: Row or column out of bounds for SelectCell.",
 
2210
            NULL, 0);
 
2211
        return;
 
2212
    }
 
2213
 
 
2214
    /* If no cells have been selected yet, allocate memory here */
 
2215
    if (!mw->matrix.selected_cells)
 
2216
        xbaeCopySelectedCells(mw);
 
2217
 
 
2218
    /*
 
2219
     * Scroll the cell onto the screen
 
2220
     */
 
2221
    visible = xbaeIsCellVisible(mw, row, column);
 
2222
 
 
2223
    if (mw->matrix.scroll_select && !visible)
 
2224
        xbaeMakeCellVisible(mw, row, column);
 
2225
 
 
2226
    /*
 
2227
     * If the cell is not already selected, select it and redraw it
 
2228
     */
 
2229
    if (!mw->matrix.selected_cells[row][column])
 
2230
    {
 
2231
        mw->matrix.selected_cells[row][column] = True;
 
2232
        mw->matrix.num_selected_cells++;
 
2233
        if (mw->matrix.scroll_select || visible)
 
2234
        {
 
2235
            if (row >= TRAILING_VERT_ORIGIN(mw))
 
2236
                xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2237
            
 
2238
            xbaeDrawCell(mw, row, column);
 
2239
 
 
2240
            if (row >= TRAILING_VERT_ORIGIN(mw))
 
2241
                xbaeSetClipMask(mw, CLIP_NONE);
 
2242
        }
 
2243
    }
 
2244
}
 
2245
 
 
2246
/*
 
2247
 * Matrix select_row method
 
2248
 */
 
2249
void
 
2250
xbaeSelectRow(mw, row)
 
2251
XbaeMatrixWidget mw;
 
2252
int row;
 
2253
{
 
2254
    int j, lc, rc;
 
2255
    Boolean fixed = False, trailing_fixed = False;
 
2256
    Boolean visible;
 
2257
    unsigned int clip_reason = CLIP_NONE, save_clip = CLIP_NONE;
 
2258
 
 
2259
    if (row >= mw->matrix.rows || row < 0)
 
2260
    {
 
2261
        XtAppWarningMsg(
 
2262
            XtWidgetToApplicationContext((Widget) mw),
 
2263
            "selectRow", "badIndex", "XbaeMatrix",
 
2264
            "XbaeMatrix: Row out of bounds for SelectRow.",
 
2265
            NULL, 0);
 
2266
        return;
 
2267
    }
 
2268
 
 
2269
    /* If no cells have been selected yet, allocate memory here */
 
2270
    if (!mw->matrix.selected_cells)
 
2271
        xbaeCopySelectedCells(mw);
 
2272
 
 
2273
    visible = xbaeIsRowVisible(mw, row);
 
2274
    /*
 
2275
     * Scroll the row onto the screen
 
2276
     */
 
2277
    if (mw->matrix.scroll_select)
 
2278
        xbaeMakeRowVisible(mw, row);
 
2279
 
 
2280
    /*
 
2281
     * If the row is not visible, there's no need to redraw - but, we do
 
2282
     * need to update the selected cell resource
 
2283
     */
 
2284
    if(!mw->matrix.scroll_select && !visible)
 
2285
    {
 
2286
        for (j = 0; j < mw->matrix.columns; j++)
 
2287
            if (!mw->matrix.selected_cells[row][j])
 
2288
            {
 
2289
                mw->matrix.num_selected_cells++;
 
2290
                mw->matrix.selected_cells[row][j] = True;
 
2291
            }
 
2292
        return;
 
2293
    }
 
2294
    
 
2295
    /*
 
2296
     * Establish any necessary clipping for redrawing the cells
 
2297
     */
 
2298
    save_clip = mw->matrix.current_clip;
 
2299
    if (row >= TRAILING_VERT_ORIGIN(mw))
 
2300
        clip_reason = CLIP_TRAILING_FIXED_ROWS;
 
2301
    if (CLIP_NONE != clip_reason)
 
2302
        xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2303
 
 
2304
    /*
 
2305
     * For each cell in the row, if the cell is not already selected,
 
2306
     * select it and redraw it
 
2307
     */
 
2308
    xbaeGetVisibleColumns(mw, &lc, &rc);
 
2309
    for (j = 0; j < mw->matrix.columns; j++)
 
2310
    {
 
2311
        if (!mw->matrix.selected_cells[row][j])
 
2312
        {
 
2313
            mw->matrix.selected_cells[row][j] = True;
 
2314
            mw->matrix.num_selected_cells++;
 
2315
            if ((j >= lc && j <= rc) ||
 
2316
                (j < (int)mw->matrix.fixed_columns) ||
 
2317
                (j >= TRAILING_HORIZ_ORIGIN(mw)))
 
2318
            {
 
2319
                if ((! fixed) && (j < (int)mw->matrix.fixed_columns))
 
2320
                {
 
2321
                    fixed = True;
 
2322
                    xbaeSetClipMask(mw, clip_reason | CLIP_FIXED_COLUMNS);
 
2323
                }
 
2324
                else if (fixed && (j >= (int)mw->matrix.fixed_columns) &&
 
2325
                         (j < TRAILING_HORIZ_ORIGIN(mw)))
 
2326
                {
 
2327
                    fixed = False;
 
2328
                    xbaeSetClipMask(mw, clip_reason);
 
2329
                }
 
2330
                else if ((! trailing_fixed) && (j >= TRAILING_HORIZ_ORIGIN(mw)))
 
2331
                {
 
2332
                    trailing_fixed = True;
 
2333
                    xbaeSetClipMask(mw, clip_reason |
 
2334
                                    CLIP_TRAILING_FIXED_COLUMNS);
 
2335
                }
 
2336
                
 
2337
                xbaeClearCell(mw, row, j);
 
2338
                xbaeDrawCell(mw, row, j);
 
2339
            }
 
2340
        }
 
2341
    }
 
2342
    if (save_clip != mw->matrix.current_clip)
 
2343
        xbaeSetClipMask(mw, CLIP_NONE);
 
2344
}
 
2345
 
 
2346
/*
 
2347
 * Matrix select_column method
 
2348
 */
 
2349
void
 
2350
xbaeSelectColumn(mw, column)
 
2351
XbaeMatrixWidget mw;
 
2352
int column;
 
2353
{
 
2354
    int i, tr, br;
 
2355
    Boolean once = False;
 
2356
 
 
2357
    unsigned int clip_reason = CLIP_NONE;
 
2358
 
 
2359
    if (column >= mw->matrix.columns || column < 0)
 
2360
    {
 
2361
        XtAppWarningMsg(
 
2362
            XtWidgetToApplicationContext((Widget) mw),
 
2363
            "selectColumn", "badIndex", "XbaeMatrix",
 
2364
            "XbaeMatrix: Column out of bounds for SelectColumn.",
 
2365
            NULL, 0);
 
2366
        return;
 
2367
    }
 
2368
 
 
2369
    /* If no cells have been selected yet, allocate memory here */
 
2370
    if (!mw->matrix.selected_cells)
 
2371
        xbaeCopySelectedCells(mw);
 
2372
 
 
2373
    /*
 
2374
     * Scroll the column onto the screen
 
2375
     */
 
2376
    if (mw->matrix.scroll_select)
 
2377
        xbaeMakeColumnVisible(mw, column);
 
2378
 
 
2379
    /*
 
2380
     * No need to redraw unless the column is visible
 
2381
     */
 
2382
    if (!mw->matrix.scroll_select && !xbaeIsColumnVisible(mw, column))
 
2383
    {
 
2384
        for (i = 0; i < mw->matrix.rows; i++)
 
2385
            if (!mw->matrix.selected_cells[i][column])
 
2386
            {
 
2387
                mw->matrix.num_selected_cells++;
 
2388
                mw->matrix.selected_cells[i][column] = True;
 
2389
            }
 
2390
        return;
 
2391
    }
 
2392
    
 
2393
    /*
 
2394
     * Establish any necessary clipping for redrawing the cells
 
2395
     */
 
2396
    if (column < (int)mw->matrix.fixed_columns)
 
2397
        clip_reason = CLIP_FIXED_COLUMNS;
 
2398
    else if (column >= TRAILING_HORIZ_ORIGIN(mw))
 
2399
        clip_reason = CLIP_TRAILING_FIXED_COLUMNS;
 
2400
    if (CLIP_NONE != clip_reason)
 
2401
        xbaeSetClipMask(mw, clip_reason | CLIP_VISIBLE_HEIGHT);
 
2402
        
 
2403
    /*
 
2404
     * For each cell in the column, if the cell is not already selected,
 
2405
     * select it and redraw it
 
2406
     */
 
2407
    xbaeGetVisibleRows(mw, &tr, &br);
 
2408
    for (i = 0; i < mw->matrix.rows; i++)
 
2409
    {
 
2410
        if (!mw->matrix.selected_cells[i][column])
 
2411
        {
 
2412
            mw->matrix.selected_cells[i][column] = True;
 
2413
            mw->matrix.num_selected_cells++;
 
2414
            if ((i >= tr && i <= br) ||
 
2415
                (i < (int)mw->matrix.fixed_rows) ||
 
2416
                (i >= TRAILING_VERT_ORIGIN(mw)))
 
2417
            {
 
2418
                if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
 
2419
                {
 
2420
                    once = True;
 
2421
                    xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_ROWS);
 
2422
                }
 
2423
                
 
2424
                xbaeClearCell(mw, i, column);
 
2425
                xbaeDrawCell(mw, i, column);                
 
2426
            }
 
2427
        }
 
2428
    }
 
2429
    
 
2430
    if (once || (CLIP_NONE != clip_reason))
 
2431
        xbaeSetClipMask(mw, CLIP_NONE);
 
2432
}
 
2433
 
 
2434
/*
 
2435
 * Matrix deselect_all method
 
2436
 */
 
2437
void
 
2438
xbaeDeselectAll(mw)
 
2439
XbaeMatrixWidget mw;
 
2440
{
 
2441
    int i, j;
 
2442
    int tr, br, lc, rc;
 
2443
    register Boolean do_row, once = False;
 
2444
 
 
2445
    mw->matrix.num_selected_cells = 0;
 
2446
    /* If selected_cells is NULL, no cells have been selected yet  */
 
2447
    if (!mw->matrix.selected_cells)
 
2448
        return;
 
2449
    
 
2450
    xbaeGetVisibleCells(mw, &tr, &br, &lc, &rc);
 
2451
    
 
2452
    for (i = 0; i < mw->matrix.rows; i++)
 
2453
    {
 
2454
        do_row = False;
 
2455
        if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
 
2456
        {
 
2457
            once = True;
 
2458
            xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2459
        }
 
2460
        for (j = 0; j < mw->matrix.columns; j++)
 
2461
        {
 
2462
            if (mw->matrix.selected_cells[i][j])
 
2463
            {
 
2464
                mw->matrix.selected_cells[i][j] = False;
 
2465
                if (((i < (int)mw->matrix.fixed_rows) ||
 
2466
                     (i >= TRAILING_VERT_ORIGIN(mw)) ||
 
2467
                     (i >= tr && i <= br)) &&
 
2468
                    ((j < (int)mw->matrix.fixed_columns) ||
 
2469
                     (j >= TRAILING_HORIZ_ORIGIN(mw)) ||
 
2470
                     (j >= lc && j <= rc)))
 
2471
                {
 
2472
                    xbaeClearCell(mw, i, j);
 
2473
                    xbaeDrawCell(mw, i, j);
 
2474
 
 
2475
                    do_row = True;
 
2476
                }
 
2477
            }
 
2478
        }
 
2479
    }
 
2480
    if (once)
 
2481
        xbaeSetClipMask(mw, CLIP_NONE);
 
2482
}
 
2483
 
 
2484
/*
 
2485
 * Matrix select_all method
 
2486
 */
 
2487
void
 
2488
xbaeSelectAll(mw)
 
2489
XbaeMatrixWidget mw;
 
2490
{
 
2491
    int i, j;
 
2492
    int tr, br, lc, rc;
 
2493
    register Boolean do_row, once = False;
 
2494
 
 
2495
    xbaeGetVisibleCells(mw, &tr, &br, &lc, &rc);
 
2496
    
 
2497
    if (!mw->matrix.selected_cells)
 
2498
        xbaeCopySelectedCells(mw);
 
2499
 
 
2500
    for (i = 0; i < mw->matrix.rows; i++)
 
2501
    {
 
2502
        do_row = False;
 
2503
        if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
 
2504
        {
 
2505
            once = True;
 
2506
            xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2507
        }
 
2508
        for (j = 0; j < mw->matrix.columns; j++)
 
2509
        {
 
2510
            if (!mw->matrix.selected_cells[i][j])
 
2511
            {
 
2512
                mw->matrix.num_selected_cells++;
 
2513
                mw->matrix.selected_cells[i][j] = True;
 
2514
                if (((i < (int)mw->matrix.fixed_rows) ||
 
2515
                     (i >= TRAILING_VERT_ORIGIN(mw)) ||
 
2516
                     (i >= tr && i <= br)) &&
 
2517
                    ((j < (int)mw->matrix.fixed_columns) ||
 
2518
                     (j >= TRAILING_HORIZ_ORIGIN(mw)) ||
 
2519
                     (j >= lc && j <= rc)))
 
2520
                {
 
2521
                    xbaeClearCell(mw, i, j);
 
2522
                    xbaeDrawCell(mw, i, j);
 
2523
 
 
2524
                    do_row = True;
 
2525
                }
 
2526
            }
 
2527
        }
 
2528
 
 
2529
    }
 
2530
    if (once)
 
2531
        xbaeSetClipMask(mw, CLIP_NONE);
 
2532
}
 
2533
 
 
2534
/*
 
2535
 * Matrix deselect_cell method
 
2536
 */
 
2537
void
 
2538
xbaeDeselectCell(mw, row, column)
 
2539
XbaeMatrixWidget mw;
 
2540
int row;
 
2541
int column;
 
2542
{
 
2543
    if (row >= mw->matrix.rows || row < 0 ||
 
2544
        column > mw->matrix.columns - 1 || column < 0)
 
2545
    {
 
2546
        XtAppWarningMsg(
 
2547
            XtWidgetToApplicationContext((Widget) mw),
 
2548
            "deselectCell", "badIndex", "XbaeMatrix",
 
2549
            "XbaeMatrix: Row or column out of bounds for DeselectCell.",
 
2550
            NULL, 0);
 
2551
        return;
 
2552
    }
 
2553
 
 
2554
    if (!mw->matrix.selected_cells)
 
2555
        return;
 
2556
 
 
2557
    if (mw->matrix.selected_cells[row][column])
 
2558
    {
 
2559
        mw->matrix.num_selected_cells--;
 
2560
        mw->matrix.selected_cells[row][column] = False;
 
2561
        if (xbaeIsCellVisible(mw, row, column))
 
2562
        {
 
2563
            if (row >= TRAILING_VERT_ORIGIN(mw))
 
2564
                xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2565
 
 
2566
            xbaeClearCell(mw, row, column);
 
2567
            xbaeDrawCell(mw, row, column);
 
2568
 
 
2569
            if (row >= TRAILING_VERT_ORIGIN(mw))
 
2570
                xbaeSetClipMask(mw, CLIP_NONE);
 
2571
 
 
2572
        }
 
2573
    }
 
2574
}
 
2575
 
 
2576
/*
 
2577
 * Matrix deselect_row method
 
2578
 */
 
2579
void
 
2580
xbaeDeselectRow(mw, row)
 
2581
XbaeMatrixWidget mw;
 
2582
int row;
 
2583
{
 
2584
    int j, lc, rc;
 
2585
    Boolean fixed = False, trailing_fixed = False;
 
2586
    unsigned int clip_reason = CLIP_NONE, save_clip;
 
2587
 
 
2588
    if (row >= mw->matrix.rows || row < 0)
 
2589
    {
 
2590
        XtAppWarningMsg(
 
2591
            XtWidgetToApplicationContext((Widget) mw),
 
2592
            "deselectRow", "badIndex", "XbaeMatrix",
 
2593
            "XbaeMatrix: Row parameter out of bounds for DeselectRow.",
 
2594
            NULL, 0);
 
2595
        return;
 
2596
    }
 
2597
 
 
2598
    if (!mw->matrix.selected_cells)
 
2599
        return;
 
2600
 
 
2601
    /*
 
2602
     * Establish any necessary clipping for redrawing the cells
 
2603
     */
 
2604
    save_clip = mw->matrix.current_clip;
 
2605
    if (row >= TRAILING_VERT_ORIGIN(mw))
 
2606
        clip_reason = CLIP_TRAILING_FIXED_ROWS;
 
2607
    if (CLIP_NONE != clip_reason)
 
2608
        xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
 
2609
 
 
2610
    /*
 
2611
     * For each cell in the row, if the cell is selected,
 
2612
     * deselect it and redraw it
 
2613
     */
 
2614
    xbaeGetVisibleColumns(mw, &lc, &rc);
 
2615
    for (j = 0; j < mw->matrix.columns; j++)
 
2616
    {
 
2617
        if (mw->matrix.selected_cells[row][j])
 
2618
        {
 
2619
            mw->matrix.num_selected_cells--;
 
2620
            mw->matrix.selected_cells[row][j] = False;
 
2621
            if ((j >= lc && j <= rc) ||
 
2622
                (j < (int)mw->matrix.fixed_columns) ||
 
2623
                (j >= TRAILING_HORIZ_ORIGIN(mw)))
 
2624
            {
 
2625
                if ((! fixed) && (j < (int)mw->matrix.fixed_columns))
 
2626
                {
 
2627
                    fixed = True;
 
2628
                    xbaeSetClipMask(mw, clip_reason | CLIP_FIXED_COLUMNS);
 
2629
                }
 
2630
                else if (fixed && (j >= (int)mw->matrix.fixed_columns) &&
 
2631
                         (j < TRAILING_HORIZ_ORIGIN(mw)))
 
2632
                {
 
2633
                    fixed = False;
 
2634
                    xbaeSetClipMask(mw, clip_reason);
 
2635
                }
 
2636
                else if ((! trailing_fixed) && (j >= TRAILING_HORIZ_ORIGIN(mw)))
 
2637
                {
 
2638
                    trailing_fixed = True;
 
2639
                    xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_COLUMNS);
 
2640
                }
 
2641
                
 
2642
                xbaeClearCell(mw, row, j);
 
2643
                xbaeDrawCell(mw, row, j);
 
2644
            }
 
2645
        }
 
2646
    }
 
2647
 
 
2648
    if (save_clip != mw->matrix.current_clip)
 
2649
        xbaeSetClipMask(mw, CLIP_NONE);
 
2650
}
 
2651
 
 
2652
/*
 
2653
 * Matrix deselect_column method
 
2654
 */
 
2655
void
 
2656
xbaeDeselectColumn(mw, column)
 
2657
XbaeMatrixWidget mw;
 
2658
int column;
 
2659
{
 
2660
    int i, tr, br;
 
2661
    Boolean once = False;
 
2662
    unsigned int clip_reason = CLIP_NONE;
 
2663
 
 
2664
    if (column >= mw->matrix.columns || column < 0)
 
2665
    {
 
2666
        XtAppWarningMsg(
 
2667
            XtWidgetToApplicationContext((Widget) mw),
 
2668
            "deselectColumn", "badIndex", "XbaeMatrix",
 
2669
            "XbaeMatrix: Column parameter out of bounds for DeselectColumn.",
 
2670
            NULL, 0);
 
2671
        return;
 
2672
    }
 
2673
 
 
2674
    if (!mw->matrix.selected_cells)
 
2675
        return;
 
2676
 
 
2677
    /*
 
2678
     * Establish any necessary clipping for redrawing the cells
 
2679
     */
 
2680
    if (column < (int)mw->matrix.fixed_columns)
 
2681
        clip_reason = CLIP_FIXED_COLUMNS;
 
2682
    else if (column >= TRAILING_HORIZ_ORIGIN(mw))
 
2683
        clip_reason = CLIP_TRAILING_FIXED_COLUMNS;
 
2684
    if (CLIP_NONE != clip_reason)
 
2685
        xbaeSetClipMask(mw, clip_reason | CLIP_VISIBLE_HEIGHT);
 
2686
 
 
2687
    /*
 
2688
     * For each cell in the column, if the cell is selected,
 
2689
     * deselect it and redraw it
 
2690
     */
 
2691
    xbaeGetVisibleRows(mw, &tr, &br);
 
2692
    for (i = 0; i < mw->matrix.rows; i++)
 
2693
    {
 
2694
        if (mw->matrix.selected_cells[i][column])
 
2695
        {
 
2696
            mw->matrix.num_selected_cells--;
 
2697
            mw->matrix.selected_cells[i][column] = False;
 
2698
            if ((i >= tr && i <= br) ||
 
2699
                (i < (int)mw->matrix.fixed_rows) ||
 
2700
                (i >= TRAILING_VERT_ORIGIN(mw)))
 
2701
            {
 
2702
                if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
 
2703
                {
 
2704
                    once = True;
 
2705
                    xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_ROWS);
 
2706
                }
 
2707
 
 
2708
                xbaeClearCell(mw, i, column);
 
2709
                xbaeDrawCell(mw, i, column);
 
2710
 
 
2711
            }
 
2712
        }
 
2713
    }
 
2714
    if (once || (CLIP_NONE != clip_reason))
 
2715
        xbaeSetClipMask(mw, CLIP_NONE);
 
2716
}
 
2717
 
 
2718
/*
 
2719
 * Matrix get_cell method
 
2720
 */
 
2721
String
 
2722
xbaeGetCell(mw, row, column)
 
2723
XbaeMatrixWidget mw;
 
2724
int row, column;
 
2725
{
 
2726
    String value;
 
2727
    
 
2728
    if (row >= mw->matrix.rows || row < 0 ||
 
2729
        column > mw->matrix.columns - 1 || column < 0)
 
2730
    {
 
2731
        XtAppWarningMsg(
 
2732
            XtWidgetToApplicationContext((Widget) mw),
 
2733
            "getCell", "badIndex", "XbaeMatrix",
 
2734
            "XbaeMatrix: Row or column out of bounds for GetCell.",
 
2735
            NULL, 0);
 
2736
        return (NULL);
 
2737
    }
 
2738
    if (mw->matrix.draw_cell_callback)
 
2739
    {
 
2740
        Pixel bgcolor, fgcolor;
 
2741
        Pixmap pixmap, mask;
 
2742
        int width, height, depth;
 
2743
        
 
2744
        if (xbaeGetDrawCellValue(mw, row, column, &value, &pixmap,
 
2745
                                 &mask, &width, &height, &bgcolor, &fgcolor,
 
2746
                                 &depth) == XbaePixmap)
 
2747
            value = "";
 
2748
    }
 
2749
    else if (!mw->matrix.cells)
 
2750
        return "";
 
2751
    else
 
2752
        value = mw->matrix.cells[row][column];
 
2753
 
 
2754
    return value;
 
2755
}
 
2756
 
 
2757
/*
 
2758
 * Matrix commit_edit method
 
2759
 */
 
2760
Boolean
 
2761
#if NeedFunctionPrototypes
 
2762
xbaeCommitEdit(XbaeMatrixWidget mw, XEvent *event, Boolean unmap)
 
2763
#else
 
2764
xbaeCommitEdit(mw, event, unmap)
 
2765
XbaeMatrixWidget mw;
 
2766
XEvent *event;
 
2767
Boolean unmap;
 
2768
#endif
 
2769
{
 
2770
    Boolean commit;
 
2771
 
 
2772
    if (!XtIsManaged(TextChild(mw)))
 
2773
        return True;
 
2774
 
 
2775
    /*
 
2776
     * Attempt to commit the edit
 
2777
     */
 
2778
    commit = DoCommitEdit(mw, event);
 
2779
 
 
2780
    /*
 
2781
     * If the commit succeeded and we are supposed to unmap the textField,
 
2782
     * then hide the textField and traverse out
 
2783
     */
 
2784
    if (commit && unmap)
 
2785
    {
 
2786
        XtUnmanageChild(TextChild(mw));
 
2787
        XmProcessTraversal(TextChild(mw), XmTRAVERSE_RIGHT);
 
2788
    }
 
2789
 
 
2790
    return commit;
 
2791
}
 
2792
 
 
2793
/*
 
2794
 * Matrix cancel_edit method
 
2795
 */
 
2796
void
 
2797
#if NeedFunctionPrototypes
 
2798
xbaeCancelEdit(XbaeMatrixWidget mw, Boolean unmap)
 
2799
#else
 
2800
xbaeCancelEdit(mw, unmap)
 
2801
XbaeMatrixWidget mw;
 
2802
Boolean unmap;
 
2803
#endif
 
2804
{
 
2805
    if (!XtIsManaged(TextChild(mw)))
 
2806
        return;
 
2807
 
 
2808
    /*
 
2809
     * If unmap is set, hide the textField and traverse out.
 
2810
     */
 
2811
    if (unmap)
 
2812
    {
 
2813
        XtUnmanageChild(TextChild(mw));
 
2814
        XmProcessTraversal(TextChild(mw), XmTRAVERSE_RIGHT);
 
2815
    }
 
2816
 
 
2817
    /*
 
2818
     * Don't unmap, just restore original contents
 
2819
     */
 
2820
    else if (!mw->matrix.draw_cell_callback)
 
2821
    {
 
2822
        XtVaSetValues(TextChild(mw),
 
2823
                      XmNvalue, (mw->matrix.cells ?
 
2824
                                 mw->matrix.cells[mw->matrix.current_row]
 
2825
                                 [mw->matrix.current_column] : ""),
 
2826
                      NULL);
 
2827
    }
 
2828
    else
 
2829
    {
 
2830
        /* Ask the application what should be in the cell */
 
2831
        String string;
 
2832
        Pixmap pixmap, mask;
 
2833
        Pixel bg, fg;
 
2834
        int width, height, depth;
 
2835
        
 
2836
        if (xbaeGetDrawCellValue(mw, mw->matrix.current_row,
 
2837
                                 mw->matrix.current_column, &string,
 
2838
                                 &pixmap, &mask, &width, &height,
 
2839
                                 &bg, &fg, &depth) == XbaeString)
 
2840
 
 
2841
            XtVaSetValues(TextChild(mw), XmNvalue, string, NULL);
 
2842
    }
 
2843
}
 
2844
 
 
2845
/*
 
2846
 * Matrix add_rows method
 
2847
 */
 
2848
void
 
2849
xbaeAddRows(mw, position, rows, labels, colors, backgrounds, num_rows)
 
2850
XbaeMatrixWidget mw;
 
2851
int position;
 
2852
String *rows;
 
2853
String *labels;
 
2854
Pixel *colors;
 
2855
Pixel *backgrounds;
 
2856
int num_rows;
 
2857
{
 
2858
    Boolean haveVSB, haveHSB;
 
2859
 
 
2860
    /*
 
2861
     * Do some error checking.
 
2862
     */
 
2863
    if (num_rows <= 0)
 
2864
        return;
 
2865
    if (position < 0 || position > mw->matrix.rows)
 
2866
    {
 
2867
        XtAppWarningMsg(
 
2868
            XtWidgetToApplicationContext((Widget) mw),
 
2869
            "addRows", "badPosition", "XbaeMatrix",
 
2870
            "XbaeMatrix: Position out of bounds in AddRows.",
 
2871
            NULL, 0);
 
2872
        return;
 
2873
    }
 
2874
 
 
2875
    haveVSB = XtIsManaged(VertScrollChild(mw));
 
2876
    haveHSB = XtIsManaged(HorizScrollChild(mw));
 
2877
    /*
 
2878
     * If we add rows, and there is no drawCellCallback, we must allocate
 
2879
     * the cells array to prevent potential disaster
 
2880
     */
 
2881
    if (!mw->matrix.cells && !mw->matrix.draw_cell_callback)
 
2882
        xbaeCopyCells(mw);
 
2883
    
 
2884
    /*
 
2885
     * Add the new rows into the internal cells/labels data structure.
 
2886
     */
 
2887
    AddRowsToTable(mw, position, rows, labels, colors, backgrounds, num_rows);
 
2888
 
 
2889
    /*
 
2890
     * Reconfig the VSB maximum.
 
2891
     */
 
2892
    XtVaSetValues(VertScrollChild(mw),
 
2893
                  XmNmaximum, mw->matrix.rows ?
 
2894
                  (mw->matrix.rows - (int) mw->matrix.fixed_rows -
 
2895
                   (int) mw->matrix.trailing_fixed_rows) : 1,
 
2896
                  NULL);
 
2897
 
 
2898
    /*
 
2899
     * Relayout.
 
2900
     */
 
2901
    xbaeResize(mw);
 
2902
 
 
2903
    /*
 
2904
     * Call our cancel_edit method since the rows shifted underneath us
 
2905
     */
 
2906
    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
 
2907
        (mw, True);
 
2908
 
 
2909
    if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
2910
    {
 
2911
        Rectangle rect;
 
2912
        int x, y;
 
2913
 
 
2914
        /*
 
2915
         * Determine which part of the non clip region needs to be
 
2916
         * redisplayed
 
2917
         */
 
2918
        if (position >= (int)mw->matrix.fixed_rows)
 
2919
        {
 
2920
            xbaeRowColToXY(mw, position, mw->matrix.fixed_columns, &x, &y);
 
2921
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
2922
                mw->matrix.scrollbar_placement == XmTOP_RIGHT)
 
2923
                y += HORIZ_SB_SPACE(mw);
 
2924
            y += ROW_HEIGHT(mw) * mw->matrix.fixed_rows +
 
2925
                COLUMN_LABEL_HEIGHT(mw);
 
2926
        }
 
2927
        else
 
2928
        {
 
2929
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
2930
                mw->matrix.scrollbar_placement == XmTOP_RIGHT)
 
2931
                y = HORIZ_SB_SPACE(mw);
 
2932
            else
 
2933
                y = 0;
 
2934
            y += ROW_HEIGHT(mw) * position + COLUMN_LABEL_HEIGHT(mw);
 
2935
        }
 
2936
        SETRECT(rect, 0, y, mw->core.width, mw->core.height);
 
2937
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
2938
        XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
 
2939
                   rect.x1, rect.y1,
 
2940
                   rect.x2 - rect.x1, rect.y2 - rect.y1, True);
 
2941
        /*
 
2942
         * If the scrollbars have just been mapped and there are
 
2943
         * labels then the labels shift around. The labels need
 
2944
         * to be redrawn
 
2945
         */
 
2946
        if (!haveVSB && XtIsManaged(VertScrollChild(mw)) &&
 
2947
            mw->matrix.column_labels)
 
2948
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
2949
                       0, HORIZ_SB_OFFSET(mw), 0,
 
2950
                       COLUMN_LABEL_HEIGHT(mw), True);
 
2951
        if ((!haveHSB && XtIsManaged(VertScrollChild(mw)) &&
 
2952
             mw->matrix.row_labels) ||
 
2953
            ((mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
2954
              mw->matrix.scrollbar_placement == XmBOTTOM_LEFT) &&
 
2955
             !haveVSB && XtIsManaged(VertScrollChild(mw))))
 
2956
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
2957
                       VERT_SB_OFFSET(mw), 0, ROW_LABEL_WIDTH(mw), 0, True);
 
2958
    }
 
2959
}
 
2960
 
 
2961
/*
 
2962
 * Matrix delete_rows method
 
2963
 */
 
2964
void
 
2965
xbaeDeleteRows(mw, position, num_rows)
 
2966
XbaeMatrixWidget mw;
 
2967
int position;
 
2968
int num_rows;
 
2969
{
 
2970
    int        max, value;
 
2971
    Boolean haveVSB;
 
2972
    Boolean haveHSB;
 
2973
 
 
2974
    /*
 
2975
     * Do some error checking.
 
2976
     */
 
2977
    if (num_rows <= 0)
 
2978
        return;
 
2979
    if (position < 0 || position + num_rows > mw->matrix.rows)
 
2980
    {
 
2981
        XtAppWarningMsg(
 
2982
            XtWidgetToApplicationContext((Widget) mw),
 
2983
            "deleteRows", "badPosition", "XbaeMatrix",
 
2984
            "XbaeMatrix: Position out of bounds in DeleteRows.",
 
2985
            NULL, 0);
 
2986
        return;
 
2987
    }
 
2988
    if (num_rows > (mw->matrix.rows - (int)mw->matrix.fixed_rows -
 
2989
                    (int)mw->matrix.trailing_fixed_rows))
 
2990
    {
 
2991
        XtAppWarningMsg(
 
2992
            XtWidgetToApplicationContext((Widget) mw),
 
2993
            "deleteRows", "tooMany", "XbaeMatrix",
 
2994
            "XbaeMatrix: Attempting to delete too many rows in DeleteRows.",
 
2995
            NULL, 0);
 
2996
        return;
 
2997
    }
 
2998
 
 
2999
    haveVSB = XtIsManaged(VertScrollChild(mw));
 
3000
    haveHSB = XtIsManaged(HorizScrollChild(mw));
 
3001
 
 
3002
    /*
 
3003
     * Delete the new rows from the internal cells/labels data structure.
 
3004
     */
 
3005
    DeleteRowsFromTable(mw, position, num_rows);
 
3006
 
 
3007
    /*
 
3008
     * Reconfig the VSB maximum. Reset the sliderSize to avoid warnings.
 
3009
     * Also check the scrollbar value to see that it's not out of range.
 
3010
     */
 
3011
    XtVaGetValues(VertScrollChild(mw),
 
3012
                      XmNvalue, &value,
 
3013
                      NULL);
 
3014
 
 
3015
    max = mw->matrix.rows ?
 
3016
        (mw->matrix.rows - (int) mw->matrix.fixed_rows -
 
3017
         (int) mw->matrix.trailing_fixed_rows) : 1;
 
3018
 
 
3019
    XtVaSetValues(VertScrollChild(mw),
 
3020
                  XmNvalue, (value >= max) ? max - 1 : value,
 
3021
                  XmNmaximum, mw->matrix.rows - (int) mw->matrix.fixed_rows -
 
3022
                  (int) mw->matrix.trailing_fixed_rows ?
 
3023
                  (mw->matrix.rows - (int) mw->matrix.fixed_rows -
 
3024
                   (int) mw->matrix.trailing_fixed_rows) : 1,
 
3025
                  XmNsliderSize, 1,
 
3026
                  NULL);
 
3027
 
 
3028
    /*
 
3029
     * Relayout.
 
3030
     */
 
3031
    xbaeResize(mw);
 
3032
 
 
3033
    /*
 
3034
     * Call our cancel_edit method since the rows shifted underneath us
 
3035
     */
 
3036
    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
 
3037
        (mw, True);
 
3038
 
 
3039
    if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
3040
    {
 
3041
        Rectangle rect;
 
3042
        int y;
 
3043
 
 
3044
        /*
 
3045
         * Determine which part of the non clip region needs to be
 
3046
         * redisplayed
 
3047
         */
 
3048
#if 0
 
3049
        dest_y = (position - mw->matrix.fixed_rows) * ROW_HEIGHT(mw);
 
3050
        src_y = dest_y + num_rows * ROW_HEIGHT(mw);
 
3051
        if (XtIsManaged(LeftClip(mw)))
 
3052
        {
 
3053
            if (src_y < LeftClip(mw)->core.height)
 
3054
            {
 
3055
                /* Copy what we can up to replace the deleted rows */
 
3056
                XCopyArea(XtDisplay(mw), XtWindow(LeftClip(mw)),
 
3057
                          XtWindow(LeftClip(mw)), mw->matrix.draw_gc,
 
3058
                          0, src_y, LeftClip(mw)->core.width,
 
3059
                          LeftClip(mw)->core.height - src_y,
 
3060
                          0, dest_y);
 
3061
                /* And clear the new area that needs to be redrawn */
 
3062
                XClearArea(XtDisplay(mw), XtWindow(LeftClip(mw)),
 
3063
                           0, LeftClip(mw)->core.height - src_y,
 
3064
                           LeftClip(mw)->core.width,
 
3065
                           LeftClip(mw)->core.height - src_y, True);
 
3066
            }
 
3067
        }
 
3068
        if (XtIsManaged(RightClip(mw)))
 
3069
        {
 
3070
            if (src_y < RightClip(mw)->core.height)
 
3071
            {
 
3072
                XCopyArea(XtDisplay(mw), XtWindow(RightClip(mw)),
 
3073
                          XtWindow(RightClip(mw)), mw->matrix.draw_gc,
 
3074
                          0, src_y, RightClip(mw)->core.width,
 
3075
                          RightClip(mw)->core.height - src_y,
 
3076
                          0, dest_y);
 
3077
                XClearArea(XtDisplay(mw), XtWindow(RightClip(mw)),
 
3078
                           0, RightClip(mw)->core.height - src_y,
 
3079
                           RightClip(mw)->core.width,
 
3080
                           RightClip(mw)->core.height - src_y, True);
 
3081
            }
 
3082
        }
 
3083
#endif
 
3084
        y = ROW_LABEL_OFFSET(mw) + position * ROW_HEIGHT(mw);
 
3085
        SETRECT(rect, 0, y, mw->core.width, mw->core.height - y);
 
3086
        /* xxx could this use an XCopyArea() instead */
 
3087
        XClearArea(XtDisplay(mw), XtWindow(mw),
 
3088
                   0, y, mw->core.width, mw->core.height - y, True);
 
3089
 
 
3090
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
3091
 
 
3092
        y = (position - mw->matrix.fixed_rows) * ROW_HEIGHT(mw);
 
3093
 
 
3094
        XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
 
3095
                   0, y, rect.x2, mw->core.height - y, True);
 
3096
        /*
 
3097
         * If the scrollbars have just been unmapped and there are
 
3098
         * labels then the labels shift around. The labels need
 
3099
         * to be redrawn
 
3100
         */
 
3101
        if (haveVSB && !XtIsManaged(VertScrollChild(mw)) &&
 
3102
            mw->matrix.column_labels)
 
3103
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3104
                       0, HORIZ_SB_OFFSET(mw), 0,
 
3105
                       COLUMN_LABEL_HEIGHT(mw), True);
 
3106
        if (haveHSB && !XtIsManaged(VertScrollChild(mw)) &&
 
3107
            mw->matrix.row_labels)
 
3108
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3109
                       VERT_SB_OFFSET(mw), 0, ROW_LABEL_WIDTH(mw), 0, True);
 
3110
#if 0
 
3111
        /*
 
3112
         * If we are deleting rows and there are different cell backgrounds
 
3113
         * or foregrounds and the deleted row was on the visible clip, then
 
3114
         * the colours can get confused.
 
3115
         */
 
3116
        if (mw->matrix.colors || mw->matrix.even_row_background !=
 
3117
            mw->core.background_pixel || mw->matrix.odd_row_background !=
 
3118
            mw->core.background_pixel)
 
3119
            XbaeClipRedraw(ClipChild(mw));
 
3120
#endif
 
3121
    }
 
3122
}
 
3123
 
 
3124
/*
 
3125
 * Matrix add_columns method.
 
3126
 */
 
3127
void
 
3128
xbaeAddColumns(mw, position, columns, labels, widths, max_lengths,
 
3129
               alignments, label_alignments, colors, backgrounds, num_columns)
 
3130
XbaeMatrixWidget mw;
 
3131
int position;
 
3132
String *columns;
 
3133
String *labels;
 
3134
short *widths;
 
3135
int *max_lengths;
 
3136
unsigned char *alignments;
 
3137
unsigned char *label_alignments;
 
3138
Pixel *colors;
 
3139
Pixel *backgrounds;
 
3140
int num_columns;
 
3141
{
 
3142
    Boolean haveVSB;
 
3143
    Boolean haveHSB;
 
3144
 
 
3145
    /*
 
3146
     * Do some error checking.
 
3147
     */
 
3148
    if (num_columns <= 0)
 
3149
        return;
 
3150
    if (position < 0 || position > mw->matrix.columns)
 
3151
    {
 
3152
        XtAppWarningMsg(
 
3153
            XtWidgetToApplicationContext((Widget) mw),
 
3154
            "addColumns", "badPosition", "XbaeMatrix",
 
3155
            "XbaeMatrix: Position out of bounds in AddColumns.",
 
3156
            NULL, 0);
 
3157
        return;
 
3158
    }
 
3159
    if (!widths)
 
3160
    {
 
3161
        XtAppWarningMsg(
 
3162
            XtWidgetToApplicationContext((Widget) mw),
 
3163
            "addColumns", "noWidths", "XbaeMatrix",
 
3164
            "XbaeMatrix: Must specify column widths in AddColumns.",
 
3165
            NULL, 0);
 
3166
        return;
 
3167
    }
 
3168
 
 
3169
    /*
 
3170
     * If we add columns, and there is no drawCellCallback, we must allocate
 
3171
     * the cells array to prevent potential disaster
 
3172
     */
 
3173
    if (!mw->matrix.cells && !mw->matrix.draw_cell_callback)
 
3174
        xbaeCopyCells(mw);
 
3175
    
 
3176
    haveVSB = XtIsManaged(VertScrollChild(mw));
 
3177
    haveHSB = XtIsManaged(HorizScrollChild(mw));
 
3178
 
 
3179
    /*
 
3180
     * Add the new rows into the internal cells/labels data structure.
 
3181
     */
 
3182
    AddColumnsToTable(mw, position, columns, labels, widths, max_lengths,
 
3183
                      alignments, label_alignments, colors, backgrounds,
 
3184
                      num_columns);
 
3185
 
 
3186
    /*
 
3187
     * Reconfig the HSB maximum.
 
3188
     */
 
3189
    XtVaSetValues(HorizScrollChild(mw),
 
3190
                  XmNmaximum, NON_FIXED_TOTAL_WIDTH(mw) ?
 
3191
                  NON_FIXED_TOTAL_WIDTH(mw) : 1,
 
3192
                  NULL);
 
3193
    
 
3194
    /*
 
3195
     * Relayout.
 
3196
     */
 
3197
    xbaeResize(mw);
 
3198
    
 
3199
    /*
 
3200
     * Call our cancel_edit method since the columns shifted underneath us
 
3201
     */
 
3202
    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
 
3203
        (mw, True);
 
3204
    
 
3205
    if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
3206
    {
 
3207
        Rectangle rect;
 
3208
        int x, y;
 
3209
 
 
3210
        /*
 
3211
         * Determine which part of the non clip region needs to be
 
3212
         * redisplayed
 
3213
         */
 
3214
        if (position >= (int)mw->matrix.fixed_columns)
 
3215
        {
 
3216
            xbaeRowColToXY(mw, mw->matrix.fixed_columns, position, &x, &y);
 
3217
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3218
                mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
 
3219
                x += VERT_SB_SPACE(mw);
 
3220
            x += COLUMN_POSITION(mw, mw->matrix.fixed_columns) +
 
3221
                ROW_LABEL_WIDTH(mw);
 
3222
        }
 
3223
        else
 
3224
        {
 
3225
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3226
                mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
 
3227
                x = VERT_SB_SPACE(mw);
 
3228
            else
 
3229
                x = 0;
 
3230
            x += COLUMN_POSITION(mw, position) + ROW_LABEL_WIDTH(mw);
 
3231
        }
 
3232
        SETRECT(rect, x, 0, mw->core.width, mw->core.height);
 
3233
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
3234
        XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
 
3235
                   rect.x1, rect.y1,
 
3236
                   rect.x2 - rect.x1, rect.y2 - rect.y1, True);
 
3237
        /*
 
3238
         * If the scrollbars have just been mapped and there are
 
3239
         * labels then the labels shift around. The labels need
 
3240
         * to be redrawn
 
3241
         */
 
3242
        if ((!haveVSB && XtIsManaged(VertScrollChild(mw)) &&
 
3243
             mw->matrix.column_labels) ||
 
3244
            ((mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3245
              mw->matrix.scrollbar_placement == XmTOP_RIGHT) &&
 
3246
             !haveHSB && XtIsManaged(HorizScrollChild(mw))))
 
3247
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3248
                       0, HORIZ_SB_OFFSET(mw), 0,
 
3249
                       COLUMN_LABEL_HEIGHT(mw), True);
 
3250
        if ((!haveHSB && XtIsManaged(VertScrollChild(mw)) &&
 
3251
             mw->matrix.row_labels) ||
 
3252
            ((mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3253
              mw->matrix.scrollbar_placement == XmTOP_RIGHT)))
 
3254
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3255
                       VERT_SB_OFFSET(mw), 0, ROW_LABEL_WIDTH(mw), 0, True);
 
3256
    }
 
3257
}
 
3258
 
 
3259
/*
 
3260
 * Matrix delete_columns method
 
3261
 */
 
3262
void
 
3263
xbaeDeleteColumns(mw, position, num_columns)
 
3264
XbaeMatrixWidget mw;
 
3265
int position;
 
3266
int num_columns;
 
3267
{
 
3268
    int maxlines;
 
3269
    Boolean haveVSB;
 
3270
    Boolean haveHSB;
 
3271
 
 
3272
    /*
 
3273
     * Do some error checking.
 
3274
     */
 
3275
    if (num_columns <= 0)
 
3276
        return;
 
3277
    if (position < 0 || position + num_columns > mw->matrix.columns)
 
3278
    {
 
3279
        XtAppWarningMsg(
 
3280
            XtWidgetToApplicationContext((Widget) mw),
 
3281
            "deleteColumns", "badPosition", "XbaeMatrix",
 
3282
            "XbaeMatrix: Position out of bounds in DeleteColumns.",
 
3283
            NULL, 0);
 
3284
        return;
 
3285
    }
 
3286
    if (num_columns > (mw->matrix.columns - (int)mw->matrix.fixed_columns -
 
3287
                       (int)mw->matrix.trailing_fixed_columns))
 
3288
    {
 
3289
        XtAppWarningMsg(
 
3290
            XtWidgetToApplicationContext((Widget) mw),
 
3291
            "deleteColumns", "tooMany", "XbaeMatrix",
 
3292
            "XbaeMatrix: Attempting to delete too many columns in DeleteColumns.",
 
3293
            NULL, 0);
 
3294
        return;
 
3295
    }
 
3296
 
 
3297
    haveVSB = XtIsManaged(VertScrollChild(mw));
 
3298
    haveHSB = XtIsManaged(HorizScrollChild(mw));
 
3299
 
 
3300
    maxlines = mw->matrix.column_label_maxlines;
 
3301
 
 
3302
    /*
 
3303
     * Delete the new columns from the internal cells/labels data structure.
 
3304
     */
 
3305
    DeleteColumnsFromTable(mw, position, num_columns);
 
3306
 
 
3307
    /*
 
3308
     * Reconfig the HSB maximum. Reset the sliderSize to avoid warnings.
 
3309
     */
 
3310
    XtVaSetValues(HorizScrollChild(mw),
 
3311
                  XmNvalue, 0,    /* value to 0 to stop sb from whinging */
 
3312
                  XmNmaximum, NON_FIXED_TOTAL_WIDTH(mw) ?
 
3313
                  NON_FIXED_TOTAL_WIDTH(mw) : 1,
 
3314
                  XmNsliderSize, 1,
 
3315
                  NULL);
 
3316
 
 
3317
    /*
 
3318
     * Relayout.
 
3319
     */
 
3320
    xbaeResize(mw);
 
3321
 
 
3322
    /*
 
3323
     * Call our cancel_edit method since the columns shifted underneath us
 
3324
     */
 
3325
    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
 
3326
        (mw, True);
 
3327
 
 
3328
    if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
 
3329
    {
 
3330
        Rectangle rect;
 
3331
        int x, y;
 
3332
 
 
3333
        if (maxlines != mw->matrix.column_label_maxlines)
 
3334
        {
 
3335
            /*
 
3336
             * If a column with a high label gets deleted, then the matrix
 
3337
             * gets pulled up the screen and leaves dangly bits underneath.
 
3338
             * Clear the whole area to ensure correct display and forget the
 
3339
             * rest of the calculation
 
3340
             */
 
3341
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3342
                       0, 0, 0 /*Full Width*/, 0 /*Full Height*/,
 
3343
                       True);
 
3344
            return;
 
3345
        }
 
3346
        /*
 
3347
         * Determine which part of the non clip region needs to be
 
3348
         * redisplayed
 
3349
         */
 
3350
        if (position >= (int)mw->matrix.fixed_columns)
 
3351
        {
 
3352
            xbaeRowColToXY(mw, mw->matrix.fixed_columns, position, &x, &y);
 
3353
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3354
                mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
 
3355
                x += VERT_SB_SPACE(mw);
 
3356
            x += COLUMN_POSITION(mw, mw->matrix.fixed_columns) +
 
3357
                ROW_LABEL_WIDTH(mw);
 
3358
        }
 
3359
        else
 
3360
        {
 
3361
            if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
 
3362
                mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
 
3363
                x = VERT_SB_SPACE(mw);
 
3364
            else
 
3365
                x = 0;
 
3366
            x += COLUMN_POSITION(mw, position) + ROW_LABEL_WIDTH(mw);
 
3367
        }
 
3368
        SETRECT(rect, x, 0, mw->core.width, mw->core.height);
 
3369
        XClearArea(XtDisplay(mw), XtWindow(mw),
 
3370
                   VISIBLE_WIDTH(mw) + FIXED_COLUMN_WIDTH(mw) +
 
3371
                   TRAILING_FIXED_COLUMN_WIDTH(mw),
 
3372
                   0,
 
3373
                   mw->core.width, mw->core.height, True);
 
3374
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
3375
        XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
 
3376
                   rect.x1, rect.y1,
 
3377
                   rect.x2 - rect.x1, rect.y2 - rect.y1, True);
 
3378
        /*
 
3379
         * If the scrollbars have just been unmapped and there are
 
3380
         * labels then the labels shift around. The labels need
 
3381
         * to be redrawn
 
3382
         */
 
3383
        if (haveVSB && !XtIsManaged(VertScrollChild(mw)) &&
 
3384
            mw->matrix.column_labels)
 
3385
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3386
                       0, HORIZ_SB_OFFSET(mw), 0,
 
3387
                       COLUMN_LABEL_HEIGHT(mw), True);
 
3388
        if (haveHSB && !XtIsManaged(VertScrollChild(mw)) &&
 
3389
            mw->matrix.row_labels)
 
3390
            XClearArea(XtDisplay(mw), XtWindow(mw),
 
3391
                       VERT_SB_OFFSET(mw), 0, ROW_LABEL_WIDTH(mw), 0, True);
 
3392
    }
 
3393
}
 
3394
 
 
3395
/*
 
3396
 * Matrix set_row_colors method
 
3397
 */
 
3398
void
 
3399
#if NeedFunctionPrototypes
 
3400
xbaeSetRowColors(XbaeMatrixWidget mw, int position, Pixel *colors,
 
3401
                 int num_colors, Boolean bg)
 
3402
#else
 
3403
xbaeSetRowColors(mw, position, colors, num_colors, bg)
 
3404
XbaeMatrixWidget mw;
 
3405
int position;
 
3406
Pixel *colors;
 
3407
int num_colors;
 
3408
Boolean bg;
 
3409
#endif
 
3410
{
 
3411
    Rectangle rect;
 
3412
    int i, j;
 
3413
    Pixel **set;
 
3414
    Pixel pixel;
 
3415
    
 
3416
    /*
 
3417
     * Do some error checking.
 
3418
     */
 
3419
    if (num_colors <= 0)
 
3420
        return;
 
3421
    if (position < 0 || position + num_colors > mw->matrix.rows)
 
3422
    {
 
3423
        XtAppWarningMsg(
 
3424
            XtWidgetToApplicationContext((Widget) mw),
 
3425
            "setRowColors", "badPosition", "XbaeMatrix",
 
3426
            "XbaeMatrix: Position out of bounds or too many colors in SetRowColors.",
 
3427
            NULL, 0);
 
3428
        return;
 
3429
    }
 
3430
 
 
3431
    /*
 
3432
     * If we don't have any colors yet, malloc them, and initialize
 
3433
     * unused entries to the appropriate color
 
3434
     */
 
3435
    if ((!bg && !mw->matrix.colors) ||
 
3436
        (bg && !mw->matrix.cell_background))
 
3437
    {
 
3438
        if (!bg)
 
3439
        {
 
3440
            xbaeCreateColors(mw);
 
3441
            set = &mw->matrix.colors[0];
 
3442
            pixel = mw->manager.foreground;
 
3443
            for (i = 0; i < position; i++)
 
3444
                for (j = 0; j < mw->matrix.columns; j++)
 
3445
                    set[i][j] = pixel;
 
3446
            for (i = position + num_colors; i < mw->matrix.rows; i++)
 
3447
                for (j = 0; j < mw->matrix.columns; j++)
 
3448
                    set[i][j] = pixel;
 
3449
        }
 
3450
        else
 
3451
            xbaeCopyBackgrounds(mw);
 
3452
    }
 
3453
    
 
3454
    if (!bg)
 
3455
        set = &mw->matrix.colors[0];
 
3456
    else
 
3457
        set = &mw->matrix.cell_background[0];
 
3458
 
 
3459
    /*
 
3460
     * Set each row to the appropriate color
 
3461
     */
 
3462
    for (i = 0; i < num_colors; i++)
 
3463
        for (j = 0; j < mw->matrix.columns; j++)
 
3464
            set[i + position][j] = colors[i];
 
3465
        
 
3466
    if (XtIsRealized((Widget)mw))
 
3467
    {
 
3468
        /*
 
3469
         * Redraw all the visible non-fixed cells. We don't need to clear first
 
3470
         * since only the color changed.
 
3471
         */
 
3472
        SETRECT(rect,
 
3473
                0, 0,
 
3474
                ClipChild(mw)->core.width - 1, ClipChild(mw)->core.height - 1);
 
3475
        xbaeRedrawCells(mw, &rect);
 
3476
 
 
3477
        /*
 
3478
         * Redraw all the visible fixed cells (but not the labels).
 
3479
         * We don't need to clear first since only the color changed.
 
3480
         */
 
3481
        SETRECT(rect,
 
3482
                ROW_LABEL_WIDTH(mw), COLUMN_LABEL_HEIGHT(mw),
 
3483
                mw->core.width - 1, mw->core.height - 1);
 
3484
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
3485
        
 
3486
    }
 
3487
    if (position <= mw->matrix.current_row && 
 
3488
        position + num_colors > mw->matrix.current_row &&
 
3489
        XtIsRealized(TextChild(mw)))
 
3490
    {
 
3491
        if (bg)
 
3492
            XtVaSetValues(TextChild(mw), XmNbackground, 
 
3493
                          mw->matrix.cell_background[mw->matrix.current_row]
 
3494
                          [mw->matrix.current_column],
 
3495
                          NULL);
 
3496
        else
 
3497
            XtVaSetValues(TextChild(mw), XmNforeground, 
 
3498
                          mw->matrix.colors[mw->matrix.current_row]
 
3499
                          [mw->matrix.current_column],
 
3500
                          NULL);
 
3501
    }
 
3502
}
 
3503
 
 
3504
/*
 
3505
 * Matrix set_column_colors method
 
3506
 */
 
3507
void
 
3508
#if NeedFunctionPrototypes
 
3509
xbaeSetColumnColors(XbaeMatrixWidget mw, int position, Pixel *colors,
 
3510
                    int num_colors, Boolean bg)
 
3511
#else
 
3512
xbaeSetColumnColors(mw, position, colors, num_colors, bg)
 
3513
XbaeMatrixWidget mw;
 
3514
int position;
 
3515
Pixel *colors;
 
3516
int num_colors;
 
3517
Boolean bg;
 
3518
#endif
 
3519
{
 
3520
    Rectangle rect;
 
3521
    int i, j;
 
3522
    Pixel **set;
 
3523
    Pixel pixel;
 
3524
    
 
3525
    /*
 
3526
     * Do some error checking.
 
3527
     */
 
3528
    if (num_colors <= 0)
 
3529
        return;
 
3530
    if (position < 0 || position + num_colors > mw->matrix.columns)
 
3531
    {
 
3532
        XtAppWarningMsg(
 
3533
            XtWidgetToApplicationContext((Widget) mw),
 
3534
            "setColumnColors", "badPosition", "XbaeMatrix",
 
3535
            "XbaeMatrix: Position out of bounds or too many colors in SetColumnColors.",
 
3536
            NULL, 0);
 
3537
        return;
 
3538
    }
 
3539
 
 
3540
    /*
 
3541
     * If we don't have any colors yet, malloc them, and initialize
 
3542
     * unused entries to foreground
 
3543
     */
 
3544
    if ((!bg && !mw->matrix.colors) ||
 
3545
        (bg && !mw->matrix.cell_background))
 
3546
    {
 
3547
        if (!bg)
 
3548
        {
 
3549
            xbaeCreateColors(mw);
 
3550
            set = &mw->matrix.colors[0];
 
3551
            pixel = mw->manager.foreground;
 
3552
            for (i = 0; i < mw->matrix.rows; i++)
 
3553
                for (j = 0; j < position; j++)
 
3554
                    set[i][j] = pixel;
 
3555
            for (i = 0; i < mw->matrix.rows; i++)
 
3556
                for (j = position + num_colors; j < mw->matrix.columns; j++)
 
3557
                    set[i][j] = pixel;
 
3558
        }
 
3559
        else
 
3560
            xbaeCopyBackgrounds(mw);
 
3561
    }
 
3562
 
 
3563
    if (!bg)
 
3564
        set = &mw->matrix.colors[0];
 
3565
    else
 
3566
        set = &mw->matrix.cell_background[0];
 
3567
 
 
3568
    /*
 
3569
     * Set each column to the appropriate color
 
3570
     */
 
3571
    for (i = 0; i < mw->matrix.rows; i++)
 
3572
        for (j = 0; j < num_colors; j++)
 
3573
            set[i][j + position] = colors[j];
 
3574
 
 
3575
    if (XtIsRealized((Widget)mw))
 
3576
    {
 
3577
        /*
 
3578
         * Redraw all the visible non-fixed cells. We don't need to clear first
 
3579
         * since only the color changed.
 
3580
         */
 
3581
        SETRECT(rect,
 
3582
                0, 0,
 
3583
                ClipChild(mw)->core.width - 1, ClipChild(mw)->core.height - 1);
 
3584
        xbaeRedrawCells(mw, &rect);
 
3585
 
 
3586
        /*
 
3587
         * Redraw all the visible fixed cells (but not the labels).
 
3588
         * We don't need to clear first since only the color changed.
 
3589
         */
 
3590
        SETRECT(rect,
 
3591
                ROW_LABEL_WIDTH(mw), COLUMN_LABEL_HEIGHT(mw),
 
3592
                mw->core.width - 1, mw->core.height - 1);
 
3593
        xbaeRedrawLabelsAndFixed(mw, &rect);
 
3594
    }
 
3595
    if (position <= mw->matrix.current_column && 
 
3596
        position + num_colors > mw->matrix.current_column &&
 
3597
        XtIsRealized(TextChild(mw)))
 
3598
    {
 
3599
        if (bg)
 
3600
            XtVaSetValues(TextChild(mw), XmNbackground, 
 
3601
                          mw->matrix.cell_background[mw->matrix.current_row]
 
3602
                          [mw->matrix.current_column],
 
3603
                          NULL);
 
3604
        else
 
3605
            XtVaSetValues(TextChild(mw), XmNforeground, 
 
3606
                          mw->matrix.colors[mw->matrix.current_row]
 
3607
                          [mw->matrix.current_column],
 
3608
                          NULL);
 
3609
    }
 
3610
}
 
3611
 
 
3612
/*
 
3613
 * Matrix set_cell_color method
 
3614
 */
 
3615
void
 
3616
#if NeedFunctionPrototypes
 
3617
xbaeSetCellColor(XbaeMatrixWidget mw, int row, int column, Pixel color, Boolean bg)
 
3618
#else
 
3619
xbaeSetCellColor(mw, row, column, color, bg)
 
3620
XbaeMatrixWidget mw;
 
3621
int row;
 
3622
int column;
 
3623
Pixel color;
 
3624
Boolean bg;
 
3625
#endif
 
3626
{
 
3627
    int i, j;
 
3628
    Pixel **set;
 
3629
    Pixel pixel;
 
3630
    
 
3631
    /*
 
3632
     * Do some error checking.
 
3633
     */
 
3634
    if (row >= mw->matrix.rows || row < 0 ||
 
3635
        column >= mw->matrix.columns || column < 0)
 
3636
    {
 
3637
        XtAppWarningMsg(
 
3638
            XtWidgetToApplicationContext((Widget) mw),
 
3639
            "xbaeSetCellColor", "badIndex", "XbaeMatrix",
 
3640
            "XbaeMatrix: Row or column out of bounds for xbaeSetCellColor.",
 
3641
            NULL, 0);
 
3642
        return;
 
3643
    }
 
3644
 
 
3645
    /*
 
3646
     * If we don't have any colors yet, malloc them and initialize them
 
3647
     */
 
3648
    if ((!bg && !mw->matrix.colors) ||
 
3649
        (bg && !mw->matrix.cell_background))
 
3650
    {
 
3651
        if (!bg)
 
3652
        {
 
3653
            xbaeCreateColors(mw);
 
3654
            set = &mw->matrix.colors[0];
 
3655
            pixel = mw->manager.foreground;
 
3656
            for (i = 0; i < mw->matrix.rows; i++)
 
3657
                for (j = 0; j < mw->matrix.columns; j++)
 
3658
                    set[i][j] = pixel;
 
3659
        }
 
3660
        else
 
3661
            xbaeCopyBackgrounds(mw);
 
3662
    }
 
3663
 
 
3664
    if (!bg)
 
3665
        set = &mw->matrix.colors[0];
 
3666
    else
 
3667
        set = &mw->matrix.cell_background[0];
 
3668
 
 
3669
    /*
 
3670
     * Set the cell's color
 
3671
     */
 
3672
    set[row][column] = color;
 
3673
 
 
3674
    if (XtIsRealized((Widget)mw))
 
3675
    {
 
3676
        /*
 
3677
         * Redraw the cell if it is visible
 
3678
         */
 
3679
        if (xbaeIsCellVisible(mw, row, column))
 
3680
            xbaeDrawCell(mw, row, column);
 
3681
    }
 
3682
    if (row == mw->matrix.current_row &&
 
3683
        column == mw->matrix.current_column && XtIsRealized(TextChild(mw)))
 
3684
    {
 
3685
        if (bg)
 
3686
            XtVaSetValues(TextChild(mw), XmNbackground, 
 
3687
                          mw->matrix.cell_background[mw->matrix.current_row]
 
3688
                          [mw->matrix.current_column],
 
3689
                          NULL);
 
3690
        else
 
3691
            XtVaSetValues(TextChild(mw), XmNforeground, 
 
3692
                          mw->matrix.colors[mw->matrix.current_row]
 
3693
                          [mw->matrix.current_column],
 
3694
                          NULL);
 
3695
    }
 
3696
}
 
3697