2
* Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
3
* Copyright(c) 1995-99 Andrew Lister
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
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.
27
* Methods.c created by Andrew Lister (7 August, 1995)
35
#include <X11/Intrinsic.h>
39
#include "ScrollMgr.h"
50
/* For memmove/bcopy */
53
#if !defined(HAVE_MEMMOVE) && !defined(XBAE_NEED_BCOPY)
54
#define XBAE_NEED_BCOPY
58
* Added another BCOPY macro for porting purposes. Porting to 15+ UNIX
59
* platforms. Renamed bcopy to BCOPY and typecast to fix compiler warnings
62
#if !defined(XBAE_NEED_BCOPY) || defined(SVR4) || defined(VMS) || defined(__EMX__)
63
#define BCOPY(src, dest, n) memmove((void *)(dest), (void *)(src), (n))
65
#define BCOPY(src, dest, n) bcopy((void *)(src), (void *)(dest), (n))
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 *));
78
* Add rows to the internal cells data structure.
79
* If rows or labels is NULL, add empty rows.
82
AddRowsToTable(mw, position, rows, labels, colors, backgrounds, num_rows)
94
* Realloc a larger array of row pointers and a larger label arrays
96
if (mw->matrix.cells || rows)
97
mw->matrix.cells = (String **) XtRealloc((char *) mw->matrix.cells,
98
(mw->matrix.rows + num_rows) *
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) *
106
if (mw->matrix.row_button_labels)
107
mw->matrix.row_button_labels =
108
(Boolean *) XtRealloc((char *) mw->matrix.
110
(mw->matrix.rows + num_rows) *
113
if (mw->matrix.colors || colors)
114
mw->matrix.colors = (Pixel **) XtRealloc((char *) mw->matrix.colors,
115
(mw->matrix.rows + num_rows) *
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) *
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 *));
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) *
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) *
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 *));
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));
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) *
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 *));
170
* If we are inserting rows into the middle, we need to make room.
172
if (position < mw->matrix.rows)
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 *));
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 *));
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 *));
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.
234
for (i = 0; i < num_rows; i++)
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));
251
if (mw->matrix.cell_widgets)
252
mw->matrix.cell_widgets[i + position] =
253
(Widget *) XtMalloc(mw->matrix.columns * sizeof(Widget));
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));
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.
283
for (i = 0; i < num_rows; i++)
284
for (j = 0; j < mw->matrix.columns; j++)
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] : "")) :
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;
298
if (mw->matrix.cell_widgets)
299
mw->matrix.cell_widgets[i + position][j] = NULL;
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;
314
mw->matrix.rows += num_rows;
318
* Delete rows from the internal cells data structure.
321
DeleteRowsFromTable(mw, position, num_rows)
329
* We don't bother to realloc, we will just have some wasted space.
330
* XXX is this a problem?
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.
338
for (i = position; i < position + num_rows; i++)
340
/* Fixed a crash I was getting, Since I allow NULL cells. Earl R. */
341
if (mw->matrix.cells && mw->matrix.cells[i])
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;
349
if (mw->matrix.row_labels) {
350
XtFree((XtPointer) mw->matrix.row_labels[i]);
351
mw->matrix.row_labels[i] = NULL;
353
if (mw->matrix.colors) {
354
XtFree((XtPointer) mw->matrix.colors[i]);
355
mw->matrix.colors[i] = NULL;
357
if (mw->matrix.cell_background) {
358
XtFree((XtPointer) mw->matrix.cell_background[i]);
359
mw->matrix.cell_background[i] = NULL;
362
if (mw->matrix.cell_widgets) {
363
XtFree((XtPointer) mw->matrix.cell_widgets[i]);
364
mw->matrix.cell_widgets[i] = NULL;
367
if (mw->matrix.cell_user_data) {
368
XtFree((XtPointer) mw->matrix.cell_user_data[i]);
369
mw->matrix.cell_user_data[i] = NULL;
371
if (mw->matrix.cell_shadow_types) {
372
XtFree((XtPointer) mw->matrix.cell_shadow_types[i]);
373
mw->matrix.cell_shadow_types[i] = NULL;
375
if (mw->matrix.selected_cells) {
377
* Deselect the row so num_selected_cells gets updated
379
xbaeDeselectRow(mw, i);
380
XtFree((XtPointer) mw->matrix.selected_cells[i]);
381
mw->matrix.selected_cells[i] = NULL;
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;
392
* Copy those rows which are below the ones deleted, up.
393
* (unless we deleted rows from the bottom).
395
if (position + num_rows < mw->matrix.rows)
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 *));
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 *));
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 *));
455
mw->matrix.rows -= num_rows;
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.
468
AddColumnsToTable(mw, position, columns, labels, widths, max_lengths,
469
alignments, label_alignments, colors, backgrounds,
477
unsigned char *alignments;
478
unsigned char *label_alignments;
486
* Realloc larger cells, widths, max_lengths, alignments, colors,
487
* highlighted_cells, selected_cells, labels and label lines arrays.
490
if (mw->matrix.rows == 0)
493
XtWidgetToApplicationContext((Widget) mw),
494
"AddColumns", "noRows", "XbaeMatrix",
495
"XbaeMatrix: Attempting to add columns with no rows.",
500
for (i = 0; i < mw->matrix.rows; i++)
502
if (mw->matrix.cells || columns)
504
if (!mw->matrix.cells)
506
mw->matrix.columns += num_columns;
508
mw->matrix.columns -= num_columns;
511
mw->matrix.cells[i] =
512
(String *) XtRealloc((char *) mw->matrix.cells[i],
513
(mw->matrix.columns + num_columns) *
516
if (mw->matrix.colors || colors)
518
if (!mw->matrix.colors)
520
mw->matrix.columns += num_columns;
522
mw->matrix.columns -= num_columns;
525
mw->matrix.colors[i] =
526
(Pixel *) XtRealloc((char *) mw->matrix.colors[i],
527
(mw->matrix.columns + num_columns) *
530
if (mw->matrix.cell_background || backgrounds)
532
if (!mw->matrix.cell_background)
534
mw->matrix.columns += num_columns;
535
xbaeCopyBackgrounds(mw);
536
mw->matrix.columns -= num_columns;
539
mw->matrix.cell_background[i] =
540
(Pixel *) XtRealloc((char *) mw->matrix.cell_background[i],
541
(mw->matrix.columns + num_columns) *
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) *
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) *
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) *
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));
576
mw->matrix.column_widths =
577
(short *) XtRealloc((char *) mw->matrix.column_widths,
578
(mw->matrix.columns + num_columns) *
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) *
587
if (mw->matrix.column_alignments)
588
mw->matrix.column_alignments =
590
XtRealloc((char *) mw->matrix.column_alignments,
591
(mw->matrix.columns + num_columns) *
592
sizeof(unsigned char));
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) *
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));
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) *
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));
620
if (mw->matrix.column_labels)
622
mw->matrix.column_labels =
623
(String *) XtRealloc((char *) mw->matrix.column_labels,
624
(mw->matrix.columns + num_columns) *
626
mw->matrix.column_label_lines =
627
(ColumnLabelLines) XtRealloc(
628
(char *) mw->matrix.column_label_lines, (mw->matrix.columns +
630
sizeof(ColumnLabelLinesRec));
634
* If we are inserting columns into the middle, we need to make room.
636
if (position < mw->matrix.columns)
638
BCOPY(&mw->matrix.column_widths[position],
639
&mw->matrix.column_widths[position + num_columns],
640
(mw->matrix.columns - position) * sizeof(short));
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));
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));
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));
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));
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));
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));
672
if (mw->matrix.column_labels)
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));
684
* Shift the columns in each row.
686
for (i = 0; i < mw->matrix.rows; i++)
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));
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));
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));
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.
738
for (j = 0; j < num_columns; j++)
740
mw->matrix.column_widths[j + position] = widths[j];
742
if (mw->matrix.column_max_lengths)
743
mw->matrix.column_max_lengths[j + position] =
744
max_lengths ? max_lengths[j] : (int) widths[j];
746
if (mw->matrix.column_alignments)
747
mw->matrix.column_alignments[j + position] =
748
alignments ? alignments[j] : XmALIGNMENT_BEGINNING;
750
if (mw->matrix.column_button_labels)
751
mw->matrix.column_button_labels[j + position] = False;
753
if (mw->matrix.column_label_alignments)
754
mw->matrix.column_label_alignments[j + position] =
755
label_alignments ? label_alignments[j] : XmALIGNMENT_BEGINNING;
757
if (mw->matrix.column_user_data)
758
mw->matrix.column_user_data[j + position] = (XtPointer) NULL;
761
if (mw->matrix.cell_widgets)
762
mw->matrix.cell_widgets[j + position] = NULL;
765
if (mw->matrix.column_shadow_types)
766
mw->matrix.column_shadow_types[j + position] =
767
mw->matrix.cell_shadow_type;
769
if (mw->matrix.column_labels)
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]);
778
* Add this new column to each row.
780
for (i = 0; i < mw->matrix.rows; i++)
782
if (mw->matrix.cells)
783
mw->matrix.cells[i][j + position] = columns ?
784
XtNewString(columns[i * num_columns + j]) :
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;
793
if (mw->matrix.cell_widgets)
794
mw->matrix.cell_widgets[i][j + position] = (Widget) NULL;
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;
810
mw->matrix.columns += num_columns;
811
xbaeGetCellTotalWidth(mw);
814
* See if the max number of column label lines changed
816
if (mw->matrix.column_labels)
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;
829
* Recalculate the column positions
831
xbaeFreeColumnPositions(mw);
832
mw->matrix.column_positions = CreateColumnPositions(mw);
833
xbaeGetColumnPositions(mw);
837
* Delete columns from the internal cells data structure.
840
DeleteColumnsFromTable(mw, position, num_columns)
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.
852
for (j = position; j < position + num_columns; j++)
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;
859
if (mw->matrix.column_labels)
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;
869
* Shift those columns after the ones being deleted, left.
870
* (unless we deleted columns from the right).
872
if (position + num_columns < mw->matrix.columns)
874
BCOPY(&mw->matrix.column_widths[position + num_columns],
875
&mw->matrix.column_widths[position],
876
(mw->matrix.columns - position - num_columns) * sizeof(short));
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));
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));
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) *
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));
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) *
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) *
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));
921
if (mw->matrix.column_labels)
923
BCOPY(&mw->matrix.column_labels[position + num_columns],
924
&mw->matrix.column_labels[position],
925
(mw->matrix.columns - position - num_columns) *
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));
934
* Shift the columns in each row.
936
for (i = 0; i < mw->matrix.rows; i++)
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) *
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) *
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) *
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) *
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) *
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) *
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));
985
mw->matrix.columns -= num_columns;
986
xbaeGetCellTotalWidth(mw);
989
* See if the max number of column label lines changed
991
if (mw->matrix.column_labels)
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;
1003
* Recalculate the column positions
1005
xbaeFreeColumnPositions(mw);
1006
mw->matrix.column_positions = CreateColumnPositions(mw);
1007
xbaeGetColumnPositions(mw);
1011
* Matrix set_cell method
1014
#if NeedFunctionPrototypes
1015
xbaeSetCell(XbaeMatrixWidget mw, int row, int column, const String value,
1016
Boolean update_text)
1018
xbaeSetCell(mw, row, column, value, update_text)
1019
XbaeMatrixWidget mw;
1023
Boolean update_text;
1026
if (row >= mw->matrix.rows || row < 0 ||
1027
column >= mw->matrix.columns || column < 0)
1030
XtWidgetToApplicationContext((Widget) mw),
1031
"xbaeSetCell", "badIndex", "XbaeMatrix",
1032
"XbaeMatrix: Row or column out of bounds for xbaeSetCell.",
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.
1042
if (mw->matrix.draw_cell_callback)
1044
XbaeMatrixWriteCellCallbackStruct call_data;
1046
if (mw->matrix.write_cell_callback)
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;
1057
XtCallCallbackList((Widget)mw, mw->matrix.write_cell_callback,
1058
(XtPointer) &call_data);
1064
* Store the new value in the cell.
1066
if (!mw->matrix.cells && value[0] != 0)
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
1075
* Now we are free to store the value in the widget's cell array
1077
if (mw->matrix.cells && /* It's OK to store the value */
1078
strcmp(mw->matrix.cells[row][column], value))
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).
1085
XtFree((XtPointer) mw->matrix.cells[row][column]);
1086
mw->matrix.cells[row][column] = XtNewString(value);
1095
if (xbaeIsCellVisible(mw, row, column))
1097
xbaeClearCell(mw, row, column);
1098
xbaeDrawCell(mw, row, column);
1102
* If we are editing this cell, load the textField too if update_text set.
1104
if (update_text && XtIsManaged(TextChild(mw)) &&
1105
mw->matrix.current_row == row && mw->matrix.current_column == column)
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);
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.
1120
if (mw->matrix.draw_cell_callback)
1122
Pixmap pixmap, mask;
1124
int width, height, depth;
1126
xbaeGetDrawCellValue(mw, mw->matrix.current_row,
1127
mw->matrix.current_column, &string,
1128
&pixmap, &mask, &width, &height,
1134
if (string[0] == '\0')
1135
XtVaSetValues(TextChild(mw),
1139
XmTextSetString(TextChild(mw), string);
1141
XtAddCallback(TextChild(mw), XmNmodifyVerifyCallback,
1142
xbaeModifyVerifyCB, (XtPointer)mw);
1147
DoCommitEdit(mw, event)
1148
XbaeMatrixWidget mw;
1153
if (!XtIsManaged(TextChild(mw)))
1157
* Get the value the user entered in the textField (this is a copy)
1159
cell = XmTextGetString(TextChild(mw));
1162
* Call the leaveCellCallback to see if we can leave the current cell.
1164
if (mw->matrix.leave_cell_callback)
1166
XbaeMatrixLeaveCellCallbackStruct call_data;
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;
1175
XtCallCallbackList((Widget) mw, mw->matrix.leave_cell_callback,
1176
(XtPointer)&call_data);
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.
1182
if (!call_data.doit)
1184
xbaeMakeCellVisible(
1185
mw, mw->matrix.current_row, mw->matrix.current_column);
1186
XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
1187
XtFree((XtPointer) cell);
1192
* Use the applications value if it is different.
1193
* If the application modified the string inplace, we will pick that
1196
if (call_data.value != cell)
1198
XtFree((XtPointer) cell);
1199
cell = call_data.value;
1204
* Call the set_cell method to store the new value in the cell and redraw.
1206
(*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.set_cell)
1207
(mw, mw->matrix.current_row, mw->matrix.current_column, cell, True);
1209
XtFree((XtPointer) cell);
1215
* Position and size the scrollbars and clip widget for our new size.
1219
XbaeMatrixWidget mw;
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;
1229
* Full size of widget (no SBs needed) - may be very large
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;
1239
* Portion of cells which are visible in clip widget
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);
1246
* Check the location of the scrollbars
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);
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.
1259
if (mw->matrix.hsb_display_policy == XmDISPLAY_STATIC)
1261
else if (mw->matrix.hsb_display_policy == XmDISPLAY_NONE)
1265
if (width >= full_width)
1271
height -= HORIZ_SB_HEIGHT(mw);
1274
* Same reasoning for the vertical scrollbar.
1276
if (mw->matrix.vsb_display_policy == XmDISPLAY_STATIC)
1278
else if (mw->matrix.vsb_display_policy == XmDISPLAY_NONE)
1282
if (height >= full_height)
1289
* If we have a vertical scrollbar, adjust the width and
1290
* recheck if we need the horizontal scrollbar.
1294
width -= VERT_SB_WIDTH(mw);
1295
if ((XmDISPLAY_NONE != mw->matrix.hsb_display_policy) &&
1296
(! has_horiz) && (width < full_width))
1299
height -= HORIZ_SB_HEIGHT(mw);
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
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
1314
* We also need to move the textField correspondingly
1318
* We were resized smaller than our max width.
1320
if (width < full_width)
1325
* Calculate the width of the non-fixed visible cells.
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);
1333
* Subtract the VSB if we have one.
1336
cell_width -= VERT_SB_WIDTH(mw);
1338
if (cell_width <= 0)
1342
* Adjust for shadow thickness.
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);
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.
1356
HorizScrollChild(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);
1368
* If the cells are scrolled off to the left, then drag them
1369
* back onto the screen.
1371
if (cell_width > horiz_visible)
1373
if ((HORIZ_ORIGIN(mw) -= (cell_width - horiz_visible)) < 0)
1375
HORIZ_ORIGIN(mw) = 0;
1376
mw->matrix.left_column = 0;
1379
if (XtIsManaged(TextChild(mw)))
1380
XtMoveWidget(TextChild(mw),
1381
TextChild(mw)->core.x +
1382
(cell_width - horiz_visible),
1383
TextChild(mw)->core.y);
1387
* Setup the HSB to reflect our new size.
1389
XtVaSetValues(HorizScrollChild(mw),
1390
XmNpageIncrement, cell_width,
1391
XmNsliderSize, cell_width,
1392
XmNvalue, HORIZ_ORIGIN(mw),
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.
1402
if (XtIsManaged(TextChild(mw)))
1403
XtMoveWidget(TextChild(mw),
1404
TextChild(mw)->core.x + HORIZ_ORIGIN(mw),
1405
TextChild(mw)->core.y);
1407
cell_width = NON_FIXED_TOTAL_WIDTH(mw);
1408
if (cell_width <= 0) cell_width = 1;
1410
HORIZ_ORIGIN(mw) = 0;
1411
mw->matrix.left_column = 0;
1416
HorizScrollChild(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)),
1425
HorizScrollChild(mw)->core.height,
1426
HorizScrollChild(mw)->core.border_width);
1428
XtVaSetValues(HorizScrollChild(mw),
1429
XmNpageIncrement, cell_width,
1430
XmNsliderSize, cell_width,
1431
XmNvalue, HORIZ_ORIGIN(mw),
1437
* We were resized smaller than our max height.
1439
if (height < full_height)
1444
* Calculate the height of the non-fixed visible cells.
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);
1451
* Subtract the HSB if we have one.
1454
cell_height -= HORIZ_SB_HEIGHT(mw);
1456
if (cell_height <= 0)
1460
* Adjust for shadow thickness.
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);
1466
VSBheight = cell_height +
1467
((mw->matrix.fixed_rows ? 1 : 2) *
1468
mw->manager.shadow_thickness);
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.
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),
1484
VertScrollChild(mw)->core.width, VSBheight > 0 ? VSBheight : 1,
1485
VertScrollChild(mw)->core.border_width);
1487
* If the cells are scrolled off the top, then drag them
1488
* back onto the screen.
1490
if (cell_height > vert_visible)
1492
int rows = (cell_height - vert_visible) / ROW_HEIGHT(mw);
1494
VERT_ORIGIN(mw) -= rows;
1496
if (XtIsManaged(TextChild(mw)))
1497
XtMoveWidget(TextChild(mw),
1498
TextChild(mw)->core.x,
1499
TextChild(mw)->core.y + rows * ROW_HEIGHT(mw));
1503
* Setup the VSB to reflect our new size.
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),
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.
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));
1525
cell_height = CELL_TOTAL_HEIGHT(mw);
1527
if (cell_height <= 0)
1530
rows_visible = mw->matrix.rows - mw->matrix.fixed_rows -
1531
mw->matrix.trailing_fixed_rows;
1532
VERT_ORIGIN(mw) = 0;
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),
1545
VertScrollChild(mw)->core.width,
1547
VertScrollChild(mw)->core.border_width);
1550
VertScrollChild(mw),
1551
XmNpageIncrement, rows_visible <= 0 ? 1 : rows_visible,
1552
XmNsliderSize, rows_visible <= 0 ? 1 : rows_visible,
1553
XmNvalue, VERT_ORIGIN(mw),
1559
* Map/unmap scrollbars based on flags set above
1561
if (has_horiz && !HorizScrollChild(mw)->core.managed)
1563
XtManageChild(HorizScrollChild(mw));
1565
* Generate an expose over the horizontal scrollbar to ensure it gets
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);
1573
* Take into account the little bit at the bottom of the screen
1574
* if the scrollbar is in the top location.
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),
1582
else if (!has_horiz && HorizScrollChild(mw)->core.managed)
1585
* Generate an expose over the horizontal scrollbar to ensure it gets
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);
1594
* Take into account the little bit at the bottom of the screen
1595
* if the scrollbar is in the top location.
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),
1604
if (has_vert && !VertScrollChild(mw)->core.managed)
1607
* Generate an expose over the vertical scrollbar region to ensure
1608
* it gets drawn properly
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);
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.
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);
1630
* Also clear the area below the matrix as it can get a little
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),
1639
else if (!has_vert && VertScrollChild(mw)->core.managed)
1642
* Generate an expose over the vertical scrollbar region to ensure
1643
* it gets drawn properly
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);
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
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);
1661
* And also clear the area below the matrix as it can get a little
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),
1671
* Now that we have cell_width & cell_height,
1672
* make the clip widget this size. Height is truncated to the
1675
XtConfigureWidget(ClipChild(mw),
1676
FIXED_COLUMN_LABEL_OFFSET(mw),
1677
FIXED_ROW_LABEL_OFFSET(mw),
1678
cell_width, cell_height, 0);
1680
/* Resize all the other clips */
1681
if (mw->matrix.fixed_columns <= 0)
1683
if (XtIsManaged(LeftClip(mw)))
1684
XtUnmanageChild(LeftClip(mw));
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));
1694
if (mw->matrix.trailing_fixed_columns <= 0)
1696
if (XtIsManaged(RightClip(mw)))
1697
XtUnmanageChild(RightClip(mw));
1701
XtConfigureWidget(RightClip(mw),
1702
cell_width + FIXED_COLUMN_LABEL_OFFSET(mw),
1703
FIXED_ROW_LABEL_OFFSET(mw),
1704
TRAILING_FIXED_COLUMN_WIDTH(mw),
1706
if (!XtIsManaged(RightClip(mw)))
1707
XtManageChild(RightClip(mw));
1709
if (mw->matrix.fixed_rows <= 0)
1711
if (XtIsManaged(TopClip(mw)))
1712
XtUnmanageChild(TopClip(mw));
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));
1722
if (mw->matrix.trailing_fixed_rows <= 0)
1724
if (XtIsManaged(BottomClip(mw)))
1725
XtUnmanageChild(BottomClip(mw));
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));
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.
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);
1747
* Save the non-truncated height. We need this so we can draw
1748
* the shadow correctly.
1750
mw->matrix.cell_visible_height = cell_height;
1753
* Set the clip_mask in our clipping GCs. This function relies on
1754
* the Clip widget being the correct size (above).
1756
if (XtIsRealized((Widget)mw))
1757
xbaeSetClipMask(mw, CLIP_NONE);
1759
if (mw->matrix.resize_callback != NULL)
1761
XbaeMatrixResizeCallbackStruct call_data;
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);
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.
1781
xbaeModifyVerifyCB(w, client, call)
1786
XbaeMatrixWidget mw = (XbaeMatrixWidget)client;
1787
XmTextVerifyCallbackStruct *verify = (XmTextVerifyCallbackStruct *)call;
1788
XbaeMatrixModifyVerifyCallbackStruct call_data;
1790
if (!mw->matrix.modify_verify_callback)
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;
1799
call_data.prev_text = ((XmTextRec*)w)->text.value;
1801
XtCallCallbackList((Widget) mw, mw->matrix.modify_verify_callback,
1802
(XtPointer) & call_data);
1807
* Matrix edit_cell method
1810
xbaeEditCell(mw, event, row, column, params, nparams)
1811
XbaeMatrixWidget mw;
1818
XbaeMatrixEnterCellCallbackStruct call_data;
1819
Window newWin, oldWin;
1821
Pixel fgcolor, bgcolor;
1824
Widget oldWidget, newWidget;
1829
if (row >= mw->matrix.rows || row < 0 ||
1830
column >= mw->matrix.columns || column < 0)
1833
* If we have zero rows or columns, there are no cells
1834
* available on which to place the text field so just return
1836
if (mw->matrix.rows == 0 || mw->matrix.columns == 0)
1840
XtWidgetToApplicationContext((Widget) mw),
1841
"editCell", "badIndex", "XbaeMatrix",
1842
"XbaeMatrix: Row or column out of bounds for EditCell.",
1848
* Attempt to commit the edit in the current cell. Return if we fail.
1850
if (!DoCommitEdit(mw, event))
1854
* Scroll the cell onto the screen
1856
xbaeMakeCellVisible(mw, row, column);
1859
* Fixed cells may not be editable.
1861
if (IS_FIXED(mw, row, column) && !mw->matrix.traverse_fixed)
1864
/* get the window of the new cell position */
1865
newWin = xbaeGetCellWindow(mw, &newWidget, row, column);
1868
* If we have an enterCellCallback, call it to see if the cell is
1871
call_data.map = True;
1872
call_data.doit = True;
1873
call_data.position = -1;
1874
call_data.pattern = NULL;
1876
XtVaGetValues(TextChild(mw),
1877
XmNoverwriteMode, &call_data.overwrite_mode,
1878
XmNautoFill, &call_data.auto_fill,
1879
XmNconvertCase, &call_data.convert_case,
1882
call_data.select_text = False;
1884
if (mw->matrix.enter_cell_callback)
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;
1894
XtCallCallbackList((Widget) mw, mw->matrix.enter_cell_callback,
1895
(XtPointer) & call_data);
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;
1905
* Unmap the textField to avoid flashing.
1907
if (XtIsManaged(TextChild(mw)) && XtIsRealized(TextChild(mw)))
1908
XtUnmapWidget(TextChild(mw));
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.
1917
xbaeRowColToXY(mw, row, column, &x, &y);
1920
userWidget = mw->matrix.cell_widgets[row][column];
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
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.
1953
* donato petrino, 1997/11/
1955
if ((oldWin != newWin ||
1956
mw->matrix.current_parent != newWidget) &&
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;
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.
1970
XtMoveWidget(TextChild(mw),
1971
x + mw->matrix.cell_shadow_thickness,
1972
y + mw->matrix.cell_shadow_thickness);
1978
* A user defined widget does not take into account the
1979
* cell_highlight_thickness, so we must do it!
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;
1991
* Compute the foreground and background of the text widget
1993
alt = mw->matrix.alt_row_count ?
1994
(row / mw->matrix.alt_row_count) % 2 : False;
1996
if (mw->matrix.colors)
1997
fgcolor = mw->matrix.colors[row][column];
1999
fgcolor = mw->manager.foreground;
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];
2009
bgcolor = mw->matrix.odd_row_background;
2011
bgcolor = mw->matrix.even_row_background;
2014
* If we're doing a drawCell, go ask the app what to put there.
2016
if (mw->matrix.draw_cell_callback)
2020
int width, height, depth;
2021
Pixel orig_bg, orig_fg;
2025
if (xbaeGetDrawCellValue(
2026
mw, row, column, &string, &pixmap, &mask, &width, &height,
2027
&bgcolor, &fgcolor, &depth) == XbaePixmap)
2030
* If we're showing a pixmap, we don't want the TextField.
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
2041
if (mw->matrix.reverse_select && mw->matrix.selected_cells &&
2042
mw->matrix.selected_cells[row][column])
2044
int new_fg = fgcolor;
2045
int new_bg = bgcolor;
2047
/* callback changed bg */
2048
if (orig_fg != fgcolor)
2052
/* callback changed fg */
2053
if (orig_bg != bgcolor)
2062
string = mw->matrix.cells ? mw->matrix.cells[row][column] : "";
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.
2071
if (!mw->matrix.cell_widgets[row][column])
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!
2079
XtRemoveCallback(TextChild(mw), XmNmodifyVerifyCallback,
2080
xbaeModifyVerifyCB, (XtPointer)mw);
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,
2100
XtVaSetValues(TextChild(mw), XmNvalue, string, NULL);
2102
XtAddCallback(TextChild(mw), XmNmodifyVerifyCallback,
2103
xbaeModifyVerifyCB, (XtPointer)mw);
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,
2118
* No need to do anything else if the text field is not going to
2125
* Manage and map the textField
2130
XtUnmanageChild(TextChild(mw));
2131
XtManageChild(userWidget);
2135
XtManageChild(TextChild(mw));
2137
if (XtIsRealized(TextChild(mw))
2142
XtMapWidget(TextChild(mw));
2144
else if (XtIsRealized(userWidget) && userWidget)
2145
XtMapWidget(userWidget);
2147
if (call_data.doit && !userWidget)
2150
* Set the insert position of the cursor
2154
int position = call_data.position;
2155
int length = strlen(string);
2157
if (event && (event->type == ButtonPress ||
2158
event->type == ButtonRelease ) &&
2159
position < 0 && mw->matrix.calc_cursor_position)
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.
2171
* The event must have occurred in a legal position
2172
* otherwise control wouldn't have made it here
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);
2181
if (call_data.select_text)
2182
XmTextSetSelection(TextChild(mw), 0, length,
2185
XmTextSetInsertionPosition(TextChild(mw), length);
2187
XmTextSetInsertionPosition(
2188
TextChild(mw), position > length ? length : position);
2194
* Matrix select_cell method
2197
xbaeSelectCell(mw, row, column)
2198
XbaeMatrixWidget mw;
2203
if (row >= mw->matrix.rows || row < 0 ||
2204
column >= mw->matrix.columns || column < 0)
2207
XtWidgetToApplicationContext((Widget) mw),
2208
"selectCell", "badIndex", "XbaeMatrix",
2209
"XbaeMatrix: Row or column out of bounds for SelectCell.",
2214
/* If no cells have been selected yet, allocate memory here */
2215
if (!mw->matrix.selected_cells)
2216
xbaeCopySelectedCells(mw);
2219
* Scroll the cell onto the screen
2221
visible = xbaeIsCellVisible(mw, row, column);
2223
if (mw->matrix.scroll_select && !visible)
2224
xbaeMakeCellVisible(mw, row, column);
2227
* If the cell is not already selected, select it and redraw it
2229
if (!mw->matrix.selected_cells[row][column])
2231
mw->matrix.selected_cells[row][column] = True;
2232
mw->matrix.num_selected_cells++;
2233
if (mw->matrix.scroll_select || visible)
2235
if (row >= TRAILING_VERT_ORIGIN(mw))
2236
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
2238
xbaeDrawCell(mw, row, column);
2240
if (row >= TRAILING_VERT_ORIGIN(mw))
2241
xbaeSetClipMask(mw, CLIP_NONE);
2247
* Matrix select_row method
2250
xbaeSelectRow(mw, row)
2251
XbaeMatrixWidget mw;
2255
Boolean fixed = False, trailing_fixed = False;
2257
unsigned int clip_reason = CLIP_NONE, save_clip = CLIP_NONE;
2259
if (row >= mw->matrix.rows || row < 0)
2262
XtWidgetToApplicationContext((Widget) mw),
2263
"selectRow", "badIndex", "XbaeMatrix",
2264
"XbaeMatrix: Row out of bounds for SelectRow.",
2269
/* If no cells have been selected yet, allocate memory here */
2270
if (!mw->matrix.selected_cells)
2271
xbaeCopySelectedCells(mw);
2273
visible = xbaeIsRowVisible(mw, row);
2275
* Scroll the row onto the screen
2277
if (mw->matrix.scroll_select)
2278
xbaeMakeRowVisible(mw, row);
2281
* If the row is not visible, there's no need to redraw - but, we do
2282
* need to update the selected cell resource
2284
if(!mw->matrix.scroll_select && !visible)
2286
for (j = 0; j < mw->matrix.columns; j++)
2287
if (!mw->matrix.selected_cells[row][j])
2289
mw->matrix.num_selected_cells++;
2290
mw->matrix.selected_cells[row][j] = True;
2296
* Establish any necessary clipping for redrawing the cells
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);
2305
* For each cell in the row, if the cell is not already selected,
2306
* select it and redraw it
2308
xbaeGetVisibleColumns(mw, &lc, &rc);
2309
for (j = 0; j < mw->matrix.columns; j++)
2311
if (!mw->matrix.selected_cells[row][j])
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)))
2319
if ((! fixed) && (j < (int)mw->matrix.fixed_columns))
2322
xbaeSetClipMask(mw, clip_reason | CLIP_FIXED_COLUMNS);
2324
else if (fixed && (j >= (int)mw->matrix.fixed_columns) &&
2325
(j < TRAILING_HORIZ_ORIGIN(mw)))
2328
xbaeSetClipMask(mw, clip_reason);
2330
else if ((! trailing_fixed) && (j >= TRAILING_HORIZ_ORIGIN(mw)))
2332
trailing_fixed = True;
2333
xbaeSetClipMask(mw, clip_reason |
2334
CLIP_TRAILING_FIXED_COLUMNS);
2337
xbaeClearCell(mw, row, j);
2338
xbaeDrawCell(mw, row, j);
2342
if (save_clip != mw->matrix.current_clip)
2343
xbaeSetClipMask(mw, CLIP_NONE);
2347
* Matrix select_column method
2350
xbaeSelectColumn(mw, column)
2351
XbaeMatrixWidget mw;
2355
Boolean once = False;
2357
unsigned int clip_reason = CLIP_NONE;
2359
if (column >= mw->matrix.columns || column < 0)
2362
XtWidgetToApplicationContext((Widget) mw),
2363
"selectColumn", "badIndex", "XbaeMatrix",
2364
"XbaeMatrix: Column out of bounds for SelectColumn.",
2369
/* If no cells have been selected yet, allocate memory here */
2370
if (!mw->matrix.selected_cells)
2371
xbaeCopySelectedCells(mw);
2374
* Scroll the column onto the screen
2376
if (mw->matrix.scroll_select)
2377
xbaeMakeColumnVisible(mw, column);
2380
* No need to redraw unless the column is visible
2382
if (!mw->matrix.scroll_select && !xbaeIsColumnVisible(mw, column))
2384
for (i = 0; i < mw->matrix.rows; i++)
2385
if (!mw->matrix.selected_cells[i][column])
2387
mw->matrix.num_selected_cells++;
2388
mw->matrix.selected_cells[i][column] = True;
2394
* Establish any necessary clipping for redrawing the cells
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);
2404
* For each cell in the column, if the cell is not already selected,
2405
* select it and redraw it
2407
xbaeGetVisibleRows(mw, &tr, &br);
2408
for (i = 0; i < mw->matrix.rows; i++)
2410
if (!mw->matrix.selected_cells[i][column])
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)))
2418
if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
2421
xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_ROWS);
2424
xbaeClearCell(mw, i, column);
2425
xbaeDrawCell(mw, i, column);
2430
if (once || (CLIP_NONE != clip_reason))
2431
xbaeSetClipMask(mw, CLIP_NONE);
2435
* Matrix deselect_all method
2439
XbaeMatrixWidget mw;
2443
register Boolean do_row, once = False;
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)
2450
xbaeGetVisibleCells(mw, &tr, &br, &lc, &rc);
2452
for (i = 0; i < mw->matrix.rows; i++)
2455
if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
2458
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
2460
for (j = 0; j < mw->matrix.columns; j++)
2462
if (mw->matrix.selected_cells[i][j])
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)))
2472
xbaeClearCell(mw, i, j);
2473
xbaeDrawCell(mw, i, j);
2481
xbaeSetClipMask(mw, CLIP_NONE);
2485
* Matrix select_all method
2489
XbaeMatrixWidget mw;
2493
register Boolean do_row, once = False;
2495
xbaeGetVisibleCells(mw, &tr, &br, &lc, &rc);
2497
if (!mw->matrix.selected_cells)
2498
xbaeCopySelectedCells(mw);
2500
for (i = 0; i < mw->matrix.rows; i++)
2503
if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
2506
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
2508
for (j = 0; j < mw->matrix.columns; j++)
2510
if (!mw->matrix.selected_cells[i][j])
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)))
2521
xbaeClearCell(mw, i, j);
2522
xbaeDrawCell(mw, i, j);
2531
xbaeSetClipMask(mw, CLIP_NONE);
2535
* Matrix deselect_cell method
2538
xbaeDeselectCell(mw, row, column)
2539
XbaeMatrixWidget mw;
2543
if (row >= mw->matrix.rows || row < 0 ||
2544
column > mw->matrix.columns - 1 || column < 0)
2547
XtWidgetToApplicationContext((Widget) mw),
2548
"deselectCell", "badIndex", "XbaeMatrix",
2549
"XbaeMatrix: Row or column out of bounds for DeselectCell.",
2554
if (!mw->matrix.selected_cells)
2557
if (mw->matrix.selected_cells[row][column])
2559
mw->matrix.num_selected_cells--;
2560
mw->matrix.selected_cells[row][column] = False;
2561
if (xbaeIsCellVisible(mw, row, column))
2563
if (row >= TRAILING_VERT_ORIGIN(mw))
2564
xbaeSetClipMask(mw, CLIP_TRAILING_FIXED_ROWS);
2566
xbaeClearCell(mw, row, column);
2567
xbaeDrawCell(mw, row, column);
2569
if (row >= TRAILING_VERT_ORIGIN(mw))
2570
xbaeSetClipMask(mw, CLIP_NONE);
2577
* Matrix deselect_row method
2580
xbaeDeselectRow(mw, row)
2581
XbaeMatrixWidget mw;
2585
Boolean fixed = False, trailing_fixed = False;
2586
unsigned int clip_reason = CLIP_NONE, save_clip;
2588
if (row >= mw->matrix.rows || row < 0)
2591
XtWidgetToApplicationContext((Widget) mw),
2592
"deselectRow", "badIndex", "XbaeMatrix",
2593
"XbaeMatrix: Row parameter out of bounds for DeselectRow.",
2598
if (!mw->matrix.selected_cells)
2602
* Establish any necessary clipping for redrawing the cells
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);
2611
* For each cell in the row, if the cell is selected,
2612
* deselect it and redraw it
2614
xbaeGetVisibleColumns(mw, &lc, &rc);
2615
for (j = 0; j < mw->matrix.columns; j++)
2617
if (mw->matrix.selected_cells[row][j])
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)))
2625
if ((! fixed) && (j < (int)mw->matrix.fixed_columns))
2628
xbaeSetClipMask(mw, clip_reason | CLIP_FIXED_COLUMNS);
2630
else if (fixed && (j >= (int)mw->matrix.fixed_columns) &&
2631
(j < TRAILING_HORIZ_ORIGIN(mw)))
2634
xbaeSetClipMask(mw, clip_reason);
2636
else if ((! trailing_fixed) && (j >= TRAILING_HORIZ_ORIGIN(mw)))
2638
trailing_fixed = True;
2639
xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_COLUMNS);
2642
xbaeClearCell(mw, row, j);
2643
xbaeDrawCell(mw, row, j);
2648
if (save_clip != mw->matrix.current_clip)
2649
xbaeSetClipMask(mw, CLIP_NONE);
2653
* Matrix deselect_column method
2656
xbaeDeselectColumn(mw, column)
2657
XbaeMatrixWidget mw;
2661
Boolean once = False;
2662
unsigned int clip_reason = CLIP_NONE;
2664
if (column >= mw->matrix.columns || column < 0)
2667
XtWidgetToApplicationContext((Widget) mw),
2668
"deselectColumn", "badIndex", "XbaeMatrix",
2669
"XbaeMatrix: Column parameter out of bounds for DeselectColumn.",
2674
if (!mw->matrix.selected_cells)
2678
* Establish any necessary clipping for redrawing the cells
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);
2688
* For each cell in the column, if the cell is selected,
2689
* deselect it and redraw it
2691
xbaeGetVisibleRows(mw, &tr, &br);
2692
for (i = 0; i < mw->matrix.rows; i++)
2694
if (mw->matrix.selected_cells[i][column])
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)))
2702
if ((! once) && (i >= TRAILING_VERT_ORIGIN(mw)))
2705
xbaeSetClipMask(mw, clip_reason | CLIP_TRAILING_FIXED_ROWS);
2708
xbaeClearCell(mw, i, column);
2709
xbaeDrawCell(mw, i, column);
2714
if (once || (CLIP_NONE != clip_reason))
2715
xbaeSetClipMask(mw, CLIP_NONE);
2719
* Matrix get_cell method
2722
xbaeGetCell(mw, row, column)
2723
XbaeMatrixWidget mw;
2728
if (row >= mw->matrix.rows || row < 0 ||
2729
column > mw->matrix.columns - 1 || column < 0)
2732
XtWidgetToApplicationContext((Widget) mw),
2733
"getCell", "badIndex", "XbaeMatrix",
2734
"XbaeMatrix: Row or column out of bounds for GetCell.",
2738
if (mw->matrix.draw_cell_callback)
2740
Pixel bgcolor, fgcolor;
2741
Pixmap pixmap, mask;
2742
int width, height, depth;
2744
if (xbaeGetDrawCellValue(mw, row, column, &value, &pixmap,
2745
&mask, &width, &height, &bgcolor, &fgcolor,
2746
&depth) == XbaePixmap)
2749
else if (!mw->matrix.cells)
2752
value = mw->matrix.cells[row][column];
2758
* Matrix commit_edit method
2761
#if NeedFunctionPrototypes
2762
xbaeCommitEdit(XbaeMatrixWidget mw, XEvent *event, Boolean unmap)
2764
xbaeCommitEdit(mw, event, unmap)
2765
XbaeMatrixWidget mw;
2772
if (!XtIsManaged(TextChild(mw)))
2776
* Attempt to commit the edit
2778
commit = DoCommitEdit(mw, event);
2781
* If the commit succeeded and we are supposed to unmap the textField,
2782
* then hide the textField and traverse out
2784
if (commit && unmap)
2786
XtUnmanageChild(TextChild(mw));
2787
XmProcessTraversal(TextChild(mw), XmTRAVERSE_RIGHT);
2794
* Matrix cancel_edit method
2797
#if NeedFunctionPrototypes
2798
xbaeCancelEdit(XbaeMatrixWidget mw, Boolean unmap)
2800
xbaeCancelEdit(mw, unmap)
2801
XbaeMatrixWidget mw;
2805
if (!XtIsManaged(TextChild(mw)))
2809
* If unmap is set, hide the textField and traverse out.
2813
XtUnmanageChild(TextChild(mw));
2814
XmProcessTraversal(TextChild(mw), XmTRAVERSE_RIGHT);
2818
* Don't unmap, just restore original contents
2820
else if (!mw->matrix.draw_cell_callback)
2822
XtVaSetValues(TextChild(mw),
2823
XmNvalue, (mw->matrix.cells ?
2824
mw->matrix.cells[mw->matrix.current_row]
2825
[mw->matrix.current_column] : ""),
2830
/* Ask the application what should be in the cell */
2832
Pixmap pixmap, mask;
2834
int width, height, depth;
2836
if (xbaeGetDrawCellValue(mw, mw->matrix.current_row,
2837
mw->matrix.current_column, &string,
2838
&pixmap, &mask, &width, &height,
2839
&bg, &fg, &depth) == XbaeString)
2841
XtVaSetValues(TextChild(mw), XmNvalue, string, NULL);
2846
* Matrix add_rows method
2849
xbaeAddRows(mw, position, rows, labels, colors, backgrounds, num_rows)
2850
XbaeMatrixWidget mw;
2858
Boolean haveVSB, haveHSB;
2861
* Do some error checking.
2865
if (position < 0 || position > mw->matrix.rows)
2868
XtWidgetToApplicationContext((Widget) mw),
2869
"addRows", "badPosition", "XbaeMatrix",
2870
"XbaeMatrix: Position out of bounds in AddRows.",
2875
haveVSB = XtIsManaged(VertScrollChild(mw));
2876
haveHSB = XtIsManaged(HorizScrollChild(mw));
2878
* If we add rows, and there is no drawCellCallback, we must allocate
2879
* the cells array to prevent potential disaster
2881
if (!mw->matrix.cells && !mw->matrix.draw_cell_callback)
2885
* Add the new rows into the internal cells/labels data structure.
2887
AddRowsToTable(mw, position, rows, labels, colors, backgrounds, num_rows);
2890
* Reconfig the VSB maximum.
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,
2904
* Call our cancel_edit method since the rows shifted underneath us
2906
(*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
2909
if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
2915
* Determine which part of the non clip region needs to be
2918
if (position >= (int)mw->matrix.fixed_rows)
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);
2929
if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
2930
mw->matrix.scrollbar_placement == XmTOP_RIGHT)
2931
y = HORIZ_SB_SPACE(mw);
2934
y += ROW_HEIGHT(mw) * position + COLUMN_LABEL_HEIGHT(mw);
2936
SETRECT(rect, 0, y, mw->core.width, mw->core.height);
2937
xbaeRedrawLabelsAndFixed(mw, &rect);
2938
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
2940
rect.x2 - rect.x1, rect.y2 - rect.y1, True);
2942
* If the scrollbars have just been mapped and there are
2943
* labels then the labels shift around. The labels need
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);
2962
* Matrix delete_rows method
2965
xbaeDeleteRows(mw, position, num_rows)
2966
XbaeMatrixWidget mw;
2975
* Do some error checking.
2979
if (position < 0 || position + num_rows > mw->matrix.rows)
2982
XtWidgetToApplicationContext((Widget) mw),
2983
"deleteRows", "badPosition", "XbaeMatrix",
2984
"XbaeMatrix: Position out of bounds in DeleteRows.",
2988
if (num_rows > (mw->matrix.rows - (int)mw->matrix.fixed_rows -
2989
(int)mw->matrix.trailing_fixed_rows))
2992
XtWidgetToApplicationContext((Widget) mw),
2993
"deleteRows", "tooMany", "XbaeMatrix",
2994
"XbaeMatrix: Attempting to delete too many rows in DeleteRows.",
2999
haveVSB = XtIsManaged(VertScrollChild(mw));
3000
haveHSB = XtIsManaged(HorizScrollChild(mw));
3003
* Delete the new rows from the internal cells/labels data structure.
3005
DeleteRowsFromTable(mw, position, num_rows);
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.
3011
XtVaGetValues(VertScrollChild(mw),
3015
max = mw->matrix.rows ?
3016
(mw->matrix.rows - (int) mw->matrix.fixed_rows -
3017
(int) mw->matrix.trailing_fixed_rows) : 1;
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,
3034
* Call our cancel_edit method since the rows shifted underneath us
3036
(*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
3039
if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
3045
* Determine which part of the non clip region needs to be
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)))
3053
if (src_y < LeftClip(mw)->core.height)
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,
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);
3068
if (XtIsManaged(RightClip(mw)))
3070
if (src_y < RightClip(mw)->core.height)
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,
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);
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);
3090
xbaeRedrawLabelsAndFixed(mw, &rect);
3092
y = (position - mw->matrix.fixed_rows) * ROW_HEIGHT(mw);
3094
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
3095
0, y, rect.x2, mw->core.height - y, True);
3097
* If the scrollbars have just been unmapped and there are
3098
* labels then the labels shift around. The labels need
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);
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.
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));
3125
* Matrix add_columns method.
3128
xbaeAddColumns(mw, position, columns, labels, widths, max_lengths,
3129
alignments, label_alignments, colors, backgrounds, num_columns)
3130
XbaeMatrixWidget mw;
3136
unsigned char *alignments;
3137
unsigned char *label_alignments;
3146
* Do some error checking.
3148
if (num_columns <= 0)
3150
if (position < 0 || position > mw->matrix.columns)
3153
XtWidgetToApplicationContext((Widget) mw),
3154
"addColumns", "badPosition", "XbaeMatrix",
3155
"XbaeMatrix: Position out of bounds in AddColumns.",
3162
XtWidgetToApplicationContext((Widget) mw),
3163
"addColumns", "noWidths", "XbaeMatrix",
3164
"XbaeMatrix: Must specify column widths in AddColumns.",
3170
* If we add columns, and there is no drawCellCallback, we must allocate
3171
* the cells array to prevent potential disaster
3173
if (!mw->matrix.cells && !mw->matrix.draw_cell_callback)
3176
haveVSB = XtIsManaged(VertScrollChild(mw));
3177
haveHSB = XtIsManaged(HorizScrollChild(mw));
3180
* Add the new rows into the internal cells/labels data structure.
3182
AddColumnsToTable(mw, position, columns, labels, widths, max_lengths,
3183
alignments, label_alignments, colors, backgrounds,
3187
* Reconfig the HSB maximum.
3189
XtVaSetValues(HorizScrollChild(mw),
3190
XmNmaximum, NON_FIXED_TOTAL_WIDTH(mw) ?
3191
NON_FIXED_TOTAL_WIDTH(mw) : 1,
3200
* Call our cancel_edit method since the columns shifted underneath us
3202
(*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
3205
if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
3211
* Determine which part of the non clip region needs to be
3214
if (position >= (int)mw->matrix.fixed_columns)
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);
3225
if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
3226
mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
3227
x = VERT_SB_SPACE(mw);
3230
x += COLUMN_POSITION(mw, position) + ROW_LABEL_WIDTH(mw);
3232
SETRECT(rect, x, 0, mw->core.width, mw->core.height);
3233
xbaeRedrawLabelsAndFixed(mw, &rect);
3234
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
3236
rect.x2 - rect.x1, rect.y2 - rect.y1, True);
3238
* If the scrollbars have just been mapped and there are
3239
* labels then the labels shift around. The labels need
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);
3260
* Matrix delete_columns method
3263
xbaeDeleteColumns(mw, position, num_columns)
3264
XbaeMatrixWidget mw;
3273
* Do some error checking.
3275
if (num_columns <= 0)
3277
if (position < 0 || position + num_columns > mw->matrix.columns)
3280
XtWidgetToApplicationContext((Widget) mw),
3281
"deleteColumns", "badPosition", "XbaeMatrix",
3282
"XbaeMatrix: Position out of bounds in DeleteColumns.",
3286
if (num_columns > (mw->matrix.columns - (int)mw->matrix.fixed_columns -
3287
(int)mw->matrix.trailing_fixed_columns))
3290
XtWidgetToApplicationContext((Widget) mw),
3291
"deleteColumns", "tooMany", "XbaeMatrix",
3292
"XbaeMatrix: Attempting to delete too many columns in DeleteColumns.",
3297
haveVSB = XtIsManaged(VertScrollChild(mw));
3298
haveHSB = XtIsManaged(HorizScrollChild(mw));
3300
maxlines = mw->matrix.column_label_maxlines;
3303
* Delete the new columns from the internal cells/labels data structure.
3305
DeleteColumnsFromTable(mw, position, num_columns);
3308
* Reconfig the HSB maximum. Reset the sliderSize to avoid warnings.
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,
3323
* Call our cancel_edit method since the columns shifted underneath us
3325
(*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.cancel_edit)
3328
if (!mw->matrix.disable_redisplay && XtIsRealized((Widget)mw))
3333
if (maxlines != mw->matrix.column_label_maxlines)
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
3341
XClearArea(XtDisplay(mw), XtWindow(mw),
3342
0, 0, 0 /*Full Width*/, 0 /*Full Height*/,
3347
* Determine which part of the non clip region needs to be
3350
if (position >= (int)mw->matrix.fixed_columns)
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);
3361
if (mw->matrix.scrollbar_placement == XmTOP_LEFT ||
3362
mw->matrix.scrollbar_placement == XmBOTTOM_LEFT)
3363
x = VERT_SB_SPACE(mw);
3366
x += COLUMN_POSITION(mw, position) + ROW_LABEL_WIDTH(mw);
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),
3373
mw->core.width, mw->core.height, True);
3374
xbaeRedrawLabelsAndFixed(mw, &rect);
3375
XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
3377
rect.x2 - rect.x1, rect.y2 - rect.y1, True);
3379
* If the scrollbars have just been unmapped and there are
3380
* labels then the labels shift around. The labels need
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);
3396
* Matrix set_row_colors method
3399
#if NeedFunctionPrototypes
3400
xbaeSetRowColors(XbaeMatrixWidget mw, int position, Pixel *colors,
3401
int num_colors, Boolean bg)
3403
xbaeSetRowColors(mw, position, colors, num_colors, bg)
3404
XbaeMatrixWidget mw;
3417
* Do some error checking.
3419
if (num_colors <= 0)
3421
if (position < 0 || position + num_colors > mw->matrix.rows)
3424
XtWidgetToApplicationContext((Widget) mw),
3425
"setRowColors", "badPosition", "XbaeMatrix",
3426
"XbaeMatrix: Position out of bounds or too many colors in SetRowColors.",
3432
* If we don't have any colors yet, malloc them, and initialize
3433
* unused entries to the appropriate color
3435
if ((!bg && !mw->matrix.colors) ||
3436
(bg && !mw->matrix.cell_background))
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++)
3446
for (i = position + num_colors; i < mw->matrix.rows; i++)
3447
for (j = 0; j < mw->matrix.columns; j++)
3451
xbaeCopyBackgrounds(mw);
3455
set = &mw->matrix.colors[0];
3457
set = &mw->matrix.cell_background[0];
3460
* Set each row to the appropriate color
3462
for (i = 0; i < num_colors; i++)
3463
for (j = 0; j < mw->matrix.columns; j++)
3464
set[i + position][j] = colors[i];
3466
if (XtIsRealized((Widget)mw))
3469
* Redraw all the visible non-fixed cells. We don't need to clear first
3470
* since only the color changed.
3474
ClipChild(mw)->core.width - 1, ClipChild(mw)->core.height - 1);
3475
xbaeRedrawCells(mw, &rect);
3478
* Redraw all the visible fixed cells (but not the labels).
3479
* We don't need to clear first since only the color changed.
3482
ROW_LABEL_WIDTH(mw), COLUMN_LABEL_HEIGHT(mw),
3483
mw->core.width - 1, mw->core.height - 1);
3484
xbaeRedrawLabelsAndFixed(mw, &rect);
3487
if (position <= mw->matrix.current_row &&
3488
position + num_colors > mw->matrix.current_row &&
3489
XtIsRealized(TextChild(mw)))
3492
XtVaSetValues(TextChild(mw), XmNbackground,
3493
mw->matrix.cell_background[mw->matrix.current_row]
3494
[mw->matrix.current_column],
3497
XtVaSetValues(TextChild(mw), XmNforeground,
3498
mw->matrix.colors[mw->matrix.current_row]
3499
[mw->matrix.current_column],
3505
* Matrix set_column_colors method
3508
#if NeedFunctionPrototypes
3509
xbaeSetColumnColors(XbaeMatrixWidget mw, int position, Pixel *colors,
3510
int num_colors, Boolean bg)
3512
xbaeSetColumnColors(mw, position, colors, num_colors, bg)
3513
XbaeMatrixWidget mw;
3526
* Do some error checking.
3528
if (num_colors <= 0)
3530
if (position < 0 || position + num_colors > mw->matrix.columns)
3533
XtWidgetToApplicationContext((Widget) mw),
3534
"setColumnColors", "badPosition", "XbaeMatrix",
3535
"XbaeMatrix: Position out of bounds or too many colors in SetColumnColors.",
3541
* If we don't have any colors yet, malloc them, and initialize
3542
* unused entries to foreground
3544
if ((!bg && !mw->matrix.colors) ||
3545
(bg && !mw->matrix.cell_background))
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++)
3555
for (i = 0; i < mw->matrix.rows; i++)
3556
for (j = position + num_colors; j < mw->matrix.columns; j++)
3560
xbaeCopyBackgrounds(mw);
3564
set = &mw->matrix.colors[0];
3566
set = &mw->matrix.cell_background[0];
3569
* Set each column to the appropriate color
3571
for (i = 0; i < mw->matrix.rows; i++)
3572
for (j = 0; j < num_colors; j++)
3573
set[i][j + position] = colors[j];
3575
if (XtIsRealized((Widget)mw))
3578
* Redraw all the visible non-fixed cells. We don't need to clear first
3579
* since only the color changed.
3583
ClipChild(mw)->core.width - 1, ClipChild(mw)->core.height - 1);
3584
xbaeRedrawCells(mw, &rect);
3587
* Redraw all the visible fixed cells (but not the labels).
3588
* We don't need to clear first since only the color changed.
3591
ROW_LABEL_WIDTH(mw), COLUMN_LABEL_HEIGHT(mw),
3592
mw->core.width - 1, mw->core.height - 1);
3593
xbaeRedrawLabelsAndFixed(mw, &rect);
3595
if (position <= mw->matrix.current_column &&
3596
position + num_colors > mw->matrix.current_column &&
3597
XtIsRealized(TextChild(mw)))
3600
XtVaSetValues(TextChild(mw), XmNbackground,
3601
mw->matrix.cell_background[mw->matrix.current_row]
3602
[mw->matrix.current_column],
3605
XtVaSetValues(TextChild(mw), XmNforeground,
3606
mw->matrix.colors[mw->matrix.current_row]
3607
[mw->matrix.current_column],
3613
* Matrix set_cell_color method
3616
#if NeedFunctionPrototypes
3617
xbaeSetCellColor(XbaeMatrixWidget mw, int row, int column, Pixel color, Boolean bg)
3619
xbaeSetCellColor(mw, row, column, color, bg)
3620
XbaeMatrixWidget mw;
3632
* Do some error checking.
3634
if (row >= mw->matrix.rows || row < 0 ||
3635
column >= mw->matrix.columns || column < 0)
3638
XtWidgetToApplicationContext((Widget) mw),
3639
"xbaeSetCellColor", "badIndex", "XbaeMatrix",
3640
"XbaeMatrix: Row or column out of bounds for xbaeSetCellColor.",
3646
* If we don't have any colors yet, malloc them and initialize them
3648
if ((!bg && !mw->matrix.colors) ||
3649
(bg && !mw->matrix.cell_background))
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++)
3661
xbaeCopyBackgrounds(mw);
3665
set = &mw->matrix.colors[0];
3667
set = &mw->matrix.cell_background[0];
3670
* Set the cell's color
3672
set[row][column] = color;
3674
if (XtIsRealized((Widget)mw))
3677
* Redraw the cell if it is visible
3679
if (xbaeIsCellVisible(mw, row, column))
3680
xbaeDrawCell(mw, row, column);
3682
if (row == mw->matrix.current_row &&
3683
column == mw->matrix.current_column && XtIsRealized(TextChild(mw)))
3686
XtVaSetValues(TextChild(mw), XmNbackground,
3687
mw->matrix.cell_background[mw->matrix.current_row]
3688
[mw->matrix.current_column],
3691
XtVaSetValues(TextChild(mw), XmNforeground,
3692
mw->matrix.colors[mw->matrix.current_row]
3693
[mw->matrix.current_column],