1 /*
2 * Copyright(c) 1992 Bell Communications Research, Inc. (Bellcore)
3 * Copyright(c) 1995-99 Andrew Lister
4 * All rights reserved
5 * Permission to use, copy, modify and distribute this material for
6 * any purpose and without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies, and that the name of Bellcore not be used in advertising
9 * or publicity pertaining to this material without the specific,
10 * prior written permission of an authorized representative of
11 * Bellcore.
12 *
13 * BELLCORE MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES, EX-
14 * PRESS OR IMPLIED, WITH RESPECT TO THE SOFTWARE, INCLUDING, BUT
15 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR ANY PARTICULAR PURPOSE, AND THE WARRANTY AGAINST IN-
17 * FRINGEMENT OF PATENTS OR OTHER INTELLECTUAL PROPERTY RIGHTS. THE
18 * SOFTWARE IS PROVIDED "AS IS", AND IN NO EVENT SHALL BELLCORE OR
19 * ANY OF ITS AFFILIATES BE LIABLE FOR ANY DAMAGES, INCLUDING ANY
20 * LOST PROFITS OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES RELAT-
21 * ING TO THE SOFTWARE.
22 *
23 * MatrixWidget Author: Andrew Wason, Bellcore, aw@bae.bellcore.com
24 *
25 * $Id: Create.c,v 1.1.2.3 2004/08/02 19:54:03 fnevgeny Exp $
26 */
27
28 /*
29 * Create.c created by Andrew Lister (28 Jan, 1996)
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <stdlib.h>
37
38 #include <Xm/Xm.h>
39 #include <Xbae/MatrixP.h>
40 #include <Xbae/Macros.h>
41 #include <Xbae/Utils.h>
42 #include <Xbae/Actions.h>
43 #include <Xm/ScrollBar.h>
44 #include <Xbae/Create.h>
45
46 static Pixmap createInsensitivePixmap P((XbaeMatrixWidget mw));
47
48 void
xbaeCopyBackground(widget,offset,value)49 xbaeCopyBackground(widget, offset, value)
50 Widget widget;
51 int offset;
52 XrmValue *value;
53 {
54 value->addr = (XtPointer)&(widget->core.background_pixel);
55 }
56
57
58 void
xbaeCopyForeground(widget,offset,value)59 xbaeCopyForeground(widget, offset, value)
60 Widget widget;
61 int offset;
62 XrmValue *value;
63 {
64 value->addr = (XtPointer)&(((XmManagerWidget)widget)->manager.foreground);
65 }
66
67 void
xbaeCopyDoubleClick(widget,offset,value)68 xbaeCopyDoubleClick(widget, offset, value)
69 Widget widget;
70 int offset;
71 XrmValue *value;
72 {
73 static int interval;
74
75 interval = XtGetMultiClickTime(XtDisplay(widget));
76 value->addr = (XtPointer)&interval;
77 }
78
79 void
xbaeCopyCells(mw)80 xbaeCopyCells(mw)
81 XbaeMatrixWidget mw;
82 {
83 String **copy = NULL;
84 int i, j;
85 Boolean empty_row;
86
87 if (mw->matrix.rows && mw->matrix.columns)
88 {
89 /*
90 * Malloc an array of row pointers
91 */
92 copy = (String **) XtMalloc(mw->matrix.rows * sizeof(String *));
93
94 /*
95 * Malloc an array of Strings for each row pointer
96 */
97 for (i = 0; i < mw->matrix.rows; i++)
98 copy[i] = (String *) XtMalloc(mw->matrix.columns * sizeof(String));
99
100 /*
101 * Create a bunch of "" cells if cells was NULL
102 */
103 if (!mw->matrix.cells)
104 {
105 for (i = 0; i < mw->matrix.rows; i++)
106 for (j = 0; j < mw->matrix.columns; j++)
107 copy[i][j] = XtNewString("");
108 }
109
110 /*
111 * Otherwise copy the table passed in
112 */
113 else
114 {
115 for (i = 0, empty_row = False; i < mw->matrix.rows; i++)
116 {
117 if (!empty_row && !mw->matrix.cells[i])
118 empty_row = True;
119 for (j = 0; j < mw->matrix.columns; j++)
120 {
121 if (empty_row || !mw->matrix.cells[i][j])
122 {
123 XtAppWarningMsg(
124 XtWidgetToApplicationContext((Widget)mw),
125 "copyCells", "badValue", "XbaeMatrix",
126 "XbaeMatrix: NULL entry found in cell table",
127 NULL, 0);
128 for (;j < mw->matrix.columns; j++)
129 copy[i][j] = XtNewString("");
130 }
131 else
132 copy[i][j] = XtNewString(mw->matrix.cells[i][j]);
133 }
134 }
135 }
136 }
137 mw->matrix.cells = copy;
138 }
139
140 #if CELL_WIDGETS
141 void
xbaeCopyCellWidgets(mw)142 xbaeCopyCellWidgets(mw)
143 XbaeMatrixWidget mw;
144 {
145 Widget **copy = NULL;
146 int i, j;
147
148 /*
149 * Malloc an array of row pointers
150 */
151 if (mw->matrix.rows && mw->matrix.columns)
152 {
153 copy = (Widget **) XtCalloc((Cardinal)mw->matrix.rows,
154 sizeof(Widget *));
155
156 for (i = 0; i < mw->matrix.rows; i++)
157 {
158 copy[i] = (Widget *) XtCalloc((Cardinal)mw->matrix.columns,
159 sizeof(Widget));
160 if (mw->matrix.cell_widgets)
161 for (j = 0; j < mw->matrix.columns; j++)
162 if (mw->matrix.cell_widgets[i][j])
163 copy[i][j] = mw->matrix.cell_widgets[i][j];
164 }
165 }
166 mw->matrix.cell_widgets = copy;
167 }
168 #endif
169
170 void
xbaeCopyCellShadowTypes(mw)171 xbaeCopyCellShadowTypes(mw)
172 XbaeMatrixWidget mw;
173 {
174 unsigned char **copy = NULL;
175 int i, j;
176
177 if (mw->matrix.rows && mw->matrix.columns)
178 {
179 copy = (unsigned char **) XtMalloc(mw->matrix.rows *
180 sizeof(unsigned char*));
181
182 for (i = 0; i < mw->matrix.rows; i++)
183 copy[i] = (unsigned char*) XtMalloc(mw->matrix.columns *
184 sizeof(unsigned char));
185
186 for (i = 0; i < mw->matrix.rows; i++)
187 for (j = 0; j < mw->matrix.columns; j++)
188 {
189 if (!mw->matrix.cell_shadow_types[i][j])
190
191 {
192 XtAppWarningMsg(
193 XtWidgetToApplicationContext((Widget) mw),
194 "xbaeCopyCellShadowTypes", "badValue", "XbaeMatrix",
195 "XbaeMatrix: NULL entry found in cellShadowTypes array",
196 NULL, 0);
197 copy[i][j] = XmSHADOW_OUT;
198 }
199 else
200 copy[i][j] = mw->matrix.cell_shadow_types[i][j];
201 }
202 }
203 mw->matrix.cell_shadow_types = copy;
204 }
205
206 void
xbaeCopyRowShadowTypes(mw)207 xbaeCopyRowShadowTypes(mw)
208 XbaeMatrixWidget mw;
209 {
210 unsigned char *copy = NULL;
211 int i;
212
213 if (mw->matrix.rows)
214 {
215 copy = (unsigned char *) XtMalloc(mw->matrix.rows *
216 sizeof(unsigned char));
217
218 for (i = 0; i < mw->matrix.rows; i++)
219 if (!mw->matrix.row_shadow_types[i])
220 {
221 XtAppWarningMsg(
222 XtWidgetToApplicationContext((Widget) mw),
223 "xbaeCopyRowShadowTypes", "badValue", "XbaeMatrix",
224 "XbaeMatrix: NULL entry found in rowShadowTypes array",
225 NULL, 0);
226 copy[i] = XmSHADOW_OUT;
227 }
228 else
229 copy[i] = mw->matrix.row_shadow_types[i];
230 }
231 mw->matrix.row_shadow_types = copy;
232 }
233
234 void
xbaeCopyColumnShadowTypes(mw)235 xbaeCopyColumnShadowTypes(mw)
236 XbaeMatrixWidget mw;
237 {
238 unsigned char *copy = NULL;
239 int i;
240
241 if (mw->matrix.columns)
242 {
243 copy = (unsigned char *) XtMalloc(mw->matrix.columns *
244 sizeof(unsigned char));
245
246 for (i = 0; i < mw->matrix.columns; i++)
247 if (!mw->matrix.column_shadow_types[i])
248 {
249 XtAppWarningMsg(
250 XtWidgetToApplicationContext((Widget) mw),
251 "xbaeCopyColumnShadowTypes", "badValue", "XbaeMatrix",
252 "XbaeMatrix: NULL entry found in columnShadowTypes array",
253 NULL, 0);
254 copy[i] = XmSHADOW_OUT;
255 }
256 else
257 copy[i] = mw->matrix.column_shadow_types[i];
258 }
259 mw->matrix.column_shadow_types = copy;
260 }
261
262
263 void
xbaeCopyCellUserData(mw)264 xbaeCopyCellUserData(mw)
265 XbaeMatrixWidget mw;
266 {
267 XtPointer **copy = NULL;
268 int i, j;
269
270 if (mw->matrix.rows && mw->matrix.columns)
271 {
272 copy = (XtPointer **) XtMalloc(mw->matrix.rows * sizeof(XtPointer*));
273
274 for (i = 0; i < mw->matrix.rows; i++)
275 copy[i] = (XtPointer*) XtMalloc(mw->matrix.columns *
276 sizeof(XtPointer));
277
278 for (i = 0; i < mw->matrix.rows; i++)
279 for (j = 0; j < mw->matrix.columns; j++)
280 copy[i][j] = mw->matrix.cell_user_data[i][j];
281 }
282 mw->matrix.cell_user_data = copy;
283 }
284
285 void
xbaeCopyRowUserData(mw)286 xbaeCopyRowUserData(mw)
287 XbaeMatrixWidget mw;
288 {
289 XtPointer *copy = NULL;
290 int i;
291
292 if (mw->matrix.rows)
293 {
294 copy = (XtPointer *) XtMalloc(mw->matrix.rows * sizeof(XtPointer));
295
296 for (i = 0; i < mw->matrix.rows; i++)
297 copy[i] = mw->matrix.row_user_data[i];
298 }
299 mw->matrix.row_user_data = copy;
300 }
301
302 void
xbaeCopyColumnUserData(mw)303 xbaeCopyColumnUserData(mw)
304 XbaeMatrixWidget mw;
305 {
306 XtPointer *copy = NULL;
307 int i;
308
309 if (mw->matrix.columns)
310 {
311 copy = (XtPointer *) XtMalloc(mw->matrix.columns * sizeof(XtPointer));
312
313 for (i = 0; i < mw->matrix.columns; i++)
314 copy[i] = mw->matrix.column_user_data[i];
315 }
316 mw->matrix.column_user_data = copy;
317 }
318
319 void
xbaeCopyRowLabels(mw)320 xbaeCopyRowLabels(mw)
321 XbaeMatrixWidget mw;
322 {
323 String *copy = NULL;
324 int i;
325 Boolean empty_label;
326
327 if (mw->matrix.rows)
328 {
329 copy = (String *) XtMalloc(mw->matrix.rows * sizeof(String));
330
331 for (i = 0, empty_label = False; i < mw->matrix.rows; i++)
332 if (empty_label || !mw->matrix.row_labels[i])
333 {
334 XtAppWarningMsg(
335 XtWidgetToApplicationContext((Widget) mw),
336 "copyRowLabels", "badValue", "XbaeMatrix",
337 "XbaeMatrix: NULL entry found in rowLabels array",
338 NULL, 0);
339 copy[i] = XtNewString("");
340 empty_label = True;
341 }
342 else
343 copy[i] = XtNewString(mw->matrix.row_labels[i]);
344 }
345 mw->matrix.row_labels = copy;
346 }
347
348 void
xbaeCopyColumnLabels(mw)349 xbaeCopyColumnLabels(mw)
350 XbaeMatrixWidget mw;
351 {
352 String *copy = NULL;
353 int i;
354 Boolean empty_column;
355
356 if (mw->matrix.columns)
357 {
358 copy = (String *) XtMalloc(mw->matrix.columns * sizeof(String));
359
360 mw->matrix.column_label_lines = (ColumnLabelLines)
361 XtMalloc(mw->matrix.columns * sizeof(ColumnLabelLinesRec));
362
363 for (i = 0, empty_column = False; i < mw->matrix.columns; i++)
364 if (empty_column || !mw->matrix.column_labels[i])
365 {
366 XtAppWarningMsg(
367 XtWidgetToApplicationContext((Widget) mw),
368 "copyColumnLabels", "badValue", "XbaeMatrix",
369 "XbaeMatrix: NULL entry found in columnLabels array",
370 NULL, 0);
371 copy[i] = XtNewString("");
372 empty_column = True;
373 xbaeParseColumnLabel(
374 copy[i], &mw->matrix.column_label_lines[i]);
375 }
376 else
377 {
378 copy[i] = XtNewString(mw->matrix.column_labels[i]);
379 xbaeParseColumnLabel(mw->matrix.column_labels[i],
380 &mw->matrix.column_label_lines[i]);
381 }
382
383 /*
384 * Determine max number of lines in column labels
385 */
386 mw->matrix.column_label_maxlines =
387 mw->matrix.column_label_lines[0].lines;
388
389 for (i = 1; i < mw->matrix.columns; i++)
390 if (mw->matrix.column_label_lines[i].lines >
391 mw->matrix.column_label_maxlines)
392 mw->matrix.column_label_maxlines =
393 mw->matrix.column_label_lines[i].lines;
394 }
395 mw->matrix.column_labels = copy;
396 }
397
398 void
xbaeCopyColumnWidths(mw)399 xbaeCopyColumnWidths(mw)
400 XbaeMatrixWidget mw;
401 {
402 short *copy = NULL;
403 int i;
404 Boolean bad = False;
405
406 if (mw->matrix.columns)
407 {
408 copy = (short *) XtMalloc(mw->matrix.columns * sizeof(short));
409
410 for (i = 0; i < mw->matrix.columns; i++)
411 {
412 if (!bad && mw->matrix.column_widths[i] == BAD_WIDTH)
413 {
414 bad = True;
415 XtAppWarningMsg(
416 XtWidgetToApplicationContext((Widget) mw),
417 "copyColumnWidths", "tooShort", "XbaeMatrix",
418 "XbaeMatrix: Column widths array is too short",
419 NULL, 0);
420 copy[i] = 1;
421 }
422 else if (bad)
423 copy[i] = 1;
424 else
425 copy[i] = mw->matrix.column_widths[i];
426 }
427 }
428 mw->matrix.column_widths = copy;
429 }
430
431 void
xbaeCopyColumnMaxLengths(mw)432 xbaeCopyColumnMaxLengths(mw)
433 XbaeMatrixWidget mw;
434 {
435 int *copy = NULL;
436 int i;
437 Boolean bad = False;
438
439 if (mw->matrix.columns)
440 {
441 copy = (int *) XtMalloc(mw->matrix.columns * sizeof(int));
442
443 for (i = 0; i < mw->matrix.columns; i++)
444 {
445 if (!bad && mw->matrix.column_max_lengths[i] == BAD_MAXLENGTH)
446 {
447 bad = True;
448 XtAppWarningMsg(
449 XtWidgetToApplicationContext((Widget) mw),
450 "copyColumnMaxLengths", "tooShort", "XbaeMatrix",
451 "XbaeMatrix: Column max lengths array is too short",
452 NULL, 0);
453 copy[i] = 1;
454 }
455 else if (bad)
456 copy[i] = 1;
457 else
458 copy[i] = mw->matrix.column_max_lengths[i];
459 }
460 }
461 mw->matrix.column_max_lengths = copy;
462 }
463
464 void
xbaeCopyColumnAlignments(mw)465 xbaeCopyColumnAlignments(mw)
466 XbaeMatrixWidget mw;
467 {
468 unsigned char *copy = NULL;
469 int i;
470 Boolean bad = False;
471
472 if (mw->matrix.columns)
473 {
474 copy = (unsigned char *) XtMalloc(mw->matrix.columns *
475 sizeof(unsigned char));
476
477 for (i = 0; i < mw->matrix.columns; i++)
478 {
479 if (!bad && mw->matrix.column_alignments[i] == BAD_ALIGNMENT)
480 {
481 bad = True;
482 XtAppWarningMsg(
483 XtWidgetToApplicationContext((Widget) mw),
484 "copyColumnAlignments", "tooShort", "XbaeMatrix",
485 "XbaeMatrix: Column alignments array is too short",
486 NULL, 0);
487 copy[i] = XmALIGNMENT_BEGINNING;
488 }
489 else if (bad)
490 copy[i] = XmALIGNMENT_BEGINNING;
491 else
492 copy[i] = mw->matrix.column_alignments[i];
493 }
494 }
495 mw->matrix.column_alignments = copy;
496 }
497
498 void
xbaeCopyColumnButtonLabels(mw)499 xbaeCopyColumnButtonLabels(mw)
500 XbaeMatrixWidget mw;
501 {
502 Boolean *copy = NULL;
503 int i;
504
505 if (mw->matrix.columns)
506 {
507 copy = (Boolean *) XtMalloc(mw->matrix.columns *
508 sizeof(Boolean));
509
510 for (i = 0; i < mw->matrix.columns; i++)
511 {
512 copy[i] = mw->matrix.column_button_labels[i];
513 }
514 }
515 mw->matrix.column_button_labels = copy;
516 }
517
518 void
xbaeCopyRowButtonLabels(mw)519 xbaeCopyRowButtonLabels(mw)
520 XbaeMatrixWidget mw;
521 {
522 Boolean *copy = NULL;
523 int i;
524
525 if (mw->matrix.rows)
526 {
527 copy = (Boolean *) XtMalloc(mw->matrix.rows *
528 sizeof(Boolean));
529
530 for (i = 0; i < mw->matrix.rows; i++)
531 {
532 copy[i] = mw->matrix.row_button_labels[i];
533 }
534 }
535 mw->matrix.row_button_labels = copy;
536 }
537
538 void
xbaeCopyColumnLabelAlignments(mw)539 xbaeCopyColumnLabelAlignments(mw)
540 XbaeMatrixWidget mw;
541 {
542 unsigned char *copy = NULL;
543 int i;
544 Boolean bad = False;
545
546 if (mw->matrix.columns)
547 {
548 copy = (unsigned char *) XtMalloc(mw->matrix.columns *
549 sizeof(unsigned char));
550
551 for (i = 0; i < mw->matrix.columns; i++)
552 {
553 if (!bad &&
554 mw->matrix.column_label_alignments[i] == BAD_ALIGNMENT)
555 {
556 bad = True;
557 XtAppWarningMsg(
558 XtWidgetToApplicationContext((Widget) mw),
559 "copyColumnLabelAlignments", "tooShort",
560 "XbaeMatrix",
561 "XbaeMatrix: Column label alignments array is too short",
562 NULL, 0);
563 copy[i] = XmALIGNMENT_BEGINNING;
564 }
565 else if (bad)
566 copy[i] = XmALIGNMENT_BEGINNING;
567 else
568 copy[i] = mw->matrix.column_label_alignments[i];
569 }
570 }
571 mw->matrix.column_label_alignments = copy;
572 }
573
574 void
xbaeCopyColors(mw)575 xbaeCopyColors(mw)
576 XbaeMatrixWidget mw;
577 {
578 Pixel **copy = NULL;
579 int i, j;
580 Boolean badrow = False;
581 Boolean badcol;
582
583
584 if (mw->matrix.rows && mw->matrix.columns)
585 {
586 /*
587 * Malloc an array of row pointers
588 */
589 copy = (Pixel **) XtMalloc(mw->matrix.rows * sizeof(Pixel *));
590
591 /*
592 * Malloc an array of Pixels for each row pointer
593 */
594 for (i = 0; i < mw->matrix.rows; i++)
595 copy[i] = (Pixel *) XtMalloc(mw->matrix.columns * sizeof(Pixel));
596
597 if (!mw->matrix.colors)
598 {
599 for (i = 0; i < mw->matrix.rows; i++)
600 for (j = 0; j < mw->matrix.columns; j++)
601 copy[i][j] = mw->manager.foreground;
602 }
603 else for (i = 0; i < mw->matrix.rows; i++)
604 {
605 if (!badrow && !mw->matrix.colors[i]) {
606 badrow = True;
607 XtAppWarningMsg(
608 XtWidgetToApplicationContext((Widget)mw),
609 "copyCellColors", "tooShort",
610 "XbaeMatrix",
611 "XbaeMatrix: Cell ColorPixelTable is too short",
612 NULL, 0);
613 }
614 badcol = badrow;
615 for (j = 0; j < mw->matrix.columns; j++)
616 {
617 if (badcol || mw->matrix.colors[i][j] == BAD_PIXEL)
618 {
619 badcol = True;
620 if (j > 0)
621 copy[i][j] = copy[i][j-1] ;
622 else if (i > 0)
623 copy[i][j] = copy[i-1][j] ;
624 else
625 copy[i][j] = mw->manager.foreground;
626 }
627 else
628 {
629 copy[i][j] = mw->matrix.colors[i][j];
630 }
631 }
632 }
633 }
634 mw->matrix.colors = copy;
635 }
636
637 void
xbaeCopyBackgrounds(mw)638 xbaeCopyBackgrounds(mw)
639 XbaeMatrixWidget mw;
640 {
641 Pixel **copy = NULL;
642 int i, j;
643 Boolean badrow = False;
644 Boolean badcol;
645
646 if (mw->matrix.rows && mw->matrix.columns)
647 {
648 /*
649 * Malloc an array of row pointers
650 */
651 copy = (Pixel **) XtMalloc(mw->matrix.rows * sizeof(Pixel *));
652
653 /*
654 * Malloc an array of Pixels for each row pointer
655 */
656 for (i = 0; i < mw->matrix.rows; i++)
657 copy[i] = (Pixel *) XtMalloc(mw->matrix.columns * sizeof(Pixel));
658
659 if (!mw->matrix.cell_background)
660 {
661 for (i = 0; i < mw->matrix.rows; i++)
662 {
663 Boolean alt = (mw->matrix.alt_row_count &&
664 i >= (int)mw->matrix.fixed_rows) ? (
665 ((i - (int)mw->matrix.fixed_rows) /
666 mw->matrix.alt_row_count) % 2) : False;
667
668 /*
669 * Assign the even and odd row colours appropriately. These
670 * will be a copy of the core->background if they have not
671 * been explicitly set but if they have, we want to
672 * preserve the colours as they appear now
673 */
674 for (j = 0; j < mw->matrix.columns; j++)
675 copy[i][j] = (alt ? mw->matrix.odd_row_background :
676 mw->matrix.even_row_background);
677 }
678 }
679 else for (i = 0; i < mw->matrix.rows; i++)
680 {
681 if (!badrow && !mw->matrix.cell_background[i]) {
682 badrow = True;
683 XtAppWarningMsg(
684 XtWidgetToApplicationContext((Widget)mw),
685 "copyCellColors", "tooShort",
686 "XbaeMatrix",
687 "XbaeMatrix: Cell BackgroundPixelTable is too short",
688 NULL, 0);
689 }
690 badcol = badrow;
691 for (j = 0; j < mw->matrix.columns; j++)
692 {
693 if (badcol || mw->matrix.cell_background[i][j] == BAD_PIXEL)
694 {
695 badcol = True;
696 if (j > 0)
697 copy[i][j] = copy[i][j-1] ;
698 else if (i > 0)
699 copy[i][j] = copy[i-1][j] ;
700 else
701 copy[i][j] = mw->core.background_pixel;
702 }
703 else
704 {
705 copy[i][j] = mw->matrix.cell_background[i][j];
706 }
707 }
708 }
709 }
710 mw->matrix.cell_background = copy;
711 }
712
713 /*
714 * Copy the selectedCells resource. Create a 2D array of Booleans to
715 * represent selected cells if it is NULL.
716 */
717 void
xbaeCopySelectedCells(mw)718 xbaeCopySelectedCells(mw)
719 XbaeMatrixWidget mw;
720 {
721 Boolean **copy = NULL;
722 int i, j;
723
724 if (mw->matrix.rows && mw->matrix.columns)
725 {
726 /*
727 * Malloc an array of row pointers
728 */
729 mw->matrix.num_selected_cells = 0;
730 copy = (Boolean **) XtMalloc(mw->matrix.rows * sizeof(Boolean *));
731
732 /*
733 * Malloc an array of Booleans for each row pointer
734 */
735 for (i = 0; i < mw->matrix.rows; i++)
736 copy[i] = (Boolean *) XtCalloc(mw->matrix.columns,
737 sizeof(Boolean));
738
739 /*
740 * If selected_cells is not NULL, copy the table passed in
741 */
742 if (mw->matrix.selected_cells)
743 for (i = 0; i < mw->matrix.rows; i++)
744 for (j = 0; j < mw->matrix.columns; j++)
745 {
746 copy[i][j] = mw->matrix.selected_cells[i][j];
747 if (mw->matrix.selected_cells[i][j])
748 mw->matrix.num_selected_cells++;
749 }
750 }
751 mw->matrix.selected_cells = copy;
752 }
753
754 #if XmVersion >= 1002
755 /*
756 * Copy the highlightedCells resource. Create a 2D array of Booleans to
757 * represent highlighted cells if it is NULL.
758 */
759 void
xbaeCopyHighlightedCells(mw)760 xbaeCopyHighlightedCells(mw)
761 XbaeMatrixWidget mw;
762 {
763 unsigned char **copy = NULL;
764 int i, j;
765
766 if (mw->matrix.rows && mw->matrix.columns)
767 {
768 /*
769 * Malloc an array of row pointers
770 */
771 copy = (unsigned char **) XtMalloc(mw->matrix.rows *
772 sizeof(Boolean *));
773
774 /*
775 * Malloc an array of Booleans for each row pointer
776 */
777 for (i = 0; i < mw->matrix.rows; i++)
778 copy[i] = (unsigned char *) XtCalloc(mw->matrix.columns,
779 sizeof(Boolean));
780
781 /*
782 * If highlighted_cells is not NULL, copy the table passed in
783 */
784 if (mw->matrix.highlighted_cells)
785 for (i = 0; i < mw->matrix.rows; i++)
786 for (j = 0; j < mw->matrix.columns; j++)
787 copy[i][j] = mw->matrix.highlighted_cells[i][j];
788 }
789 mw->matrix.highlighted_cells = copy;
790 }
791 #endif
792
793 /*
794 * Create a matrix of Pixels
795 */
796 void
xbaeCreateColors(mw)797 xbaeCreateColors(mw)
798 XbaeMatrixWidget mw;
799 {
800 int i;
801
802 if (mw->matrix.rows && mw->matrix.columns)
803 {
804 /*
805 * Malloc an array of row pointers
806 */
807 mw->matrix.colors = (Pixel **) XtMalloc(mw->matrix.rows *
808 sizeof(Pixel *));
809
810 /*
811 * Malloc an array of Pixels for each row pointer
812 */
813 for (i = 0; i < mw->matrix.rows; i++)
814 mw->matrix.colors[i] = (Pixel *) XtMalloc(mw->matrix.columns *
815 sizeof(Pixel));
816 }
817 else
818 mw->matrix.colors = NULL;
819 }
820
821 /*
822 * Create a pixmap to be used for drawing the matrix contents when
823 * XmNsensitive is set to False
824 */
825 static Pixmap
createInsensitivePixmap(mw)826 createInsensitivePixmap(mw)
827 XbaeMatrixWidget mw;
828 {
829 static char stippleBits[] = { 0x01, 0x02 };
830 static Pixmap *stipple = NULL;
831 Display *dpy = XtDisplay(mw);
832 Screen *scr = XtScreen (mw);
833 int i;
834 int maxScreens = ScreenCount(dpy);
835
836 if (!stipple)
837 {
838 stipple = (Pixmap *) XtMalloc(maxScreens*sizeof(Pixmap));
839 for (i = 0 ; i < maxScreens ; i++)
840 stipple[i] = XCreatePixmapFromBitmapData(
841 dpy, RootWindow(dpy,i), stippleBits, 2, 2, 0, 1, 1);
842 }
843 for (i = 0; i < maxScreens; i++)
844 {
845 if (ScreenOfDisplay(dpy, i) == scr)
846 return stipple[i];
847 }
848 return (Pixmap)NULL;
849 }
850
851 void
xbaeCreateGridLineGC(mw)852 xbaeCreateGridLineGC(mw)
853 XbaeMatrixWidget mw;
854 {
855 XGCValues values;
856 XtGCMask mask = GCForeground | GCBackground;
857
858 values.foreground = mw->matrix.grid_line_color;
859 values.background = mw->manager.foreground;
860
861 /*
862 * GC for drawing grid lines
863 */
864 mw->matrix.grid_line_gc = XtGetGC((Widget) mw, mask, &values);
865
866 /*
867 * GC for drawing grid lines with clipping
868 */
869 mw->matrix.cell_grid_line_gc = XCreateGC(XtDisplay(mw),
870 GC_PARENT_WINDOW(mw),
871 mask, &values);
872 }
873
874 void
xbaeCreateDrawGC(mw)875 xbaeCreateDrawGC(mw)
876 XbaeMatrixWidget mw;
877 {
878 XGCValues values;
879 unsigned long mask = GCForeground | GCStipple;
880
881 /*
882 * GC for drawing cells. We create it instead of using a cached one,
883 * since the foreground may change frequently.
884 */
885 values.foreground = mw->manager.foreground;
886 values.stipple = createInsensitivePixmap(mw);
887 /* font id isn't used for fontsets */
888 if (mw->matrix.font_struct) {
889 mask |= GCFont;
890 values.font = mw->matrix.fid;
891 }
892 mw->matrix.draw_gc = XCreateGC(XtDisplay(mw),
893 GC_PARENT_WINDOW(mw),
894 mask, &values);
895 }
896
897 void
xbaeCreatePixmapGC(mw)898 xbaeCreatePixmapGC(mw)
899 XbaeMatrixWidget mw;
900 {
901 XGCValues values;
902 unsigned long mask = GCForeground | GCGraphicsExposures | GCStipple;
903
904 values.foreground = mw->manager.foreground;
905 values.graphics_exposures = False;
906 values.stipple = createInsensitivePixmap(mw);
907
908 mw->matrix.pixmap_gc = XCreateGC(XtDisplay(mw),
909 GC_PARENT_WINDOW(mw),
910 mask, &values);
911 }
912
913 void
xbaeCreateLabelGC(mw)914 xbaeCreateLabelGC(mw)
915 XbaeMatrixWidget mw;
916 {
917 XGCValues values;
918 unsigned long mask = GCForeground | GCStipple;
919
920 /*
921 * GC for drawing labels
922 */
923 values.foreground = mw->manager.foreground;
924 values.stipple = createInsensitivePixmap(mw);
925 /* font id isn't used for fontsets */
926 if (mw->matrix.label_font_struct) {
927 mask |= GCFont;
928 values.font = mw->matrix.label_fid;
929 }
930 mw->matrix.label_gc = XCreateGC(XtDisplay(mw),
931 GC_PARENT_WINDOW(mw),
932 mask, &values);
933 }
934
935 void
xbaeCreateLabelClipGC(mw)936 xbaeCreateLabelClipGC(mw)
937 XbaeMatrixWidget mw;
938 {
939 XGCValues values;
940 unsigned long mask = GCForeground | GCStipple;
941
942 /*
943 * GC for drawing labels with clipping.
944 */
945 values.foreground = mw->manager.foreground;
946 values.stipple = createInsensitivePixmap(mw);
947 /* font id isn't used for fontsets */
948 if (mw->matrix.label_font_struct) {
949 mask |= GCFont;
950 values.font = mw->matrix.label_fid;
951 }
952 mw->matrix.label_clip_gc = XCreateGC(XtDisplay(mw),
953 GC_PARENT_WINDOW(mw),
954 mask, &values);
955 }
956
957 void
xbaeCreateTopShadowClipGC(mw)958 xbaeCreateTopShadowClipGC(mw)
959 XbaeMatrixWidget mw;
960 {
961 XGCValues values;
962 XtGCMask mask = GCForeground | GCBackground;
963
964 /*
965 * GC for drawing top shadow inside cells with clipping.
966 */
967 values.foreground = mw->manager.top_shadow_color;
968 values.background = mw->manager.foreground;
969
970 if (mw->manager.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
971 {
972 mask |= GCFillStyle | GCTile;
973 values.fill_style = FillTiled;
974 values.tile = mw->manager.top_shadow_pixmap;
975 }
976 mw->matrix.cell_top_shadow_clip_gc = XCreateGC(
977 XtDisplay(mw), GC_PARENT_WINDOW(mw), mask, &values);
978
979 mask |= GCFunction;
980 values.function = GXxor;
981 mw->matrix.resize_top_shadow_gc = XtGetGC(
982 (Widget) mw, mask, &values);
983 }
984
985 void
xbaeCreateBottomShadowClipGC(mw)986 xbaeCreateBottomShadowClipGC(mw)
987 XbaeMatrixWidget mw;
988 {
989 XGCValues values;
990 XtGCMask mask = GCForeground | GCBackground;
991
992 /*
993 * GC for drawing bottom shadow inside cells with clipping.
994 */
995 values.foreground = mw->manager.bottom_shadow_color;
996 values.background = mw->manager.foreground;
997
998 if (mw->manager.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP)
999 {
1000 mask |= GCFillStyle | GCTile;
1001 values.fill_style = FillTiled;
1002 values.tile = mw->manager.bottom_shadow_pixmap;
1003 }
1004 mw->matrix.cell_bottom_shadow_clip_gc = XCreateGC(
1005 XtDisplay(mw), GC_PARENT_WINDOW(mw), mask, &values);
1006
1007 mask |= GCFunction;
1008 values.function = GXxor;
1009 mw->matrix.resize_bottom_shadow_gc = XtGetGC(
1010 (Widget) mw, mask, &values);
1011 }
1012
1013 static short
xbaeGetFontWidth(font_struct)1014 xbaeGetFontWidth(font_struct)
1015 XFontStruct *font_struct;
1016 {
1017 short width;
1018 unsigned long fp;
1019 unsigned char char_idx;
1020
1021 /*
1022 * From the XmText man page: If the em-space value is
1023 * available, it is used. If not, the width of the numeral "0"
1024 * is used. If this is not available, the maximum width is used.
1025 */
1026 if (XGetFontProperty(font_struct, XA_QUAD_WIDTH, &fp) && fp != 0) {
1027 width = (short) fp;
1028 } else {
1029 if (font_struct->min_char_or_byte2 <= '0' &&
1030 font_struct->max_char_or_byte2 >= '0' &&
1031 font_struct->per_char) {
1032 char_idx = '0' - font_struct->min_char_or_byte2;
1033 width = font_struct->per_char[char_idx].width;
1034 } else {
1035 width = font_struct->max_bounds.width;
1036 }
1037 }
1038
1039 /* last safety check */
1040 if (width <= 0) {
1041 width = 1;
1042 }
1043
1044 return width;
1045 }
1046
1047 void
xbaeNewFont(mw)1048 xbaeNewFont(mw)
1049 XbaeMatrixWidget mw;
1050 {
1051 XmFontContext context;
1052 XmFontListEntry font_list_entry;
1053 XmFontType type;
1054 XtPointer fontp;
1055
1056 /*
1057 * Make a private copy of the FontList
1058 */
1059 mw->matrix.font_list = XmFontListCopy(mw->matrix.font_list);
1060
1061 /*
1062 * Get XmFontListEntry from FontList
1063 */
1064 if (!XmFontListInitFontContext(&context, mw->matrix.font_list))
1065 XtAppErrorMsg(
1066 XtWidgetToApplicationContext((Widget) mw),
1067 "newFont", "badFont", "XbaeMatrix",
1068 "XbaeMatrix: XmFontListInitFontContext failed, bad fontList",
1069 NULL, 0);
1070
1071 if ((font_list_entry = XmFontListNextEntry(context)) == NULL)
1072 XtAppErrorMsg(
1073 XtWidgetToApplicationContext((Widget) mw),
1074 "newFont", "badFont", "XbaeMatrix",
1075 "XbaeMatrix: XmFontListNextEntry failed, no next fontList",
1076 NULL, 0);
1077
1078 fontp = XmFontListEntryGetFont(font_list_entry, &type);
1079
1080
1081 if (type == XmFONT_IS_FONTSET)
1082 {
1083 XFontSetExtents *extents;
1084
1085 mw->matrix.font_set = (XFontSet)fontp;
1086 mw->matrix.font_struct = (XFontStruct*)NULL;
1087
1088 extents = XExtentsOfFontSet(mw->matrix.font_set);
1089
1090 mw->matrix.font_width = extents->max_logical_extent.width;
1091 mw->matrix.font_height = extents->max_logical_extent.height;
1092 mw->matrix.font_y = extents->max_logical_extent.y;
1093 mw->matrix.fid = 0; /* not used for fontsets */
1094 }
1095 else
1096 {
1097 XFontStruct *font_struct = (XFontStruct *)fontp;
1098
1099 mw->matrix.font_set = (XFontSet)NULL;
1100 mw->matrix.font_struct = font_struct;
1101
1102 mw->matrix.font_width = xbaeGetFontWidth(font_struct);
1103 mw->matrix.font_height = (font_struct->max_bounds.descent +
1104 font_struct->max_bounds.ascent);
1105 mw->matrix.font_y = -font_struct->max_bounds.ascent;
1106 mw->matrix.fid = font_struct->fid;
1107 }
1108
1109 XmFontListFreeFontContext(context);
1110 }
1111
1112 void
xbaeNewLabelFont(mw)1113 xbaeNewLabelFont(mw)
1114 XbaeMatrixWidget mw;
1115 {
1116 XmFontContext context;
1117 XmFontListEntry font_list_entry;
1118 XmFontType type;
1119 XtPointer fontp;
1120
1121 /*
1122 * Make a private copy of the FontList
1123 */
1124 mw->matrix.label_font_list = XmFontListCopy(mw->matrix.label_font_list);
1125
1126 /*
1127 * Get XmFontListEntry from FontList
1128 */
1129 if (!XmFontListInitFontContext(&context, mw->matrix.label_font_list))
1130 XtAppErrorMsg(
1131 XtWidgetToApplicationContext((Widget) mw),
1132 "newFont", "badLabelFont", "XbaeMatrix",
1133 "XbaeMatrix: XmFontListInitFontContext failed, bad labelFontList",
1134 NULL, 0);
1135
1136 if ((font_list_entry = XmFontListNextEntry(context)) == NULL)
1137 XtAppErrorMsg(
1138 XtWidgetToApplicationContext((Widget) mw),
1139 "newFont", "badLabelFont", "XbaeMatrix",
1140 "XbaeMatrix: XmFontListNextEntry failed, no next fontList",
1141 NULL, 0);
1142
1143 fontp = XmFontListEntryGetFont(font_list_entry, &type);
1144
1145 if (type == XmFONT_IS_FONTSET)
1146 {
1147 XFontSetExtents *extents;
1148
1149 mw->matrix.label_font_set = (XFontSet)fontp;
1150 mw->matrix.label_font_struct = (XFontStruct*)NULL;
1151
1152 extents = XExtentsOfFontSet(mw->matrix.label_font_set);
1153
1154 mw->matrix.label_font_width = extents->max_logical_extent.width;
1155 mw->matrix.label_font_height = extents->max_logical_extent.height;
1156 mw->matrix.label_font_y = extents->max_logical_extent.y;
1157 mw->matrix.label_fid = 0; /* not used for fontsets */
1158 }
1159 else
1160 {
1161 XFontStruct *font_struct = (XFontStruct *)fontp;
1162
1163 mw->matrix.label_font_set = (XFontSet)NULL;
1164 mw->matrix.label_font_struct = font_struct;
1165
1166 mw->matrix.label_font_width = xbaeGetFontWidth(font_struct);
1167 mw->matrix.label_font_height = (font_struct->max_bounds.descent +
1168 font_struct->max_bounds.ascent);
1169 mw->matrix.label_font_y = -font_struct->max_bounds.ascent;
1170 mw->matrix.label_fid = font_struct->fid;
1171 }
1172
1173 XmFontListFreeFontContext(context);
1174 }
1175
1176 void
xbaeFreeCells(mw)1177 xbaeFreeCells(mw)
1178 XbaeMatrixWidget mw;
1179 {
1180 int i, j;
1181
1182 if (!mw->matrix.cells)
1183 return;
1184
1185 /*
1186 * Free each cell in a row, then free the row and go to the next one
1187 */
1188 for (i = 0; i < mw->matrix.rows; i++)
1189 {
1190 for (j = 0; j < mw->matrix.columns; j++)
1191 XtFree((XtPointer) mw->matrix.cells[i][j]);
1192 XtFree((XtPointer) mw->matrix.cells[i]);
1193 }
1194
1195 /*
1196 * Free the array of row pointers
1197 */
1198 XtFree((XtPointer) mw->matrix.cells);
1199 mw->matrix.cells = NULL;
1200 }
1201
1202 #if CELL_WIDGETS
1203 void
xbaeFreeCellWidgets(mw)1204 xbaeFreeCellWidgets(mw)
1205 XbaeMatrixWidget mw;
1206 {
1207 int i, j;
1208
1209 if (!mw->matrix.cell_widgets)
1210 return;
1211
1212 /*
1213 * Free each cell in a row, then free the row and go to the next one
1214 */
1215 for (i = 0; i < mw->matrix.rows; i++)
1216 {
1217 for (j = 0; j < mw->matrix.columns; j++)
1218 XtFree((XtPointer) mw->matrix.cell_widgets[i][j]);
1219 XtFree((XtPointer) mw->matrix.cell_widgets[i]);
1220 }
1221
1222 /*
1223 * Free the array of row pointers
1224 */
1225 XtFree((XtPointer) mw->matrix.cell_widgets);
1226 mw->matrix.cell_widgets = NULL;
1227 }
1228 #endif
1229
1230 void
xbaeFreeRowLabels(mw)1231 xbaeFreeRowLabels(mw)
1232 XbaeMatrixWidget mw;
1233 {
1234 int i;
1235
1236 if (!mw->matrix.row_labels)
1237 return;
1238
1239 for (i = 0; i < mw->matrix.rows; i++)
1240 XtFree((XtPointer) mw->matrix.row_labels[i]);
1241
1242 XtFree((XtPointer) mw->matrix.row_labels);
1243 mw->matrix.row_labels = NULL;
1244 }
1245
1246 void
xbaeFreeColumnLabels(mw)1247 xbaeFreeColumnLabels(mw)
1248 XbaeMatrixWidget mw;
1249 {
1250 int i;
1251
1252 if (!mw->matrix.column_labels)
1253 return;
1254
1255 for (i = 0; i < mw->matrix.columns; i++)
1256 {
1257 XtFree((XtPointer) mw->matrix.column_labels[i]);
1258 XtFree((XtPointer) mw->matrix.column_label_lines[i].lengths);
1259 }
1260
1261 XtFree((XtPointer) mw->matrix.column_label_lines);
1262 XtFree((XtPointer) mw->matrix.column_labels);
1263 mw->matrix.column_labels = NULL;
1264 }
1265
1266
1267 void
xbaeFreeColors(mw)1268 xbaeFreeColors(mw)
1269 XbaeMatrixWidget mw;
1270 {
1271 int i;
1272
1273 if (!mw->matrix.colors)
1274 return;
1275
1276 /*
1277 * Free each row of Pixels
1278 */
1279 for (i = 0; i < mw->matrix.rows; i++)
1280 XtFree((XtPointer) mw->matrix.colors[i]);
1281
1282 /*
1283 * Free the array of row pointers
1284 */
1285 XtFree((XtPointer) mw->matrix.colors);
1286 mw->matrix.colors = NULL;
1287 }
1288
1289 void
xbaeFreeBackgrounds(mw)1290 xbaeFreeBackgrounds(mw)
1291 XbaeMatrixWidget mw;
1292 {
1293 int i;
1294
1295 if (!mw->matrix.cell_background)
1296 return;
1297
1298 /*
1299 * Free each row of Pixels
1300 */
1301 for (i = 0; i < mw->matrix.rows; i++)
1302 XtFree((XtPointer) mw->matrix.cell_background[i]);
1303
1304 /*
1305 * Free the array of row pointers
1306 */
1307 XtFree((XtPointer) mw->matrix.cell_background);
1308 mw->matrix.cell_background = NULL;
1309 }
1310
1311 void
xbaeFreeSelectedCells(mw)1312 xbaeFreeSelectedCells(mw)
1313 XbaeMatrixWidget mw;
1314 {
1315 int i;
1316
1317 /*
1318 * Free each row of XtPointer pointers
1319 */
1320 if (!mw->matrix.selected_cells)
1321 return;
1322
1323 for (i = 0; i < mw->matrix.rows; i++)
1324 XtFree((XtPointer) mw->matrix.selected_cells[i]);
1325
1326 /*
1327 * Free the array of row pointers
1328 */
1329 XtFree((XtPointer) mw->matrix.selected_cells);
1330 mw->matrix.selected_cells = NULL;
1331 }
1332
1333 #if XmVersion >= 1002
1334 void
xbaeFreeHighlightedCells(mw)1335 xbaeFreeHighlightedCells(mw)
1336 XbaeMatrixWidget mw;
1337 {
1338 int i;
1339
1340 if (!mw->matrix.highlighted_cells)
1341 return;
1342
1343 /*
1344 * Free each row of XtPointer pointers
1345 */
1346 for (i = 0; i < mw->matrix.rows; i++)
1347 XtFree((XtPointer) mw->matrix.highlighted_cells[i]);
1348
1349 /*
1350 * Free the array of row pointers
1351 */
1352 XtFree((XtPointer) mw->matrix.highlighted_cells);
1353 mw->matrix.highlighted_cells = NULL;
1354 }
1355 #endif
1356
1357 void
xbaeFreeCellUserData(mw)1358 xbaeFreeCellUserData(mw)
1359 XbaeMatrixWidget mw;
1360 {
1361 if (mw->matrix.cell_user_data)
1362 {
1363 int i;
1364
1365 /*
1366 * Free each row of Booleans
1367 */
1368 for (i = 0; i < mw->matrix.rows; i++)
1369 XtFree((XtPointer) mw->matrix.cell_user_data[i]);
1370
1371 /*
1372 * Free the array of row pointers
1373 */
1374 XtFree((XtPointer) mw->matrix.cell_user_data);
1375 }
1376 mw->matrix.cell_user_data = NULL;
1377 }
1378
1379
1380 void
xbaeFreeCellShadowTypes(mw)1381 xbaeFreeCellShadowTypes(mw)
1382 XbaeMatrixWidget mw;
1383 {
1384 if (mw->matrix.cell_shadow_types)
1385 {
1386 int i;
1387
1388 /*
1389 * Free each row of unsigned char pointers
1390 */
1391 for (i = 0; i < mw->matrix.rows; i++)
1392 XtFree((XtPointer) mw->matrix.cell_shadow_types[i]);
1393
1394 /*
1395 * Free the array of row pointers
1396 */
1397 XtFree((XtPointer) mw->matrix.cell_shadow_types);
1398 }
1399 mw->matrix.cell_shadow_types = NULL;
1400 }
1401
1402