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: Matrix.c,v 1.1.2.2 2004/07/02 21:53:02 fnevgeny Exp $
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <X11/StringDefs.h>
36 #include <X11/Xlib.h>
37 #include <Xm/XmP.h>
38 #include <Xm/AtomMgr.h>
39 #include <Xm/ScrollBar.h>
40 #include <Xm/TextF.h>
41 #if XmVersion > 1001
42 #include <Xm/DrawP.h>
43 #include <Xm/DragIcon.h>
44 #include <Xm/DragC.h>
45 #endif
46 #include <Xbae/Clip.h>
47 #include <Xbae/MatrixP.h>
48 #include <Xbae/Converters.h>
49 #include <Xbae/ScrollMgr.h>
50 #include <Xbae/Actions.h>
51 #include <Xbae/Create.h>
52 #include <Xbae/Methods.h>
53 #include <Xbae/Utils.h>
54 #include <Xbae/Shadow.h>
55
56 #ifndef XlibSpecificationRelease
57 #define XrmPermStringToQuark XrmStringToQuark
58 #endif
59
60 /*
61 * Translations for Matrix (these will also be used by the Clip child).
62 */
63 static char defaultTranslations[] =
64 "<Btn1Up> : DefaultAction()\n\
65 <Btn1Down> : DefaultAction() EditCell(Pointer)\n\
66 Shift<Btn2Down> : ResizeColumns()\n\
67 <Btn2Down> : ProcessDrag()\n\
68 <Btn1Motion> : HandleMotion()";
69
70 /*
71 * Default translations for XmNtextTranslations resource
72 */
73 static char default_text_translations[] =
74 "#override\n\
75 Shift ~Ctrl ~Meta ~Alt <Key>Tab : EditCell(Left)\n\
76 ~Ctrl ~Meta ~Alt <Key>Tab : EditCell(Right)\n\
77 <Key>osfUp : EditCell(Up)\n\
78 <Key>osfDown : EditCell(Down)\n\
79 <Key>osfActivate : CommitEdit(False)\n\
80 ~Shift ~Meta ~Alt <Key>Return : CommitEdit(False)\n\
81 Ctrl <Key>osfCancel : CancelEdit(False)\n\
82 Shift Ctrl ~Meta ~Alt <Key>Tab : TraversePrev()\n\
83 Ctrl ~Meta ~Alt <Key>Tab : TraverseNext()\n\
84 <Key>osfPageDown : PageDown()\n\
85 <Key>osfPageUp : PageUp()";
86
87
88 #define offset(field) XtOffsetOf(XbaeMatrixRec, field)
89
90 static XtResource resources[] =
91 {
92 #ifdef ALLOW_COLUMN_RESIZE
93 {XmNallowColumnResize, XmCColumnResize, XmRBoolean, sizeof(Boolean),
94 offset(matrix.allow_column_resize), XmRImmediate, (XtPointer) True},
95 #else
96 {XmNallowColumnResize, XmCColumnResize, XmRBoolean, sizeof(Boolean),
97 offset(matrix.allow_column_resize), XmRImmediate, (XtPointer) False},
98 #endif
99 {XmNaltRowCount, XmCAltRowCount, XmRInt, sizeof(int),
100 offset(matrix.alt_row_count), XmRImmediate, (XtPointer) 1},
101
102 {XmNboldLabels, XmCBoldLabels, XmRBoolean, sizeof(Boolean),
103 offset(matrix.bold_labels), XmRImmediate, (XtPointer) False},
104
105 {XmNbuttonLabels, XmCButtonLabels, XmRBoolean, sizeof(Boolean),
106 offset(matrix.button_labels), XmRImmediate, (XtPointer) False},
107
108 {XmNbuttonLabelBackground, XmCColor, XmRPixel, sizeof(Pixel),
109 offset(matrix.button_label_background), XmRCallProc,
110 (XtPointer)xbaeCopyBackground},
111
112 {XmNcalcCursorPosition, XmCCalcCursorPosition, XmRBoolean, sizeof(Boolean),
113 offset(matrix.calc_cursor_position), XmRImmediate, (XtPointer) False},
114
115 {XmNcellBackgrounds, XmCColors, XmRPixelTable, sizeof(Pixel **),
116 offset(matrix.cell_background), XmRImmediate, (XtPointer) NULL},
117
118 {XmNcellHighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
119 sizeof(Dimension), offset(matrix.cell_highlight_thickness),
120 XmRImmediate, (XtPointer) 2},
121
122 {XmNcellMarginHeight, XmCMarginHeight, XmRVerticalDimension,
123 sizeof(Dimension), offset(matrix.cell_margin_height),
124 XmRImmediate, (XtPointer) 3},
125
126 {XmNcellMarginWidth, XmCMarginWidth, XmRHorizontalDimension,
127 sizeof(Dimension), offset(matrix.cell_margin_width),
128 XmRImmediate, (XtPointer) 3},
129
130 {XmNcellShadowThickness, XmCShadowThickness, XmRDimension,
131 sizeof(Dimension), offset(matrix.cell_shadow_thickness),
132 XmRImmediate, (XtPointer) 1},
133
134 {XmNcellShadowType, XmCShadowType, XmRShadowType,
135 sizeof(unsigned char), offset(matrix.cell_shadow_type), XmRImmediate,
136 (XtPointer) XmSHADOW_OUT},
137
138 {XmNcellShadowTypes, XmCCellShadowTypes, XmRShadowTypeTable,
139 sizeof(unsigned char**), offset(matrix.cell_shadow_types), XmRImmediate,
140 (XtPointer) NULL},
141
142 {XmNcellUserData, XmCCellUserData, XmRUserDataTable,
143 sizeof(XtPointer**), offset(matrix.cell_user_data), XmRImmediate,
144 (XtPointer) NULL},
145 #if CELL_WIDGETS
146 {XmNcellWidgets, XmCCellWidgets, XmRWidgetTable,
147 sizeof(Widget **), offset(matrix.cell_widgets), XmRImmediate,
148 (XtPointer) NULL},
149 #endif
150 {XmNcells, XmCCells, XmRCellTable, sizeof(String **),
151 offset(matrix.cells), XmRImmediate, NULL},
152
153 {XmNclipWindow, XmCClipWindow, XmRWidget, sizeof(Widget),
154 offset(matrix.clip_window), XmRImmediate, NULL},
155
156 {XmNcolors, XmCColors, XmRPixelTable, sizeof(Pixel **),
157 offset(matrix.colors), XmRImmediate, (XtPointer) NULL},
158
159 {XmNcolumnAlignments, XmCAlignments, XmRAlignmentArray,
160 sizeof(unsigned char *), offset(matrix.column_alignments),
161 XmRImmediate, (XtPointer) NULL},
162
163 {XmNcolumnButtonLabels, XmCButtonLabels, XmRBooleanArray,
164 sizeof(Boolean*), offset(matrix.column_button_labels),
165 XmRImmediate, (XtPointer) NULL},
166
167 {XmNcolumnLabelAlignments, XmCAlignments, XmRAlignmentArray,
168 sizeof(unsigned char *), offset(matrix.column_label_alignments),
169 XmRImmediate, (XtPointer) NULL},
170
171 {XmNcolumnLabelColor, XmCColor, XmRPixel, sizeof(Pixel),
172 offset(matrix.column_label_color), XmRCallProc,
173 (XtPointer)xbaeCopyForeground},
174
175 {XmNcolumnLabels, XmCLabels, XmRStringArray, sizeof(String *),
176 offset(matrix.column_labels), XmRImmediate, NULL},
177
178 {XmNcolumnMaxLengths, XmCColumnMaxLengths, XmRMaxLengthArray,
179 sizeof(int *), offset(matrix.column_max_lengths),
180 XmRImmediate, NULL},
181
182 {XmNcolumnShadowTypes, XmCShadowTypes, XmRShadowTypeArray,
183 sizeof(unsigned char*), offset(matrix.column_shadow_types), XmRImmediate,
184 (XtPointer) NULL},
185
186 {XmNcolumnUserData, XmCUserDatas, XmRUserDataArray,
187 sizeof(XtPointer*), offset(matrix.column_user_data), XmRImmediate,
188 (XtPointer) NULL},
189
190 {XmNcolumnWidths, XmCColumnWidths, XmRWidthArray, sizeof(short *),
191 offset(matrix.column_widths), XmRImmediate, NULL},
192
193 {XmNcolumns, XmCColumns, XmRInt, sizeof(int),
194 offset(matrix.columns), XmRImmediate, (XtPointer) 1},
195
196 {XmNdefaultActionCallback,XmCCallback,XmRCallback,sizeof(XtCallbackList),
197 offset(matrix.default_action_callback),XmRCallback,NULL },
198
199 {XmNdoubleClickInterval, XmCDoubleClickInterval, XmRInt, sizeof(int),
200 offset(matrix.double_click_interval), XmRCallProc,
201 (XtPointer)xbaeCopyDoubleClick },
202
203 {XmNdrawCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
204 offset(matrix.draw_cell_callback), XmRCallback, NULL},
205
206 {XmNenterCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
207 offset(matrix.enter_cell_callback), XmRCallback, NULL},
208
209 {XmNevenRowBackground, XmCBackground, XmRPixel, sizeof(Pixel),
210 offset(matrix.even_row_background), XmRCallProc,
211 (XtPointer)xbaeCopyBackground},
212
213 {XmNfill, XmCFill, XmRBoolean, sizeof(Boolean),
214 offset(matrix.fill), XmRImmediate, (XtPointer) False},
215
216 {XmNfixedColumns, XmCFixedColumns, XmRDimension, sizeof(Dimension),
217 offset(matrix.fixed_columns), XmRImmediate, (XtPointer) 0},
218
219 {XmNfixedRows, XmCFixedRows, XmRDimension, sizeof(Dimension),
220 offset(matrix.fixed_rows), XmRImmediate, (XtPointer) 0},
221
222 {XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList),
223 offset(matrix.font_list), XmRString, (XtPointer) "fixed"},
224
225 {XmNgridLineColor, XmCColor, XmRPixel, sizeof(Pixel),
226 offset(matrix.grid_line_color), XmRCallProc,
227 (XtPointer)xbaeCopyForeground},
228
229 {XmNgridType, XmCGridType, XmRGridType,
230 sizeof(unsigned char), offset(matrix.grid_type),
231 XmRImmediate, (XtPointer)XmGRID_CELL_LINE},
232
233 #if XmVersion >= 1002
234 {XmNhighlightedCells, XmCHighlightedCells, XmRHighlightTable,
235 sizeof(unsigned char **), offset(matrix.highlighted_cells),
236 XmRImmediate, (XtPointer) NULL},
237 #endif
238
239 {XmNhorizontalScrollBar, XmCHorizontalScrollBar, XmRWidget, sizeof(Widget),
240 offset(matrix.horizontal_sb), XmRImmediate, NULL},
241
242 {XmNhorizontalScrollBarDisplayPolicy, XmCMatrixScrollBarDisplayPolicy,
243 XmRMatrixScrollBarDisplayPolicy, sizeof(unsigned char),
244 offset(matrix.hsb_display_policy), XmRImmediate,
245 (XtPointer) XmDISPLAY_AS_NEEDED},
246
247 {XmNlabelActivateCallback, XmCCallback, XmRCallback,
248 sizeof(XtCallbackList), offset(matrix.label_activate_callback),
249 XmRCallback, NULL},
250
251 {XmNlabelFont, XmCFontList, XmRFontList, sizeof(XmFontList),
252 offset(matrix.label_font_list), XmRString, (XtPointer)NULL },
253
254 {XmNleaveCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
255 offset(matrix.leave_cell_callback), XmRCallback, NULL},
256
257 {XmNleftColumn, XmCLeftColumn, XmRInt, sizeof(int),
258 offset(matrix.left_column), XmRImmediate, (XtPointer) 0 },
259
260 {XmNmodifyVerifyCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
261 offset(matrix.modify_verify_callback), XmRCallback, NULL},
262
263 {XmNoddRowBackground, XmCBackground, XmRPixel, sizeof(Pixel),
264 offset(matrix.odd_row_background), XmRCallProc,
265 (XtPointer)xbaeCopyBackground},
266
267 #if XmVersion > 1001
268 {XmNprocessDragCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
269 offset(matrix.process_drag_callback), XmRCallback, NULL},
270 #endif
271
272 /* Resize callback resource. Added by mjs */
273 {XmNresizeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
274 offset(matrix.resize_callback), XmRCallback, NULL},
275
276 {XmNresizeColumnCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
277 offset(matrix.resize_column_callback), XmRCallback, NULL},
278
279 {XmNreverseSelect, XmCReverseSelect, XmRBoolean, sizeof(Boolean),
280 offset(matrix.reverse_select), XmRImmediate, (XtPointer) False},
281
282 {XmNrowButtonLabels, XmCButtonLabels, XmRBooleanArray,
283 sizeof(Boolean*), offset(matrix.row_button_labels),
284 XmRImmediate, (XtPointer) NULL},
285
286 {XmNrowLabelAlignment, XmCAlignment, XmRAlignment, sizeof(unsigned char),
287 offset(matrix.row_label_alignment),
288 XmRImmediate, (XtPointer) XmALIGNMENT_END},
289
290 {XmNrowLabelColor, XmCColor, XmRPixel, sizeof(Pixel),
291 offset(matrix.row_label_color), XmRCallProc,
292 (XtPointer)xbaeCopyForeground },
293
294 {XmNrowLabelWidth, XmCRowLabelWidth, XmRShort, sizeof(short),
295 offset(matrix.row_label_width), XmRImmediate, (XtPointer) 0},
296
297 {XmNrowLabels, XmCLabels, XmRStringArray, sizeof(String *),
298 offset(matrix.row_labels), XmRImmediate, NULL},
299
300 {XmNrowShadowTypes, XmCShadowTypes, XmRShadowTypeArray,
301 sizeof(unsigned char*), offset(matrix.row_shadow_types), XmRImmediate,
302 (XtPointer) NULL},
303
304 {XmNrowUserData, XmCUserDatas, XmRUserDataArray,
305 sizeof(XtPointer*), offset(matrix.row_user_data), XmRImmediate,
306 (XtPointer) NULL},
307
308 {XmNrows, XmCRows, XmRInt, sizeof(int),
309 offset(matrix.rows), XmRImmediate, (XtPointer) 1},
310
311 {XmNscrollBarPlacement, XmCScrollBarPlacement, XmRScrollBarPlacement,
312 sizeof(unsigned char), offset(matrix.scrollbar_placement), XmRImmediate,
313 (XtPointer) XmBOTTOM_RIGHT },
314
315 {XmNselectCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
316 offset(matrix.select_cell_callback), XmRCallback, NULL},
317
318 {XmNselectScrollVisible, XmCSelectScrollVisible, XmRBoolean,
319 sizeof(Boolean), offset(matrix.scroll_select), XmRImmediate,
320 (XtPointer) True},
321
322 {XmNselectedBackground, XmCColor, XmRPixel, sizeof(Pixel),
323 offset(matrix.selected_background), XmRCallProc,
324 (XtPointer)xbaeCopyForeground},
325
326 {XmNselectedCells, XmCSelectedCells, XmRBooleanTable, sizeof(Boolean **),
327 offset(matrix.selected_cells), XmRImmediate, (XtPointer) NULL},
328
329 {XmNselectedForeground, XmCColor, XmRPixel, sizeof(Pixel),
330 offset(matrix.selected_foreground), XmRCallProc,
331 (XtPointer)xbaeCopyBackground},
332
333 {XmNselectionPolicy, XmCSelectionPolicy, XmRSelectionPolicy,
334 sizeof(unsigned char), offset(matrix.selection_policy), XmRImmediate,
335 XmSINGLE_SELECT},
336
337 /* Override Manager default */
338 {XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension,
339 sizeof(Dimension), XtOffsetOf(XmManagerRec, manager.shadow_thickness),
340 XmRImmediate, (XtPointer) 2},
341
342 {XmNshadowType, XmCShadowType, XmRShadowType,
343 sizeof(unsigned char), offset(matrix.shadow_type), XmRImmediate,
344 (XtPointer) XmSHADOW_IN},
345
346 {XmNshowArrows, XmCShowArrows, XmRBoolean, sizeof(Boolean),
347 offset(matrix.show_arrows), XmRImmediate, (XtPointer) False},
348
349 {XmNspace, XmCSpace, XmRHorizontalDimension, sizeof(Dimension),
350 offset(matrix.space), XmRImmediate, (XtPointer) 4},
351
352 {XmNtextBackground, XmCTextBackground, XmRPixel, sizeof(Pixel),
353 offset(matrix.text_background), XmRCallProc,
354 (XtPointer)xbaeCopyBackground},
355
356 {XmNtextField, XmCTextField, XmRWidget, sizeof(Widget),
357 offset(matrix.text_field), XmRImmediate, NULL},
358
359 {XmNtextShadowThickness, XmCTextShadowThickness, XmRDimension,
360 sizeof(Dimension), offset(matrix.text_shadow_thickness), XmRImmediate,
361 (XtPointer) 0},
362
363 {XmNtextTranslations, XmCTranslations, XmRTranslationTable,
364 sizeof(XtTranslations), offset(matrix.text_translations),
365 XmRString, (XtPointer) default_text_translations},
366
367 {XmNtopRow, XmCTopRow, XmRInt, sizeof(int),
368 offset(matrix.top_row), XmRImmediate, (XtPointer) 0},
369
370 {XmNtrailingAttachedBottom, XmCTrailingAttachedBottom, XmRBoolean, sizeof(Boolean),
371 offset(matrix.trailing_attached_bottom), XmRImmediate, (XtPointer) False},
372
373 {XmNtrailingAttachedRight, XmCTrailingAttachedRight, XmRBoolean, sizeof(Boolean),
374 offset(matrix.trailing_attached_right), XmRImmediate, (XtPointer) False},
375
376 {XmNtrailingFixedColumns, XmCTrailingFixedColumns, XmRDimension,
377 sizeof(Dimension), offset(matrix.trailing_fixed_columns),
378 XmRImmediate, (XtPointer) 0},
379
380 {XmNtrailingFixedRows, XmCTrailingFixedRows, XmRDimension,
381 sizeof(Dimension), offset(matrix.trailing_fixed_rows),
382 XmRImmediate, (XtPointer) 0},
383
384 {XmNtraverseCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
385 offset(matrix.traverse_cell_callback), XmRCallback, NULL},
386
387 {XmNtraverseFixedCells, XmCTraverseFixedCells, XmRBoolean, sizeof(Boolean),
388 offset(matrix.traverse_fixed), XmRImmediate, (XtPointer) False},
389
390 {XmNverticalScrollBar, XmCVerticalScrollBar, XmRWidget, sizeof(Widget),
391 offset(matrix.vertical_sb), XmRImmediate, NULL},
392
393 {XmNverticalScrollBar, XmCVerticalScrollBar, XmRWidget, sizeof(Widget),
394 offset(matrix.vertical_sb), XmRImmediate, NULL},
395
396 {XmNverticalScrollBarDisplayPolicy, XmCMatrixScrollBarDisplayPolicy,
397 XmRMatrixScrollBarDisplayPolicy, sizeof(unsigned char),
398 offset(matrix.vsb_display_policy), XmRImmediate,
399 (XtPointer) XmDISPLAY_AS_NEEDED},
400
401 {XmNvisibleColumns, XmCVisibleColumns, XmRDimension, sizeof(Dimension),
402 offset(matrix.visible_columns), XmRImmediate, (XtPointer) 0},
403
404 {XmNvisibleRows, XmCVisibleRows, XmRDimension, sizeof(Dimension),
405 offset(matrix.visible_rows), XmRImmediate, (XtPointer) 0},
406
407 {XmNwriteCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
408 offset(matrix.write_cell_callback), XmRCallback, NULL},
409
410 };
411
412 static XmSyntheticResource syn_resources[] =
413 {
414 {XmNcellHighlightThickness, sizeof(Dimension),
415 offset(matrix.cell_highlight_thickness), _XmFromHorizontalPixels,
416 _XmToHorizontalPixels},
417
418 {XmNcellMarginHeight, sizeof(Dimension), offset(matrix.cell_margin_height),
419 _XmFromVerticalPixels, _XmToVerticalPixels},
420
421 {XmNcellMarginWidth, sizeof(Dimension), offset(matrix.cell_margin_width),
422 _XmFromHorizontalPixels, _XmToHorizontalPixels},
423
424 {XmNcellShadowThickness, sizeof(Dimension),
425 offset(matrix.cell_shadow_thickness), _XmFromHorizontalPixels,
426 _XmToHorizontalPixels},
427
428 {XmNspace, sizeof(Dimension), offset(matrix.space),
429 _XmFromHorizontalPixels, _XmToHorizontalPixels},
430 };
431
432 #if XmVersion >= 1002
433 static XtIntervalId TraverseID = 0;
434 #endif
435
436 /*
437 * Declaration of methods
438 */
439 static void ClassInitialize P((void));
440 static void xbaeRegisterConverters P((void));
441 static void ClassPartInitialize P((XbaeMatrixWidgetClass));
442 static void Initialize P((XbaeMatrixWidget, XbaeMatrixWidget, ArgList,
443 Cardinal *));
444 static void Realize P((XbaeMatrixWidget, XtValueMask *,
445 XSetWindowAttributes *));
446 static void InsertChild P((Widget));
447 static void Redisplay P((Widget, XEvent *, Region));
448 static Boolean SetValues P((XbaeMatrixWidget, XbaeMatrixWidget,
449 XbaeMatrixWidget, ArgList, Cardinal *));
450 static void SetValuesAlmost P((XbaeMatrixWidget, XbaeMatrixWidget,
451 XtWidgetGeometry *, XtWidgetGeometry *));
452 static void Destroy P((XbaeMatrixWidget));
453 static XtGeometryResult GeometryManager P((Widget, XtWidgetGeometry *,
454 XtWidgetGeometry *));
455 static XtGeometryResult QueryGeometry P((XbaeMatrixWidget, XtWidgetGeometry *,
456 XtWidgetGeometry *));
457
458 /*
459 * Redraw function for clip widget
460 */
461 static void ClipRedisplay P((Widget, XEvent *, Region));
462
463 /*
464 * Private functions unique to Matrix
465 */
466 static void ResizeCells P((XbaeMatrixWidget, XbaeMatrixWidget));
467 static void ResizeSelectedCells P((XbaeMatrixWidget, XbaeMatrixWidget));
468 #if XmVersion >= 1002
469 static void ResizeHighlightedCells P((XbaeMatrixWidget, XbaeMatrixWidget));
470 #endif
471 static void ResizeColors P((XbaeMatrixWidget, XbaeMatrixWidget, Boolean));
472 static void TraverseIn P((XbaeMatrixWidget));
473
474 #if XmVersion >= 1002
475 static void TraverseInTimeOut P((XtPointer, XtIntervalId *));
476 #endif /* XmVersion >= 1002 */
477
478 /*
479 * Clip widget focusCallback
480 */
481 static void TraverseInCB P((Widget, XbaeMatrixWidget, XtPointer));
482
483 /*
484 * Matrix actions
485 */
486 static XtActionsRec actions[] =
487 {
488 {"EditCell", xbaeEditCellACT},
489 {"CancelEdit", xbaeCancelEditACT},
490 {"DefaultAction", xbaeDefaultActionACT},
491 {"CommitEdit", xbaeCommitEditACT},
492 {"ResizeColumns", xbaeResizeColumnsACT},
493 {"SelectCell", xbaeSelectCellACT},
494 {"TraverseNext", xbaeTraverseNextACT},
495 {"TraversePrev", xbaeTraversePrevACT},
496 {"ProcessDrag", xbaeProcessDragACT},
497 {"HandleMotion", xbaeHandleMotionACT},
498 {"PageDown", xbaePageDownACT},
499 {"PageUp", xbaePageUpACT}
500 };
501
502
503 static XmBaseClassExtRec BaseClassExtRec = {
504 NULL, /* next_extension */
505 NULLQUARK, /* record_type */
506 XmBaseClassExtVersion, /* version */
507 sizeof(XmBaseClassExtRec), /* record_size */
508 NULL, /* InitializePrehook */
509 NULL, /* SetValuesPrehook */
510 NULL, /* InitializePosthook */
511 NULL, /* SetValuesPosthook */
512 NULL, /* secondaryObjectClass */
513 NULL, /* secondaryCreate */
514 NULL, /* getSecRes data */
515 { 0 }, /* fastSubclass flags */
516 NULL, /* get_values_prehook */
517 NULL, /* get_values_posthook */
518 NULL, /* classPartInitPrehook */
519 NULL, /* classPartInitPosthook*/
520 NULL, /* ext_resources */
521 NULL, /* compiled_ext_resources*/
522 0, /* num_ext_resources */
523 FALSE, /* use_sub_resources */
524 XmInheritWidgetNavigable, /* widgetNavigable */
525 XmInheritFocusChange, /* focusChange */
526 };
527
528
529 externaldef(xbaematrixclassrec)
530 XbaeMatrixClassRec xbaeMatrixClassRec =
531 {
532 {
533 /* core_class fields */
534 (WidgetClass) & xmManagerClassRec, /* superclass */
535 "XbaeMatrix", /* class_name */
536 sizeof(XbaeMatrixRec), /* widget_size */
537 ClassInitialize, /* class_initialize */
538 (XtWidgetClassProc)ClassPartInitialize, /* class_part_initialize*/
539 False, /* class_inited */
540 (XtInitProc)Initialize, /* initialize */
541 NULL, /* initialize_hook */
542 (XtRealizeProc)Realize, /* realize */
543 actions, /* actions */
544 XtNumber(actions), /* num_actions */
545 resources, /* resources */
546 XtNumber(resources), /* num_resources */
547 NULLQUARK, /* xrm_class */
548 True, /* compress_motion */
549 XtExposeCompressMultiple | /* compress_exposure */
550 XtExposeGraphicsExpose |
551 XtExposeNoExpose,
552 True, /* compress_enterleave */
553 False, /* visible_interest */
554 (XtWidgetProc)Destroy, /* destroy */
555 (XtWidgetProc)xbaeResize, /* resize */
556 (XtExposeProc)Redisplay, /* expose */
557 (XtSetValuesFunc)SetValues, /* set_values */
558 NULL, /* set_values_hook */
559 (XtAlmostProc)SetValuesAlmost, /* set_values_almost */
560 NULL, /* get_values_hook */
561 NULL, /* accept_focus */
562 XtVersionDontCheck, /* version */
563 NULL, /* callback_private */
564 defaultTranslations, /* tm_table */
565 (XtGeometryHandler)QueryGeometry, /* query_geometry */
566 NULL, /* display_accelerator */
567 (XtPointer) &BaseClassExtRec /* extension */
568 },
569
570 {
571 /* composite_class fields */
572 GeometryManager, /* geometry_manager */
573 NULL, /* change_managed */
574 InsertChild, /* insert_child */
575 XtInheritDeleteChild, /* delete_child */
576 NULL, /* extension */
577 },
578 {
579 /* constraint_class fields */
580 NULL, /* resources */
581 0, /* num_resources */
582 0, /* constraint_size */
583 NULL, /* initialize */
584 NULL, /* destroy */
585 NULL, /* set_values */
586 NULL /* extension */
587 },
588 {
589 /* manager_class fields */
590 XtInheritTranslations, /* translations */
591 syn_resources, /* syn_resources */
592 XtNumber(syn_resources), /* num_syn_resources */
593 NULL, /* syn_constraint_resources */
594 0, /* num_syn_constraint_resources */
595 XmInheritParentProcess, /* parent_process */
596 NULL /* extension */
597 },
598 {
599 /* matrix_class fields */
600 xbaeSetCell, /* set_cell */
601 xbaeGetCell, /* get_cell */
602 xbaeEditCell, /* edit_cell */
603 xbaeSelectCell, /* select_cell */
604 xbaeSelectRow, /* select_row */
605 xbaeSelectColumn, /* select_column */
606 xbaeDeselectAll, /* deselect_all */
607 xbaeSelectAll, /* select_all */
608 xbaeDeselectCell, /* deselect_cell */
609 xbaeDeselectRow, /* deselect_row */
610 xbaeDeselectColumn, /* deselect_column */
611 xbaeCommitEdit, /* commit_edit */
612 xbaeCancelEdit, /* cancel_edit */
613 xbaeAddRows, /* add_rows */
614 xbaeDeleteRows, /* delete_rows */
615 xbaeAddColumns, /* add_columns */
616 xbaeDeleteColumns, /* delete_columns */
617 xbaeSetRowColors, /* set_row_colors */
618 xbaeSetColumnColors, /* set_column_colors */
619 xbaeSetCellColor, /* set_cell_color */
620 NULL, /* extension */
621 }
622 };
623
624 externaldef(xbaematrixwidgetclass)
625 WidgetClass xbaeMatrixWidgetClass = (WidgetClass) & xbaeMatrixClassRec;
626
627 static XtConvertArgRec convertArg[] = {
628 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen),
629 sizeof(Screen *)},
630 {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap),
631 sizeof(Colormap)}
632 };
633
634 static void
xbaeRegisterConverters()635 xbaeRegisterConverters()
636 {
637 /*
638 * String to StringArray is used for XmNrowLabels and XmNcolumnLabels
639 * We make a private copy of this table
640 */
641 XtSetTypeConverter(XmRString, XmRStringArray,
642 CvtStringToStringArray, NULL, 0,
643 XtCacheAll | XtCacheRefCount,
644 StringArrayDestructor);
645
646 /*
647 * String to String2DArray is used for XmNcells resource
648 * We make a private copy of this table
649 */
650 XtSetTypeConverter(XmRString, XmRCellTable,
651 CvtStringToCellTable, NULL, 0,
652 XtCacheNone,
653 StringCellDestructor);
654
655 /*
656 * String to ShortArray is used for XmNcolumnWidths resource.
657 * We make a private copy of this table
658 */
659 XtSetTypeConverter(XmRString, XmRWidthArray,
660 CvtStringToWidthArray, NULL, 0,
661 XtCacheAll | XtCacheRefCount,
662 WidthArrayDestructor);
663
664 /*
665 * String to IntArray is used for XmNcolumnMaxLengths resource.
666 * We make a private copy of this table
667 */
668 XtSetTypeConverter(XmRString, XmRMaxLengthArray,
669 CvtStringToMaxLengthArray, NULL, 0,
670 XtCacheAll | XtCacheRefCount,
671 MaxLengthArrayDestructor);
672
673 /*
674 * String to PixelTable is used for XmNcolors
675 * and XmNcellBackgrounds resources.
676 */
677 XtSetTypeConverter(XmRString, XmRPixelTable,
678 CvtStringToPixelTable,convertArg, XtNumber(convertArg),
679 XtCacheNone,
680 PixelTableDestructor);
681 /*
682 * String to BooleanArray is used for XmNcolumnButtonLabels and
683 * XmNrowButtonLabels resources.
684 */
685 XtSetTypeConverter(XmRString, XmRBooleanArray,
686 CvtStringToBooleanArray, NULL, 0,
687 XtCacheAll | XtCacheRefCount,
688 BooleanArrayDestructor);
689
690 /*
691 * String to AlignmentArray is used for XmNcolumnAlignments
692 * and XmNcolumnLabelAlignments resources.
693 */
694 XtSetTypeConverter(XmRString, XmRAlignmentArray,
695 CvtStringToAlignmentArray, NULL, 0,
696 XtCacheAll | XtCacheRefCount,
697 AlignmentArrayDestructor);
698
699 /*
700 * String to grid type is used for XmNgridType
701 */
702 XtSetTypeConverter(XmRString, XmRGridType,
703 CvtStringToGridType, NULL, 0,
704 XtCacheAll, NULL);
705
706 /*
707 * String to matrix display policy is used for
708 * XmN{vertical,horizontal}ScrollBarDisplayPolicy
709 */
710 XtSetTypeConverter(XmRString, XmRMatrixScrollBarDisplayPolicy,
711 #ifdef __VMS
712 CvtStringToMatrixScrollBarDisp,
713 #else
714 CvtStringToMatrixScrollBarDisplayPolicy,
715 #endif
716 NULL, 0, XtCacheAll, NULL);
717 }
718
719 static void
ClassInitialize()720 ClassInitialize()
721 {
722 xbaeRegisterConverters();
723 }
724
725 static void
ClassPartInitialize(mwc)726 ClassPartInitialize(mwc)
727 XbaeMatrixWidgetClass mwc;
728 {
729 register XbaeMatrixWidgetClass super =
730 (XbaeMatrixWidgetClass) mwc->core_class.superclass;
731
732 /*
733 * Allow subclasses to inherit new Matrix methods
734 */
735 if (mwc->matrix_class.set_cell == XbaeInheritSetCell)
736 mwc->matrix_class.set_cell = super->matrix_class.set_cell;
737 if (mwc->matrix_class.get_cell == XbaeInheritGetCell)
738 mwc->matrix_class.get_cell = super->matrix_class.get_cell;
739 if (mwc->matrix_class.edit_cell == XbaeInheritEditCell)
740 mwc->matrix_class.edit_cell = super->matrix_class.edit_cell;
741 if (mwc->matrix_class.select_cell == XbaeInheritSelectCell)
742 mwc->matrix_class.select_cell = super->matrix_class.select_cell;
743 if (mwc->matrix_class.select_row == XbaeInheritSelectRow)
744 mwc->matrix_class.select_row = super->matrix_class.select_row;
745 if (mwc->matrix_class.select_column == XbaeInheritSelectColumn)
746 mwc->matrix_class.select_column = super->matrix_class.select_column;
747 if (mwc->matrix_class.deselect_all == XbaeInheritDeselectAll)
748 mwc->matrix_class.deselect_all = super->matrix_class.deselect_all;
749 if (mwc->matrix_class.select_all == XbaeInheritSelectAll)
750 mwc->matrix_class.select_all = super->matrix_class.select_all;
751 if (mwc->matrix_class.deselect_cell == XbaeInheritDeselectCell)
752 mwc->matrix_class.deselect_cell = super->matrix_class.deselect_cell;
753 if (mwc->matrix_class.deselect_row == XbaeInheritDeselectRow)
754 mwc->matrix_class.deselect_row = super->matrix_class.deselect_row;
755 if (mwc->matrix_class.deselect_column == XbaeInheritDeselectColumn)
756 mwc->matrix_class.deselect_column =
757 super->matrix_class.deselect_column;
758 if (mwc->matrix_class.commit_edit == XbaeInheritCommitEdit)
759 mwc->matrix_class.commit_edit = super->matrix_class.commit_edit;
760 if (mwc->matrix_class.cancel_edit == XbaeInheritCancelEdit)
761 mwc->matrix_class.cancel_edit = super->matrix_class.cancel_edit;
762 if (mwc->matrix_class.add_rows == XbaeInheritAddRows)
763 mwc->matrix_class.add_rows = super->matrix_class.add_rows;
764 if (mwc->matrix_class.delete_rows == XbaeInheritDeleteRows)
765 mwc->matrix_class.delete_rows = super->matrix_class.delete_rows;
766 if (mwc->matrix_class.add_columns == XbaeInheritAddColumns)
767 mwc->matrix_class.add_columns = super->matrix_class.add_columns;
768 if (mwc->matrix_class.delete_columns == XbaeInheritDeleteColumns)
769 mwc->matrix_class.delete_columns = super->matrix_class.delete_columns;
770 if (mwc->matrix_class.set_row_colors == XbaeInheritSetRowColors)
771 mwc->matrix_class.set_row_colors = super->matrix_class.set_row_colors;
772 if (mwc->matrix_class.set_column_colors == XbaeInheritSetColumnColors)
773 mwc->matrix_class.set_column_colors =
774 super->matrix_class.set_column_colors;
775 if (mwc->matrix_class.set_cell_color == XbaeInheritSetCellColor)
776 mwc->matrix_class.set_cell_color = super->matrix_class.set_cell_color;
777 }
778
779
780 #ifdef NEED_24BIT_VISUAL
781 static Widget
get_shell_ancestor(w)782 get_shell_ancestor(w)
783 Widget w;
784 {
785 Widget sh;
786
787 for (sh=w ; !XtIsShell(sh) ; sh=XtParent(sh))
788 ;
789 }
790 #endif
791
792 /*
793 * Callbacks for our scrollbars.
794 */
795 static XtCallbackRec VSCallback[] =
796 {
797 {(XtCallbackProc) xbaeScrollVertCB, (XtPointer) NULL},
798 {(XtCallbackProc) NULL, NULL}
799 };
800 static XtCallbackRec HSCallback[] =
801 {
802 {(XtCallbackProc) xbaeScrollHorizCB, (XtPointer) NULL},
803 {(XtCallbackProc) NULL, NULL}
804 };
805
806 /* ARGSUSED */
807 static void
Initialize(request,new,args,num_args)808 Initialize(request, new, args, num_args)
809 XbaeMatrixWidget request, new;
810 ArgList args;
811 Cardinal *num_args;
812 {
813 Dimension marginHeight;
814
815 /*
816 * Initialize redisplay counters
817 */
818 new->matrix.disable_redisplay = 0;
819 new->matrix.first_row_offset = 0;
820
821 #if XmVersion >= 1002
822 /*
823 * Initialize highlight location
824 */
825 new->matrix.highlight_location = HighlightNone;
826 #endif
827
828 /*
829 * Check rows/cols set by resources for consistency/validity
830 */
831 if (new->matrix.rows < 0 || new->matrix.columns < 0)
832 {
833 XtAppWarningMsg(
834 XtWidgetToApplicationContext((Widget) new),
835 "initialize", "badSize", "XbaeMatrix",
836 "XbaeMatrix: Number of rows or columns is less than zero",
837 (String *) NULL, (Cardinal *) NULL);
838 if (new->matrix.rows < 0)
839 new->matrix.rows = 0;
840 if (new->matrix.columns < 0)
841 new->matrix.columns = 0;
842 }
843
844 /*
845 * Make sure column_widths were specified. If not, use a default value.
846 * This should keep the XDesigner users happy....
847 */
848 if (new->matrix.columns && (new->matrix.column_widths == NULL))
849 {
850 int i;
851
852 new->matrix.column_widths = (short*)XtMalloc(new->matrix.columns *
853 sizeof(short));
854 for (i = 0; i < new->matrix.columns; i++)
855 new->matrix.column_widths[i] = 5;
856
857 }
858
859 /* If no label font is specified, copy the default fontList, but if
860 we do then override the bold_labels resource */
861 if (!new->matrix.label_font_list)
862 new->matrix.label_font_list = XmFontListCopy(new->matrix.font_list);
863 else
864 new->matrix.bold_labels = False;
865
866 /*
867 * We must have at least one non-fixed row/column. Only complain if there
868 * are some to complain about, though. We may have none at all (yet).
869 */
870 if ((int)(new->matrix.fixed_rows +
871 new->matrix.trailing_fixed_rows) > 0 &&
872 (int)(new->matrix.fixed_rows +
873 new->matrix.trailing_fixed_rows) >= new->matrix.rows)
874 {
875 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) new),
876 "initialize", "tooManyFixed", "XbaeMatrix",
877 "XbaeMatrix: At least one row must not be fixed",
878 NULL, 0);
879 new->matrix.fixed_rows = 0;
880 new->matrix.trailing_fixed_rows = 0;
881 }
882 if ((int)(new->matrix.fixed_columns +
883 new->matrix.trailing_fixed_columns) > 0 &&
884 (int)(new->matrix.fixed_columns +
885 new->matrix.trailing_fixed_columns) >= new->matrix.columns)
886 {
887 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) new),
888 "initialize", "tooManyFixed", "XbaeMatrix",
889 "XbaeMatrix: At least one column must not be fixed",
890 NULL, 0);
891 new->matrix.fixed_columns = 0;
892 new->matrix.trailing_fixed_columns = 0;
893 }
894 /*
895 * We can't have too many visible columns
896 */
897 if (new->matrix.columns && ((int)new->matrix.visible_columns >
898 (new->matrix.columns - (int)new->matrix.fixed_columns -
899 (int)new->matrix.trailing_fixed_columns)))
900 {
901 XtAppWarningMsg(
902 XtWidgetToApplicationContext((Widget) new),
903 "initialize", "tooManyVisibleColumns", "XbaeMatrix",
904 "XbaeMatrix: visibleColumns must not be greater than\n (columns - fixedColumns - trailingFixedColumns)",
905 (String *) NULL, (Cardinal *) NULL);
906 new->matrix.visible_columns = 0;
907 }
908
909 if (new->matrix.grid_type >= XmGRID_LINE)
910 /* Deprecated types. To be removed in next version. */
911 XtAppWarningMsg(
912 XtWidgetToApplicationContext((Widget) new),
913 "cvtStringToGridType", "deprecatedType",
914 "XbaeMatrix",
915 "Value for GridType is deprecated and will be removed in next release",
916 NULL, NULL);
917
918 /*
919 * Copy the pointed to resources.
920 * If cells is NULL, we create an array of "" strings.
921 */
922 if (new->matrix.cells)
923 xbaeCopyCells(new);
924 if (new->matrix.row_labels)
925 xbaeCopyRowLabels(new);
926 if (new->matrix.column_labels)
927 xbaeCopyColumnLabels(new);
928 else
929 {
930 new->matrix.column_label_lines = NULL;
931 new->matrix.column_label_maxlines = 0;
932 }
933
934 xbaeCopyColumnWidths(new);
935
936 if (new->matrix.cell_shadow_types)
937 xbaeCopyCellShadowTypes(new);
938 if (new->matrix.row_shadow_types)
939 xbaeCopyRowShadowTypes(new);
940 if (new->matrix.column_shadow_types)
941 xbaeCopyColumnShadowTypes(new);
942
943 if (new->matrix.cell_user_data)
944 xbaeCopyCellUserData(new);
945 if (new->matrix.row_user_data)
946 xbaeCopyRowUserData(new);
947 if (new->matrix.column_user_data)
948 xbaeCopyColumnUserData(new);
949
950 #if CELL_WIDGETS
951 if (new->matrix.cell_widgets)
952 xbaeCopyCellWidgets(new);
953 #endif
954
955 if (new->matrix.column_max_lengths)
956 xbaeCopyColumnMaxLengths(new);
957
958 if (new->matrix.column_alignments)
959 xbaeCopyColumnAlignments(new);
960
961 if (new->matrix.column_button_labels)
962 xbaeCopyColumnButtonLabels(new);
963
964 if (new->matrix.column_label_alignments)
965 xbaeCopyColumnLabelAlignments(new);
966
967 if (new->matrix.colors)
968 xbaeCopyColors(new);
969
970 if (new->matrix.cell_background)
971 xbaeCopyBackgrounds(new);
972
973 if (new->matrix.selected_cells)
974 xbaeCopySelectedCells(new);
975
976 #if XmVersion >= 1002
977 if (new->matrix.highlighted_cells)
978 xbaeCopyHighlightedCells(new);
979 #endif
980
981 if (new->matrix.row_button_labels)
982 xbaeCopyRowButtonLabels(new);
983
984 /*
985 * If user didn't specify a rowLabelWidth, then calculate one based on
986 * the widest label
987 */
988 if (new->matrix.row_label_width == 0 && new->matrix.row_labels)
989 new->matrix.row_label_width = xbaeMaxRowLabel(new);
990
991 /*
992 * Copy the fontList. Get fontStruct from fontList.
993 */
994 xbaeNewFont(new);
995 xbaeNewLabelFont(new);
996
997 /*
998 * Create our 4 children (SBs and textField are unmanaged for now)
999 * they must be created in this order so our macros work
1000 * (horiz scroll, vert scroll and then clip and textField).
1001 * We scroll horizontally by pixels, vertically by rows.
1002 */
1003 new->matrix.horizontal_sb = XtVaCreateWidget(
1004 "horizScroll", xmScrollBarWidgetClass, (Widget) new,
1005 XmNorientation, XmHORIZONTAL,
1006 XmNdragCallback, HSCallback,
1007 XmNvalueChangedCallback, HSCallback,
1008 XmNincrement, FONT_WIDTH(new),
1009 XmNsliderSize, 1,
1010 XmNminimum, 0,
1011 XmNmaximum, 1,
1012 XmNbackground, new->core.background_pixel,
1013 XmNforeground, new->manager.foreground,
1014 XmNbottomShadowColor, new->manager.bottom_shadow_color,
1015 XmNbottomShadowPixmap, new->manager.bottom_shadow_pixmap,
1016 XmNhighlightColor, new->manager.highlight_color,
1017 XmNhighlightPixmap, new->manager.highlight_pixmap,
1018 XmNtopShadowColor, new->manager.top_shadow_color,
1019 XmNtopShadowPixmap, new->manager.top_shadow_pixmap,
1020 NULL);
1021
1022 HORIZ_ORIGIN(new) = 0;
1023
1024 new->matrix.vertical_sb = XtVaCreateWidget(
1025 "vertScroll", xmScrollBarWidgetClass, (Widget) new,
1026 XmNorientation, XmVERTICAL,
1027 XmNdragCallback, VSCallback,
1028 XmNvalueChangedCallback, VSCallback,
1029 XmNincrement, 1,
1030 XmNminimum, 0,
1031 XmNmaximum, new->matrix.rows ?
1032 (new->matrix.rows - (int) new->matrix.fixed_rows -
1033 (int) new->matrix.trailing_fixed_rows) : 1,
1034 XmNsliderSize, 1,
1035 XmNbackground, new->core.background_pixel,
1036 XmNforeground, new->manager.foreground,
1037 XmNbottomShadowColor, new->manager.bottom_shadow_color,
1038 XmNbottomShadowPixmap, new->manager.bottom_shadow_pixmap,
1039 XmNhighlightColor, new->manager.highlight_color,
1040 XmNhighlightPixmap, new->manager.highlight_pixmap,
1041 XmNtopShadowColor, new->manager.top_shadow_color,
1042 XmNtopShadowPixmap, new->manager.top_shadow_pixmap,
1043 NULL);
1044
1045 /*
1046 * Create the Clip widget managed so we can use it for traversal
1047 */
1048 new->matrix.clip_window = XtVaCreateManagedWidget(
1049 "clip", xbaeClipWidgetClass, (Widget) new,
1050 XmNexposeProc, ClipRedisplay,
1051 XmNtraversalOn, new->manager.traversal_on,
1052 XmNbackground, new->core.background_pixel,
1053 NULL);
1054
1055 /*
1056 * Add a callback to the Clip widget so we know when it gets the focus
1057 * and can use it in traversal.
1058 */
1059 XtAddCallback(ClipChild(new), XmNfocusCallback,
1060 (XtCallbackProc)TraverseInCB, (XtPointer) new);
1061
1062 /*
1063 * Calculate an imaginary cellMarginHeight based on the largest of
1064 * the label and cell font. If the font for the labels is bigger,
1065 * the cellMarginHeight needs to be increased to allow the cell font
1066 * to still appear centrally placed
1067 */
1068 if (LABEL_HEIGHT(new) > FONT_HEIGHT(new))
1069 marginHeight = (int)(LABEL_HEIGHT(new) +
1070 (new->matrix.cell_margin_height *
1071 2) - FONT_HEIGHT(new)) / 2;
1072 else
1073 marginHeight = new->matrix.cell_margin_height;
1074
1075 /*
1076 * Create text field (unmanaged for now) - its window will be reparented
1077 * in Realize to be a subwindow of Clip
1078 *
1079 * Set the shadow thickness to 0 to prevent a shadow drawn inside the
1080 * highlight region. The shadow thickness is used to draw the shadows
1081 * *around* the highlight
1082 */
1083
1084 new->matrix.text_field = XtVaCreateWidget(
1085 "textField", xmTextFieldWidgetClass, (Widget) new,
1086 XmNmarginWidth, new->matrix.cell_margin_width,
1087 XmNmarginHeight, marginHeight,
1088 XmNtranslations, new->matrix.text_translations,
1089 XmNfontList, new->matrix.font_list,
1090 XmNshadowThickness, new->matrix.text_shadow_thickness,
1091 XmNbackground, new->matrix.text_background,
1092 XmNforeground, new->manager.foreground,
1093 XmNbottomShadowColor, new->manager.bottom_shadow_color,
1094 XmNbottomShadowPixmap, new->manager.bottom_shadow_pixmap,
1095 XmNhighlightThickness, new->matrix.cell_highlight_thickness,
1096 XmNhighlightColor, new->manager.highlight_color,
1097 XmNhighlightPixmap, new->manager.highlight_pixmap,
1098 XmNeditMode, XmSINGLE_LINE_EDIT,
1099 NULL);
1100
1101 XtAddCallback(TextChild(new), XmNmodifyVerifyCallback, xbaeModifyVerifyCB,
1102 (XtPointer) new);
1103
1104 /* Add a handler on top of the text field to handle clicks on it */
1105 XtAddEventHandler(TextChild(new), ButtonPressMask | ButtonReleaseMask,
1106 True, (XtEventHandler)xbaeHandleClick, (XtPointer)new);
1107 XtAddEventHandler((Widget)new, ButtonPressMask | ButtonReleaseMask,
1108 True, (XtEventHandler)xbaeHandleClick, (XtPointer)new);
1109
1110 /*
1111 * Compute cell text baseline based on TextField widget
1112 */
1113 new->matrix.text_baseline = XmTextGetBaseline(TextChild(new)) +
1114 new->matrix.cell_shadow_thickness;
1115
1116 /*
1117 * Adjust the label_baseline according to the larger of the two fonts
1118 */
1119 if (LABEL_HEIGHT(new) == FONT_HEIGHT(new))
1120 new->matrix.label_baseline = new->matrix.text_baseline;
1121 else
1122 {
1123 if (LABEL_HEIGHT(new) < FONT_HEIGHT(new))
1124 marginHeight = (int)(FONT_HEIGHT(new) +
1125 new->matrix.text_shadow_thickness * 2 +
1126 new->matrix.cell_margin_height * 2 -
1127 LABEL_HEIGHT(new)) / 2;
1128 else
1129 marginHeight = new->matrix.cell_margin_height +
1130 new->matrix.text_shadow_thickness;
1131
1132 new->matrix.label_baseline = marginHeight +
1133 new->matrix.cell_shadow_thickness -
1134 new->matrix.label_font_y;
1135 }
1136 /*
1137 * Calculate total pixel width of cell area
1138 */
1139 xbaeGetCellTotalWidth(new);
1140
1141 /*
1142 * Make the clips for the fixed cells which are scrollable (i.e. the
1143 * fixed rows that can scroll horizontally, and the fixed columns which
1144 * can scroll vertically. This makes 4 scrollable fixed-cell areas.
1145 */
1146 new->matrix.left_clip = XtVaCreateWidget(
1147 "leftclip", xbaeClipWidgetClass, (Widget) new,
1148 XmNexposeProc, Redisplay,
1149 XmNtraversalOn, new->manager.traversal_on,
1150 XmNbackground, new->core.background_pixel,
1151 NULL);
1152 new->matrix.right_clip = XtVaCreateWidget(
1153 "rightclip", xbaeClipWidgetClass, (Widget) new,
1154 XmNexposeProc, Redisplay,
1155 XmNtraversalOn, new->manager.traversal_on,
1156 XmNbackground, new->core.background_pixel,
1157 NULL);
1158 new->matrix.top_clip = XtVaCreateWidget(
1159 "topclip", xbaeClipWidgetClass, (Widget) new,
1160 XmNexposeProc, Redisplay,
1161 XmNtraversalOn, new->manager.traversal_on,
1162 XmNbackground, new->core.background_pixel,
1163 NULL);
1164 new->matrix.bottom_clip = XtVaCreateWidget(
1165 "bottomclip", xbaeClipWidgetClass, (Widget) new,
1166 XmNexposeProc, Redisplay,
1167 XmNtraversalOn, new->manager.traversal_on,
1168 XmNbackground, new->core.background_pixel,
1169 NULL);
1170 /*
1171 * Cache the pixel position of each column
1172 */
1173 new->matrix.column_positions = CreateColumnPositions(new);
1174 xbaeGetColumnPositions(new);
1175
1176 /*
1177 * Now we can set the VSB maximum (relies on data from
1178 * GetCellTotalWidth above)
1179 */
1180 XtVaSetValues(HorizScrollChild(new),
1181 XmNmaximum, NON_FIXED_TOTAL_WIDTH(new) ?
1182 NON_FIXED_TOTAL_WIDTH(new) : 1,
1183 NULL);
1184
1185 /*
1186 * Current position starts at the top left editable cell.
1187 */
1188 new->matrix.current_row = new->matrix.fixed_rows;
1189 new->matrix.current_column = new->matrix.fixed_columns;
1190
1191 new->matrix.current_clip = CLIP_NONE;
1192
1193 /*
1194 * We aren't trying to traverse out
1195 */
1196 new->matrix.traversing = NOT_TRAVERSING;
1197
1198 #ifndef NEED_24BIT_VISUAL
1199 /*
1200 * Get/create our GCs
1201 */
1202 xbaeCreateDrawGC(new);
1203 xbaeCreatePixmapGC(new);
1204 xbaeCreateLabelGC(new);
1205 xbaeCreateLabelClipGC(new);
1206 xbaeCreateGridLineGC(new);
1207 xbaeCreateTopShadowClipGC(new);
1208 xbaeCreateBottomShadowClipGC(new);
1209 #endif
1210
1211 /*
1212 * Now we have created our GCs, check if the widget is sensitive
1213 */
1214 if (!new->core.sensitive)
1215 {
1216 XGCValues values;
1217 unsigned long valuemask = GCFillStyle;
1218 Display *dpy = XtDisplay(new);
1219
1220 if (!new->core.sensitive)
1221 {
1222 int i;
1223
1224 values.fill_style = FillStippled;
1225
1226 /*
1227 * Change our drawing GC's to the stipple effect to indicate
1228 * the widget is insensitive and redraw
1229 */
1230 XChangeGC(dpy, new->matrix.draw_gc, valuemask, &values);
1231 XChangeGC(dpy, new->matrix.label_gc, valuemask, &values);
1232 XChangeGC(dpy, new->matrix.label_clip_gc, valuemask, &values);
1233 XChangeGC(dpy, new->matrix.pixmap_gc, valuemask, &values);
1234 /*
1235 * Propogate the insensitive feel to our children
1236 */
1237 for (i = 0; i < XbaeNumChildren; i++)
1238 XtSetSensitive(new->composite.children[i], False);
1239 }
1240 }
1241
1242 /*
1243 * Create ScrollMgrs to manage scrolling events
1244 */
1245 new->matrix.matrix_scroll_mgr = xbaeSmCreateScrollMgr();
1246 new->matrix.clip_scroll_mgr = xbaeSmCreateScrollMgr();
1247
1248 /*
1249 * Set the last row and column to an impossible value
1250 */
1251 new->matrix.last_row = -1;
1252 new->matrix.last_column = -1;
1253 new->matrix.last_click_time = (Time)0;
1254
1255 /*
1256 * Compute our size. If either dimension was explicitly set to 0,
1257 * then that dimension is computed.
1258 * Use request because superclasses modify width/height.
1259 */
1260 if (request->core.width == 0 || request->core.height == 0)
1261 xbaeComputeSize(new, request->core.width == 0,
1262 request->core.height == 0);
1263
1264 /*
1265 * Make sure top_row is sensible before we call Resize
1266 */
1267 if (VERT_ORIGIN(new) < 0)
1268 VERT_ORIGIN(new) = 0;
1269 else if (VERT_ORIGIN(new) > new->matrix.rows)
1270 VERT_ORIGIN(new) = new->matrix.rows;
1271
1272 /*
1273 * Tweak top_row to make sure it is valid before calling Resize
1274 */
1275 if (VERT_ORIGIN(new))
1276 xbaeAdjustTopRow(new);
1277
1278 if (new->matrix.left_column)
1279 xbaeAdjustLeftColumn(new);
1280
1281 /*
1282 * Layout the scrollbars and clip widget based on our size
1283 */
1284 xbaeResize(new);
1285 }
1286
1287 static void
Realize(mw,valueMask,attributes)1288 Realize(mw, valueMask, attributes)
1289 XbaeMatrixWidget mw;
1290 XtValueMask *valueMask;
1291 XSetWindowAttributes *attributes;
1292 {
1293 *valueMask |= CWDontPropagate;
1294 attributes->do_not_propagate_mask =
1295 ButtonPressMask | ButtonReleaseMask |
1296 KeyPressMask | KeyReleaseMask | PointerMotionMask;
1297
1298 /*
1299 * Don't call our superclasses realize method, because Manager sets
1300 * bit_gravity
1301 */
1302 XtCreateWindow((Widget) mw, InputOutput, CopyFromParent,
1303 *valueMask, attributes);
1304
1305 #ifdef NEED_24BIT_VISUAL
1306 /*
1307 * Now that we have a window...
1308 * Get/create our GCs
1309 */
1310 xbaeCreateDrawGC(mw);
1311 xbaeCreatePixmapGC(mw);
1312 xbaeCreateLabelGC(mw);
1313 xbaeCreateLabelClipGC(mw);
1314 xbaeCreateTopShadowClipGC(mw);
1315 xbaeCreateBottomShadowClipGC(mw);
1316 #endif
1317
1318 /*
1319 * Reparent the textFields window to be a subwindow of Clip widget
1320 * (we need to realize them first)
1321 */
1322 XtRealizeWidget(TextChild(mw));
1323 XtRealizeWidget(ClipChild(mw));
1324 XtRealizeWidget(LeftClip(mw));
1325 XtRealizeWidget(RightClip(mw));
1326 XtRealizeWidget(TopClip(mw));
1327 XtRealizeWidget(BottomClip(mw));
1328 XReparentWindow(XtDisplay(mw), XtWindow(TextChild(mw)),
1329 XtWindow(ClipChild(mw)),
1330 TextChild(mw)->core.x, TextChild(mw)->core.y);
1331 mw->matrix.current_parent = ClipChild(mw);
1332 /*
1333 * Set the clip_mask in our clipping GCs.
1334 */
1335 xbaeSetClipMask(mw, CLIP_NONE);
1336 }
1337
1338 static void
InsertChild(w)1339 InsertChild(w)
1340 Widget w;
1341 {
1342 #if 0
1343 if (((CompositeWidget) XtParent(w))->composite.num_children > 7)
1344 {
1345 #if XmVersion > 1001
1346 /* Hah! Cannot use XmIsDragIconObjectClass because it is defined
1347 * using XtIsSubclass() (at least in the 1.2 and 2.0 headers I have
1348 * available to me). Nothing like a little QA, huh.
1349 *
1350 * Anyways, since the drag icon & context are created as widget
1351 * children of the matrix, we need to allow just those extra types
1352 * to be created as our kids.
1353 */
1354 if ((!XmIsDragContext(w)) && (!XtIsSubclass(w, xmDragIconObjectClass)))
1355 {
1356 #endif
1357 String params[1];
1358 Cardinal num_params = 1;
1359
1360 params[0] = XtClass(XtParent(w))->core_class.class_name;
1361 XtAppWarningMsg(
1362 XtWidgetToApplicationContext(w),
1363 "insertChild", "badChild", "XbaeMatrix",
1364 "XbaeMatrix: Applications cannot add children to %s widgets",
1365 params, &num_params);
1366 #if XmVersion > 1001
1367 }
1368 #endif
1369 return;
1370 }
1371 #endif
1372 #if XmVersion > 1001
1373 (*((XmManagerWidgetClass)
1374 (xbaeMatrixWidgetClass->core_class.superclass))->composite_class.insert_child) (w);
1375 #endif
1376 }
1377
1378 /*
1379 * This is the expose method for the Matrix widget.
1380 * It redraws the row and column labels, the cells in fixed rows and columns
1381 * and the clip window shadow.
1382 */
1383 /* ARGSUSED */
1384 static void
Redisplay(w,event,region)1385 Redisplay(w, event, region)
1386 Widget w;
1387 XEvent *event;
1388 Region region;
1389 {
1390 Rectangle expose;
1391 XbaeMatrixWidget mw;
1392
1393 if (XtIsSubclass(w, xbaeMatrixWidgetClass))
1394 mw = (XbaeMatrixWidget) w;
1395 else /* must be one of the clips */
1396 {
1397 int *x = NULL, *y = NULL;
1398
1399 mw = (XbaeMatrixWidget) XtParent(w);
1400 /* point at the correct x,y pair */
1401 switch (event->type)
1402 {
1403 case Expose:
1404 x = &event->xexpose.x;
1405 y = &event->xexpose.y;
1406 break;
1407
1408 case GraphicsExpose:
1409 x = &event->xgraphicsexpose.x;
1410 y = &event->xgraphicsexpose.y;
1411 break;
1412
1413 case NoExpose:
1414 break;
1415
1416 default:
1417 return;
1418 }
1419
1420 /* NoExpose event can't be translated so make sure x is set */
1421 if (x)
1422 {
1423 /*
1424 * Translate expose event coords into matrix coords if it occured
1425 * on a clip. xbaeRedrawLabelsAndFixed needs to check intersections
1426 * in matrix coords, even though the xbaeDraw* routines will
1427 * correctly retranslate these onto the correct windows for drawing.
1428 */
1429 if (w == LeftClip(mw))
1430 {
1431 *x += ROW_LABEL_WIDTH(mw) + mw->manager.shadow_thickness;
1432 *y += FIXED_ROW_LABEL_OFFSET(mw);
1433 }
1434 else if (w == RightClip(mw))
1435 {
1436 *x += TRAILING_FIXED_COLUMN_LABEL_OFFSET(mw);
1437 *y += FIXED_ROW_LABEL_OFFSET(mw);
1438 }
1439 else if (w == TopClip(mw))
1440 {
1441 *x += FIXED_COLUMN_LABEL_OFFSET(mw);
1442 *y += (COLUMN_LABEL_HEIGHT(mw) + mw->manager.shadow_thickness);
1443 }
1444 else if (w == BottomClip(mw))
1445 {
1446 *x += FIXED_COLUMN_LABEL_OFFSET(mw);
1447 *y += TRAILING_FIXED_ROW_LABEL_OFFSET(mw);
1448 }
1449 else
1450 return; /* eek! Run away quickly */
1451 }
1452 }
1453
1454 if (mw->matrix.disable_redisplay)
1455 return;
1456
1457 /*
1458 * Send our events to the mw ScrollMgr to be adjusted.
1459 */
1460 switch (event->type)
1461 {
1462
1463 case Expose:
1464 /*
1465 * The Expose event will be translated into our scrolled
1466 * coordinate system. Then it is put in a Rectangle.
1467 */
1468 xbaeSmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
1469 SETRECT(expose,
1470 event->xexpose.x, event->xexpose.y,
1471 event->xexpose.x + event->xexpose.width,
1472 event->xexpose.y + event->xexpose.height);
1473 break;
1474
1475 case GraphicsExpose:
1476 /*
1477 * The GraphicsExpose event will cause a scroll to be removed
1478 * from the managers queue, then the event will be translated
1479 * into our scrolled coordinate system. Then it is put in a Rectangle.
1480 */
1481 xbaeSmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
1482 SETRECT(expose,
1483 event->xgraphicsexpose.x, event->xgraphicsexpose.y,
1484 event->xgraphicsexpose.x + event->xgraphicsexpose.width,
1485 event->xgraphicsexpose.y + event->xgraphicsexpose.height);
1486 break;
1487
1488 case NoExpose:
1489 /*
1490 * The NoExpose event means we won't be getting any GraphicsExpose
1491 * events, so the scroll will be removed from the queue and
1492 * we are done.
1493 */
1494 xbaeSmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
1495 return;
1496
1497 default: /* maybe handled above already */
1498 return;
1499 }
1500
1501 /*
1502 * Redraw the row/column labels and fixed rows/columns which are
1503 * overlapped by the expose Rectangle.
1504 */
1505 if ((! mw->matrix.trailing_fixed_columns) &&
1506 IN_GRID_ROW_MODE(mw) && NEED_HORIZ_FILL(mw))
1507 {
1508 Rectangle nonfixed;
1509
1510 /*
1511 * We need to ensure that the last column of cells gets
1512 * redrawn so that the fill is properly redrawn.
1513 */
1514 SETRECT(nonfixed,
1515 COLUMN_POSITION(mw, mw->matrix.columns-1), 0,
1516 COLUMN_POSITION(mw, mw->matrix.columns-1)+1,
1517 ClipChild(mw)->core.height-1);
1518
1519 xbaeRedrawCells(mw, &nonfixed);
1520 }
1521 else if ((! mw->matrix.trailing_fixed_rows) &&
1522 IN_GRID_COLUMN_MODE(mw) && NEED_VERT_FILL(mw))
1523 {
1524 Rectangle nonfixed;
1525
1526 /*
1527 * We need to ensure that the last row of cells gets
1528 * redrawn so that the fill is properly redrawn.
1529 */
1530 SETRECT(nonfixed,
1531 0, ROW_HEIGHT(mw) * (mw->matrix.rows - 1),
1532 ClipChild(mw)->core.width-1,
1533 ROW_HEIGHT(mw) * mw->matrix.rows);
1534
1535 xbaeRedrawCells(mw, &nonfixed);
1536 }
1537
1538 xbaeRedrawLabelsAndFixed(mw, &expose);
1539 }
1540
1541 /*
1542 * This is the exposeProc function for the Clip widget.
1543 * It handles expose events for the Clip widget by redrawing those
1544 * non-fixed cells which were damaged.
1545 * It receives Expose, GraphicsExpose and NoExpose events.
1546 */
1547 /* ARGSUSED */
1548 static void
ClipRedisplay(w,event,region)1549 ClipRedisplay(w, event, region)
1550 Widget w;
1551 XEvent *event;
1552 Region region;
1553 {
1554 XbaeMatrixWidget mw = (XbaeMatrixWidget) XtParent(w);
1555 Rectangle expose, clip, intersect;
1556
1557 if (mw->matrix.disable_redisplay)
1558 return;
1559
1560 /*
1561 * Send our events to the clip ScrollMgr to be adjusted.
1562 */
1563 switch (event->type)
1564 {
1565
1566 case Expose:
1567 /*
1568 * The Expose event will be translated into our scrolled
1569 * coordinate system. Then it is put in a Rectangle.
1570 */
1571 xbaeSmScrollEvent(mw->matrix.clip_scroll_mgr, event);
1572 SETRECT(expose,
1573 event->xexpose.x, event->xexpose.y,
1574 event->xexpose.x + event->xexpose.width - 1,
1575 event->xexpose.y + event->xexpose.height - 1);
1576 break;
1577
1578 case GraphicsExpose:
1579 /*
1580 * The GraphicsExpose event will cause a scroll to be removed
1581 * from the managers queue, then the event will be translated
1582 * into our scrolled coordinate system. Then it is put in a Rectangle.
1583 */
1584 xbaeSmScrollEvent(mw->matrix.clip_scroll_mgr, event);
1585 SETRECT(expose,
1586 event->xgraphicsexpose.x, event->xgraphicsexpose.y,
1587 event->xgraphicsexpose.x + event->xgraphicsexpose.width - 1,
1588 event->xgraphicsexpose.y + event->xgraphicsexpose.height - 1);
1589 break;
1590
1591 case NoExpose:
1592 /*
1593 * The NoExpose event means we won't be getting any GraphicsExpose
1594 * events, so the scroll well be removed from the queue and
1595 * we are done.
1596 */
1597 xbaeSmScrollEvent(mw->matrix.clip_scroll_mgr, event);
1598 return;
1599
1600 default:
1601 return;
1602 }
1603
1604 /*
1605 * We may get an expose event larger than the size of the Clip widget.
1606 * This is because in set_values we may clear the Clip widget
1607 * before it gets resized smaller (maybe in set_values_almost).
1608 * So here we intersect the expose event with the clip widget
1609 * to ensure the expose Rectangle is not larger than the Clip widget.
1610 */
1611 SETRECT(clip,
1612 0, 0,
1613 w->core.width - 1, w->core.height - 1);
1614 INTERSECT(clip, expose, intersect);
1615
1616 /*
1617 * Redraw those cells which overlap the intersect Rectangle.
1618 */
1619 xbaeRedrawCells(mw, &intersect);
1620 }
1621
1622
1623 /* ARGSUSED */
1624 static Boolean
SetValues(current,request,new,args,num_args)1625 SetValues(current, request, new, args, num_args)
1626 XbaeMatrixWidget current, request, new;
1627 ArgList args;
1628 Cardinal *num_args;
1629 {
1630 Boolean redisplay = False; /* need to redraw */
1631 Boolean relayout = False; /* need to layout, but same size */
1632 Boolean new_column_widths = False; /* column widths changed */
1633 Boolean new_cells = False; /* cells changed */
1634 Boolean do_top_row = False; /* reset top_row */
1635 Boolean do_left_column = False; /* reset left_column */
1636 int n;
1637 Arg wargs[9];
1638
1639 #define NE(field) (current->field != new->field)
1640 #define EQ(field) (current->field == new->field)
1641
1642 /*
1643 * We cannot re-set either of the scrollbars, the textField or
1644 * clip window.
1645 */
1646 if (NE(matrix.vertical_sb) || NE(matrix.horizontal_sb) ||
1647 NE(matrix.clip_window) || NE(matrix.text_field))
1648 {
1649 XtAppWarningMsg(
1650 XtWidgetToApplicationContext((Widget) new),
1651 "setValues", "set matrix children", "XbaeMatrix",
1652 "XbaeMatrix: Cannot set matrix widget children",
1653 NULL, 0);
1654 new->matrix.vertical_sb = current->matrix.vertical_sb;
1655 new->matrix.horizontal_sb = current->matrix.horizontal_sb;
1656 new->matrix.clip_window = current->matrix.clip_window;
1657 new->matrix.text_field = current->matrix.text_field;
1658 }
1659
1660 /*
1661 * If rows changed, then:
1662 * row_labels must change or be NULL
1663 * row_button_labels must change or be NULL
1664 */
1665 if ((NE(matrix.rows) && (new->matrix.row_labels &&
1666 EQ(matrix.row_labels))) ||
1667 (new->matrix.row_button_labels &&
1668 EQ(matrix.row_button_labels)))
1669 {
1670 XtAppWarningMsg(
1671 XtWidgetToApplicationContext((Widget) new),
1672 "setValues", "rows", "XbaeMatrix",
1673 "XbaeMatrix: Number of rows changed but dependent resources did not",
1674 NULL, 0);
1675 new->matrix.rows = current->matrix.rows;
1676 new->matrix.row_labels = current->matrix.row_labels;
1677 new->matrix.row_button_labels = current->matrix.row_button_labels;
1678 }
1679
1680 /*
1681 * If columns changed, then:
1682 * column_widths must change
1683 * column_max_lengths must change or be NULL
1684 * column_labels must change or be NULL
1685 * column_alignments must change or be NULL
1686 * column_button_labels must change or be NULL
1687 * column_label_alignments must change or be NULL
1688 */
1689 if (NE(matrix.columns) &&
1690 ((new->matrix.column_labels && EQ(matrix.column_labels)) ||
1691 (new->matrix.column_max_lengths && EQ(matrix.column_max_lengths)) ||
1692 (new->matrix.column_alignments && EQ(matrix.column_alignments)) ||
1693 (new->matrix.column_button_labels &&
1694 EQ(matrix.column_button_labels)) ||
1695 (new->matrix.column_label_alignments &&
1696 EQ(matrix.column_label_alignments)) ||
1697 EQ(matrix.column_widths)))
1698 {
1699 XtAppWarningMsg(
1700 XtWidgetToApplicationContext((Widget) new),
1701 "setValues", "columns", "XbaeMatrix",
1702 "XbaeMatrix: Number of columns changed but dependent resources did not",
1703 NULL, 0);
1704 new->matrix.columns = current->matrix.columns;
1705 new->matrix.column_widths = current->matrix.column_widths;
1706 new->matrix.column_max_lengths = current->matrix.column_max_lengths;
1707 new->matrix.column_labels = current->matrix.column_labels;
1708 new->matrix.column_alignments = current->matrix.column_alignments;
1709 new->matrix.column_button_labels =
1710 current->matrix.column_button_labels;
1711 new->matrix.column_label_alignments =
1712 current->matrix.column_label_alignments;
1713 }
1714
1715 /*
1716 * Make sure we have at least one row/column.
1717 */
1718 if (new->matrix.columns < 0 || new->matrix.rows < 0)
1719 {
1720 XtAppWarningMsg(
1721 XtWidgetToApplicationContext((Widget) new),
1722 "setValues", "size", "XbaeMatrix",
1723 "XbaeMatrix: Must have at least one row and column",
1724 NULL, 0);
1725 if (new->matrix.columns < 0)
1726 new->matrix.columns = current->matrix.columns;
1727 if (new->matrix.rows < 0)
1728 new->matrix.rows = current->matrix.rows;
1729 }
1730
1731
1732 /*
1733 * We must have at least one non-fixed row/column.
1734 * This could be caused by (trailing) fixed_rows/columns or
1735 * rows/columns changing.
1736 */
1737 if ((int)(new->matrix.fixed_rows + new->matrix.trailing_fixed_rows) > 0 &&
1738 (int)(new->matrix.fixed_rows + new->matrix.trailing_fixed_rows) >=
1739 new->matrix.rows)
1740 {
1741 XtAppWarningMsg(
1742 XtWidgetToApplicationContext((Widget) new),
1743 "setValues", "tooManyFixed", "XbaeMatrix",
1744 "XbaeMatrix: At least one row must not be fixed",
1745 NULL, 0);
1746
1747 if (NE(matrix.fixed_rows))
1748 new->matrix.fixed_rows = current->matrix.fixed_rows;
1749 if (NE(matrix.trailing_fixed_rows))
1750 new->matrix.trailing_fixed_rows =
1751 current->matrix.trailing_fixed_rows;
1752 if (NE(matrix.rows))
1753 new->matrix.rows = current->matrix.rows;
1754 }
1755 if ((int)(new->matrix.fixed_columns +
1756 new->matrix.trailing_fixed_columns) > 0 &&
1757 (int)(new->matrix.fixed_columns +
1758 new->matrix.trailing_fixed_columns) >= new->matrix.columns)
1759 {
1760 XtAppWarningMsg(
1761 XtWidgetToApplicationContext((Widget) new),
1762 "setValues", "tooManyFixed", "XbaeMatrix",
1763 "XbaeMatrix: At least one column must not be fixed",
1764 NULL, 0);
1765
1766 if (NE(matrix.fixed_columns))
1767 new->matrix.fixed_columns = current->matrix.fixed_columns;
1768 if (NE(matrix.trailing_fixed_columns))
1769 new->matrix.trailing_fixed_columns =
1770 current->matrix.trailing_fixed_columns;
1771 if (NE(matrix.columns))
1772 new->matrix.columns = current->matrix.columns;
1773 }
1774
1775 /*
1776 * We can't have too many visible columns.
1777 * This could be caused by visible_columns or columns or fixed_columns
1778 * changing.
1779 */
1780 if (new->matrix.columns && ((int)new->matrix.visible_columns >
1781 (new->matrix.columns - (int)new->matrix.fixed_columns -
1782 (int)new->matrix.trailing_fixed_columns)))
1783 {
1784 XtAppWarningMsg(
1785 XtWidgetToApplicationContext((Widget) new),
1786 "setValues", "tooManyVisibleColumns", "XbaeMatrix",
1787 "XbaeMatrix: visibleColumns must not be greater than\n (columns - fixedColumns - trailingFixedColumns)",
1788 (String *) NULL, (Cardinal *) NULL);
1789 if (NE(matrix.visible_columns))
1790 new->matrix.visible_columns = current->matrix.visible_columns;
1791 if (NE(matrix.columns))
1792 new->matrix.columns = current->matrix.columns;
1793 if (NE(matrix.fixed_columns))
1794 new->matrix.fixed_columns = current->matrix.fixed_columns;
1795 if (NE(matrix.trailing_fixed_columns))
1796 new->matrix.trailing_fixed_columns =
1797 current->matrix.trailing_fixed_columns;
1798 }
1799
1800 /*
1801 * Make sure we have column_widths
1802 */
1803 if (new->matrix.columns && (new->matrix.column_widths == NULL))
1804 {
1805 XtAppWarningMsg(
1806 XtWidgetToApplicationContext((Widget) new),
1807 "setValues", "columnWidths", "XbaeMatrix",
1808 "XbaeMatrix: Must specify columnWidths",
1809 NULL, 0);
1810 new->matrix.column_widths = current->matrix.column_widths;
1811 }
1812
1813
1814 /*
1815 * If rows or columns or fixed rows/columns changed,
1816 * then we need to relayout.
1817 */
1818 if (NE(matrix.rows) || NE(matrix.fixed_rows) ||
1819 NE(matrix.trailing_fixed_rows))
1820 {
1821 /*
1822 * Reset VSB maximum. sliderSize will be reset later in Resize.
1823 */
1824 XtVaSetValues(VertScrollChild(new),
1825 XmNmaximum, (new->matrix.rows -
1826 (int) new->matrix.fixed_rows -
1827 (int) new->matrix.trailing_fixed_rows),
1828 XmNsliderSize, 1,
1829 NULL);
1830 do_top_row = True;
1831 relayout = True;
1832 }
1833
1834 if (NE(matrix.columns) || NE(matrix.fixed_columns) ||
1835 NE(matrix.trailing_fixed_columns))
1836 relayout = True;
1837
1838 /*
1839 * Copy any pointed to resources if they changed
1840 */
1841
1842 #if CELL_WIDGETS
1843 if (NE(matrix.cell_widgets))
1844 {
1845 xbaeFreeCellWidgets(current);
1846 xbaeCopyCellWidgets(current);
1847 redisplay = True;
1848 }
1849 #endif
1850
1851 if (NE(matrix.cells))
1852 {
1853 xbaeFreeCells(current);
1854 xbaeCopyCells(new);
1855 redisplay = True;
1856 new_cells = True;
1857 }
1858 else if (NE(matrix.rows) || NE(matrix.columns))
1859 ResizeCells(current, new);
1860
1861 if (NE(matrix.cell_user_data))
1862 {
1863 xbaeFreeCellUserData(current);
1864 if (new->matrix.cell_user_data)
1865 xbaeCopyCellUserData(new);
1866 }
1867 if (NE(matrix.row_user_data))
1868 {
1869 xbaeFreeRowUserData(current);
1870 if (new->matrix.row_user_data)
1871 xbaeCopyRowUserData(new);
1872 }
1873 if (NE(matrix.column_user_data))
1874 {
1875 xbaeFreeColumnUserData(current);
1876 if (new->matrix.column_user_data)
1877 xbaeCopyColumnUserData(new);
1878 }
1879 if (NE(matrix.cell_shadow_types))
1880 {
1881 xbaeFreeCellShadowTypes(current);
1882 if (new->matrix.cell_shadow_types)
1883 xbaeCopyCellShadowTypes(new);
1884 }
1885 if (NE(matrix.row_shadow_types))
1886 {
1887 xbaeFreeRowShadowTypes(current);
1888 if (new->matrix.row_shadow_types)
1889 xbaeCopyRowShadowTypes(new);
1890 }
1891 if (NE(matrix.column_shadow_types))
1892 {
1893 xbaeFreeColumnShadowTypes(current);
1894 if (new->matrix.column_shadow_types)
1895 xbaeCopyColumnShadowTypes(new);
1896 }
1897
1898 if (NE(matrix.row_labels))
1899 {
1900 /*
1901 * If we added or deleted row_labels, we need to layout.
1902 */
1903 if (!current->matrix.row_labels || !new->matrix.row_labels)
1904 relayout = True;
1905 else
1906 redisplay = True;
1907
1908 xbaeFreeRowLabels(current);
1909 if (new->matrix.row_labels)
1910 xbaeCopyRowLabels(new);
1911 }
1912 if (NE(matrix.column_labels))
1913 {
1914 xbaeFreeColumnLabels(current);
1915 if (new->matrix.column_labels)
1916 xbaeCopyColumnLabels(new);
1917 else
1918 {
1919 new->matrix.column_label_lines = NULL;
1920 new->matrix.column_label_maxlines = 0;
1921 }
1922
1923 /*
1924 * If the number of lines in column labels changed, we need to relayout
1925 */
1926 if (current->matrix.column_label_maxlines !=
1927 new->matrix.column_label_maxlines)
1928 relayout = True;
1929 else
1930 redisplay = True;
1931 }
1932 if (NE(matrix.column_max_lengths))
1933 {
1934 xbaeFreeColumnMaxLengths(current);
1935 if (new->matrix.column_max_lengths)
1936 xbaeCopyColumnMaxLengths(new);
1937 redisplay = True;
1938 }
1939 if (NE(matrix.column_alignments))
1940 {
1941 xbaeFreeColumnAlignments(current);
1942 if (new->matrix.column_alignments)
1943 xbaeCopyColumnAlignments(new);
1944 redisplay = True;
1945 }
1946 if (NE(matrix.column_button_labels))
1947 {
1948 xbaeFreeColumnButtonLabels(current);
1949 if (new->matrix.column_button_labels)
1950 xbaeCopyColumnButtonLabels(new);
1951 redisplay = True;
1952 }
1953 if (NE(matrix.row_button_labels))
1954 {
1955 xbaeFreeRowButtonLabels(current);
1956 if (new->matrix.row_button_labels)
1957 xbaeCopyRowButtonLabels(new);
1958 redisplay = True;
1959 }
1960 if (NE(matrix.column_label_alignments))
1961 {
1962 xbaeFreeColumnLabelAlignments(current);
1963 if (new->matrix.column_label_alignments)
1964 xbaeCopyColumnLabelAlignments(new);
1965 redisplay = True;
1966 }
1967 if (NE(matrix.row_label_alignment))
1968 redisplay = True;
1969 if (NE(matrix.row_label_color) || NE(matrix.column_label_color) ||
1970 NE(matrix.button_label_background))
1971 redisplay = True;
1972
1973 if (NE(matrix.colors))
1974 {
1975 xbaeFreeColors(current);
1976 if (new->matrix.colors)
1977 xbaeCopyColors(new);
1978 redisplay = True;
1979 }
1980 if (NE(matrix.cell_background))
1981 {
1982 xbaeFreeBackgrounds(current);
1983 if (new->matrix.cell_background)
1984 xbaeCopyBackgrounds(new);
1985 redisplay = True;
1986 }
1987 if (NE(matrix.grid_line_color))
1988 {
1989 XtReleaseGC((Widget)new, new->matrix.grid_line_gc);
1990 XFreeGC(XtDisplay(new), new->matrix.cell_grid_line_gc);
1991 xbaeCreateGridLineGC(new);
1992 if ((new->matrix.grid_type == XmGRID_CELL_LINE) ||
1993 (new->matrix.grid_type == XmGRID_ROW_LINE) ||
1994 (new->matrix.grid_type == XmGRID_COLUMN_LINE))
1995 redisplay = True;
1996 }
1997
1998 if (NE(matrix.alt_row_count) &&
1999 (new->matrix.even_row_background != current->core.background_pixel ||
2000 new->matrix.odd_row_background != current->core.background_pixel))
2001 redisplay = True;
2002
2003 if (NE(matrix.even_row_background) || NE(matrix.odd_row_background) ||
2004 NE(matrix.grid_type) || NE(matrix.selected_foreground) ||
2005 NE(matrix.selected_background))
2006 redisplay = True;
2007
2008 if (NE(matrix.grid_type) && (new->matrix.grid_type >= XmGRID_LINE))
2009 /* Deprecated types. To be removed in next version. */
2010 XtAppWarningMsg(
2011 XtWidgetToApplicationContext((Widget) new),
2012 "cvtStringToGridType", "deprecatedType",
2013 "XbaeMatrix",
2014 "Value for GridType is deprecated and will be removed in next release",
2015 NULL, NULL);
2016
2017 if (new->matrix.colors && EQ(matrix.colors)
2018 && (NE(matrix.rows) || NE(matrix.columns)))
2019 {
2020 ResizeColors(current, new, False);
2021 redisplay = True;
2022 }
2023
2024 if (new->matrix.cell_background && EQ(matrix.cell_background) &&
2025 (NE(matrix.rows) || NE(matrix.columns)))
2026 {
2027 ResizeColors(current, new, True);
2028 redisplay = True;
2029 }
2030
2031 if (NE(matrix.cell_shadow_type) || NE(matrix.shadow_type) ||
2032 NE(matrix.reverse_select))
2033 redisplay = True;
2034
2035 if (NE(matrix.column_widths))
2036 {
2037 xbaeFreeColumnWidths(current);
2038 xbaeCopyColumnWidths(new);
2039 relayout = True;
2040 new_column_widths = True;
2041 }
2042
2043 if (NE(matrix.selected_cells))
2044 {
2045 xbaeFreeSelectedCells(current);
2046 xbaeCopySelectedCells(new);
2047 redisplay = True;
2048 }
2049 else if (NE(matrix.rows) || NE(matrix.columns))
2050 ResizeSelectedCells(current, new);
2051
2052 #if XmVersion >= 1002
2053 if (NE(matrix.highlighted_cells))
2054 {
2055 xbaeFreeHighlightedCells(current);
2056 xbaeCopyHighlightedCells(new);
2057 redisplay = True;
2058 }
2059 else if (NE(matrix.rows) || NE(matrix.columns))
2060 ResizeHighlightedCells(current, new);
2061 #endif
2062
2063 /*
2064 * If traversal changes, pass through to Clip and textField children.
2065 */
2066 if (NE(manager.traversal_on))
2067 {
2068 XtVaSetValues(ClipChild(new),
2069 XmNtraversalOn, new->manager.traversal_on,
2070 NULL);
2071 }
2072 if (NE(matrix.even_row_background) || NE(matrix.odd_row_background))
2073 redisplay = True;
2074
2075 /*
2076 * Pass through primitive/manager resources to our children
2077 */
2078 n = 0;
2079 if (NE(core.background_pixel))
2080 {
2081 /*
2082 * Set all clip widgets to the new background (thanks Daiji)
2083 */
2084 XtVaSetValues(ClipChild(new),
2085 XmNbackground, new->core.background_pixel,
2086 NULL);
2087 XtVaSetValues(LeftClip(new),
2088 XmNbackground, new->core.background_pixel,
2089 NULL);
2090 XtVaSetValues(RightClip(new),
2091 XmNbackground, new->core.background_pixel,
2092 NULL);
2093 XtVaSetValues(TopClip(new),
2094 XmNbackground, new->core.background_pixel,
2095 NULL);
2096 XtVaSetValues(BottomClip(new),
2097 XmNbackground, new->core.background_pixel,
2098 NULL);
2099 XtSetArg(wargs[n], XmNbackground, new->core.background_pixel); n++;
2100 }
2101 if (NE(manager.foreground))
2102 {
2103 XtSetArg(wargs[n], XmNforeground, new->manager.foreground); n++;
2104 }
2105 if (NE(manager.bottom_shadow_color))
2106 {
2107 XtSetArg(wargs[n], XmNbottomShadowColor,
2108 new->manager.bottom_shadow_color); n++;
2109 }
2110 if (NE(manager.bottom_shadow_pixmap))
2111 {
2112 XtSetArg(wargs[n], XmNbottomShadowPixmap,
2113 new->manager.bottom_shadow_pixmap); n++;
2114 }
2115 if (NE(manager.highlight_color))
2116 {
2117 XtSetArg(wargs[n], XmNhighlightColor,
2118 new->manager.highlight_color); n++;
2119 }
2120 if (NE(manager.highlight_pixmap))
2121 {
2122 XtSetArg(wargs[n], XmNhighlightPixmap,
2123 new->manager.highlight_pixmap); n++;
2124 }
2125 if (NE(manager.top_shadow_color))
2126 {
2127 XtSetArg(wargs[n], XmNtopShadowColor,
2128 new->manager.top_shadow_color); n++;
2129 }
2130 if (NE(manager.top_shadow_pixmap))
2131 {
2132 XtSetArg(wargs[n], XmNtopShadowPixmap,
2133 new->manager.top_shadow_pixmap); n++;
2134 }
2135 if (n)
2136 {
2137 XtSetValues(VertScrollChild(new), wargs, n);
2138 XtSetValues(HorizScrollChild(new), wargs, n);
2139 XtSetValues(TextChild(new), wargs, n);
2140 }
2141
2142 /*
2143 * Would really like to do this in the above,
2144 * but we need to override background_pixel.
2145 */
2146 if (EQ(matrix.text_background) &&
2147 (current->matrix.text_background == current->core.background_pixel))
2148 new->matrix.text_background = new->core.background_pixel;
2149 if (NE(matrix.text_background) || NE(core.background_pixel))
2150 {
2151 XtVaSetValues(TextChild(new),
2152 XmNbackground, new->matrix.text_background,
2153 NULL);
2154 if (XtIsManaged(TextChild(new)))
2155 redisplay = True;
2156 }
2157 /*
2158 * Get a new XFontStruct and copy the fontList if it changed
2159 * and pass it to the textField.
2160 * Reset the HSB increment.
2161 * redisplay and relayout will be set below.
2162 */
2163 if (NE(matrix.font_list))
2164 {
2165 XmFontListFree(current->matrix.font_list);
2166 xbaeNewFont(new);
2167 XtVaSetValues(TextChild(new),
2168 XmNfontList, new->matrix.font_list,
2169 NULL);
2170 XtVaSetValues(HorizScrollChild(new),
2171 XmNincrement, FONT_WIDTH(new),
2172 NULL);
2173 }
2174
2175 if (NE(matrix.label_font_list))
2176 {
2177 XmFontListFree(current->matrix.label_font_list);
2178 xbaeNewLabelFont(new);
2179 XtVaSetValues(HorizScrollChild(new),
2180 XmNincrement, FONT_WIDTH(new),
2181 NULL);
2182 }
2183
2184 /*
2185 * Pass the cell resources on to the textField.
2186 * Both redisplay and relayout will be set below.
2187 *
2188 * If anything changed to affect cell total width or column positions,
2189 * recalc them
2190 */
2191 if (new_cells || NE(matrix.fid) || NE(matrix.label_fid) ||
2192 NE(matrix.cell_margin_width) || NE(matrix.cell_margin_height) ||
2193 NE(matrix.cell_shadow_thickness) || NE(matrix.fixed_columns) ||
2194 NE(matrix.trailing_fixed_columns) ||
2195 NE(matrix.cell_highlight_thickness) || new_column_widths ||
2196 NE(matrix.text_shadow_thickness))
2197 {
2198 /*
2199 * Recalculate the margin height, based on the larger of the
2200 * label and general fonts.
2201 */
2202 int marginHeight = new->matrix.cell_margin_height; /* by default */
2203
2204 if (LABEL_HEIGHT(new) > FONT_HEIGHT(new))
2205 marginHeight = (int)(LABEL_HEIGHT(new) +
2206 (new->matrix.cell_margin_height *
2207 2) - FONT_HEIGHT(new)) / 2;
2208 /*
2209 * Cancel the edit -> If I think of a better way of doing this
2210 * I'll do it, AL.
2211 */
2212 (*((XbaeMatrixWidgetClass) XtClass(new))->matrix_class.cancel_edit)
2213 (new, True);
2214
2215 XtVaSetValues(
2216 TextChild(new),
2217 XmNmarginWidth, new->matrix.cell_margin_width,
2218 XmNhighlightThickness, new->matrix.cell_highlight_thickness,
2219 XmNshadowThickness, new->matrix.text_shadow_thickness,
2220 XmNmarginHeight, marginHeight,
2221 NULL);
2222
2223 xbaeGetCellTotalWidth(new);
2224
2225 /*
2226 * Reset the HSB maximum. sliderSize will be reset later in Resize.
2227 */
2228 XtVaSetValues(HorizScrollChild(new),
2229 XmNmaximum, NON_FIXED_TOTAL_WIDTH(new) ?
2230 NON_FIXED_TOTAL_WIDTH(new) : 1,
2231 XmNsliderSize, 1,
2232 NULL);
2233
2234 /*
2235 * If the number of columns changed, we need to allocate a new array.
2236 */
2237 if (NE(matrix.columns))
2238 {
2239 xbaeFreeColumnPositions(current);
2240 new->matrix.column_positions = CreateColumnPositions(new);
2241 }
2242
2243 /*
2244 * If anything but (trailing_)fixed_columns or the highlight color
2245 * changed, we need to recalc column positions.
2246 */
2247 if (new_cells || NE(matrix.fid) || NE(matrix.label_fid) ||
2248 NE(matrix.cell_margin_width) || NE(matrix.cell_margin_height) ||
2249 NE(matrix.cell_shadow_thickness) ||
2250 NE(matrix.cell_highlight_thickness) || new_column_widths ||
2251 NE(matrix.text_shadow_thickness))
2252
2253 xbaeGetColumnPositions(new);
2254
2255 /*
2256 * Recalculate the baselines
2257 */
2258 new->matrix.text_baseline = XmTextGetBaseline(TextChild(new)) +
2259 new->matrix.cell_shadow_thickness /*+
2260 new->matrix.text_shadow_thickness*/;
2261
2262 /*
2263 * Adjust the label_baseline according to the larger of the two fonts
2264 */
2265 if (LABEL_HEIGHT(new) == FONT_HEIGHT(new))
2266 new->matrix.label_baseline = new->matrix.text_baseline;
2267 else
2268 {
2269 if (LABEL_HEIGHT(new) < FONT_HEIGHT(new))
2270 marginHeight = (FONT_HEIGHT(new) +
2271 new->matrix.text_shadow_thickness * 2 +
2272 new->matrix.cell_margin_height * 2 -
2273 (int)LABEL_HEIGHT(new)) / 2;
2274 else
2275 marginHeight = new->matrix.cell_margin_height +
2276 new->matrix.text_shadow_thickness;
2277
2278 new->matrix.label_baseline = marginHeight +
2279 new->matrix.cell_shadow_thickness -
2280 new->matrix.label_font_y;
2281 }
2282
2283 /* JDS: The comment above this section says both redisplay and
2284 * relayout get set, but only relayout was being set. I noticed
2285 * this because the resizeColumns action was setting the
2286 * columnWidths, but the clip widget wasn't properly redrawing
2287 * its cells when they were resized. This was in conjunction with
2288 * calling clipRedisplay only when the matrix redisplayed instead
2289 * of also when it relayedout :) (see the comment below).
2290 *
2291 * However, I'm not sure what else this might impact. But, I'm in
2292 * favor of the change I made to only redisplay when the matrix
2293 * redisplays since that's more efficient, I think, and it eliminated
2294 * some ugly redraws that I at least encountered. So there :).
2295 */
2296 redisplay = relayout = True;
2297 }
2298
2299 /*
2300 * Install text_translations on textField
2301 */
2302 if (NE(matrix.text_translations))
2303 XtVaSetValues(TextChild(new),
2304 XmNtranslations, new->matrix.text_translations,
2305 NULL);
2306
2307 /*
2308 * If row_label_width was set to 0, calculate it.
2309 * Otherwise if it was changed, set flags.
2310 */
2311 if (new->matrix.row_label_width == 0 && new->matrix.row_labels)
2312 {
2313 new->matrix.row_label_width = xbaeMaxRowLabel(new);
2314 relayout = True;
2315 }
2316 else if (NE(matrix.row_label_width))
2317 relayout = True;
2318
2319 /*
2320 * Check whether the widget is sensitive has changed and set our GC's
2321 * appropriately
2322 */
2323 if (XtIsSensitive((Widget)current) != XtIsSensitive((Widget)new))
2324 {
2325 XGCValues values;
2326 int i;
2327 unsigned long valuemask = GCFillStyle;
2328 Display *dpy = XtDisplay(new);
2329
2330 if (!XtIsSensitive((Widget)new))
2331 {
2332 values.fill_style = FillStippled;
2333
2334 /*
2335 * Change our drawing GC's to the stipple effect to indicate
2336 * the widget is insensitive and redraw
2337 */
2338 XChangeGC(dpy, new->matrix.draw_gc, valuemask, &values);
2339 XChangeGC(dpy, new->matrix.label_gc, valuemask, &values);
2340 XChangeGC(dpy, new->matrix.label_clip_gc, valuemask, &values);
2341 XChangeGC(dpy, new->matrix.pixmap_gc, valuemask, &values);
2342 /*
2343 * Propogate the insensitive feel to our children
2344 */
2345 for (i = 0; i < XbaeNumChildren; i++)
2346 XtSetSensitive(new->composite.children[i], False);
2347 }
2348 else
2349 {
2350 values.fill_style = FillSolid;
2351
2352 XChangeGC(dpy, new->matrix.draw_gc, valuemask, &values);
2353 XChangeGC(dpy, new->matrix.label_gc, valuemask, &values);
2354 XChangeGC(dpy, new->matrix.label_clip_gc, valuemask, &values);
2355 XChangeGC(dpy, new->matrix.pixmap_gc, valuemask, &values);
2356
2357 for (i = 0; i < XbaeNumChildren; i++)
2358 XtSetSensitive(new->composite.children[i], True);
2359 }
2360 redisplay = True;
2361 }
2362
2363 /*
2364 * If our fill policy changed or our bottom attachment,
2365 * we must redisplay and relayout.
2366 */
2367 if (NE(matrix.fill) || NE(matrix.trailing_attached_bottom))
2368 {
2369 redisplay = True;
2370 relayout = True;
2371 }
2372
2373 /*
2374 * If either of the scrollbar display policies changed,
2375 * we need to redisplay and relayout.
2376 */
2377 if (NE(matrix.vsb_display_policy) ||
2378 NE(matrix.hsb_display_policy))
2379 relayout = True;
2380
2381 /*
2382 * If the place of the scrollbars changes, we must redisplay
2383 */
2384 if (NE(matrix.scrollbar_placement))
2385 relayout = True;
2386
2387 /*
2388 * Change created GCs if needed
2389 */
2390
2391 if (NE(manager.foreground))
2392 {
2393 /*
2394 * We don't need to put the new foreground in draw_gc or
2395 * draw_clip_gc because they get a new foreground when they are used.
2396 */
2397 XSetForeground(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
2398 new->manager.foreground);
2399 XSetBackground(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
2400 new->manager.foreground);
2401 redisplay = True;
2402 }
2403 if (NE(manager.top_shadow_color))
2404 {
2405 XSetForeground(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
2406 new->manager.top_shadow_color);
2407 XSetForeground(XtDisplay(new), new->matrix.resize_top_shadow_gc,
2408 new->manager.top_shadow_color);
2409 redisplay = True;
2410 }
2411 if (NE(manager.top_shadow_pixmap))
2412 {
2413 XSetTile(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
2414 new->manager.top_shadow_pixmap);
2415 XSetTile(XtDisplay(new), new->matrix.resize_top_shadow_gc,
2416 new->manager.top_shadow_pixmap);
2417 redisplay = True;
2418 }
2419 if (NE(manager.bottom_shadow_color))
2420 {
2421 XSetForeground(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
2422 new->manager.bottom_shadow_color);
2423 XSetForeground(XtDisplay(new), new->matrix.resize_bottom_shadow_gc,
2424 new->manager.bottom_shadow_color);
2425 redisplay = True;
2426 }
2427 if (NE(manager.bottom_shadow_pixmap))
2428 {
2429 XSetTile(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
2430 new->manager.bottom_shadow_pixmap);
2431 XSetTile(XtDisplay(new), new->matrix.resize_bottom_shadow_gc,
2432 new->manager.bottom_shadow_pixmap);
2433 redisplay = True;
2434 }
2435 if (NE(matrix.fid))
2436 {
2437 XSetFont(XtDisplay(new), new->matrix.draw_gc, new->matrix.fid);
2438 redisplay = True;
2439 }
2440
2441 if (NE(matrix.label_fid))
2442 {
2443 XSetFont(XtDisplay(new), new->matrix.label_gc,
2444 new->matrix.label_fid);
2445 XSetFont(XtDisplay(new), new->matrix.label_clip_gc,
2446 new->matrix.label_fid);
2447 redisplay = True;
2448 }
2449 /*
2450 * See if any other resources changed which will require a relayout
2451 */
2452 if (NE(matrix.space) || NE(matrix.cell_shadow_thickness) ||
2453 NE(manager.shadow_thickness))
2454 relayout = True;
2455
2456 /*
2457 * If bold_labels or button labels changed, and we have labels,
2458 * we must redisplay
2459 */
2460 if ((NE(matrix.bold_labels) || NE(matrix.button_labels)) &&
2461 (new->matrix.row_labels || new->matrix.column_labels))
2462 redisplay = True;
2463
2464 /*
2465 * If showArrows is changed, redisplay to get rid of existing arrows
2466 */
2467 if (NE(matrix.show_arrows))
2468 redisplay = True;
2469
2470 /*
2471 * Compute a new size if:
2472 * visible_rows or visible_columns changed.
2473 * user set our width or height to zero.
2474 */
2475 if (NE(matrix.visible_rows) || NE(matrix.visible_columns) ||
2476 request->core.height == 0 || request->core.width == 0)
2477 xbaeComputeSize(new, request->core.width == 0,
2478 request->core.height == 0);
2479
2480 /*
2481 * If our size didn't change, but we need to layout, call Resize.
2482 * If our size did change, then Xt will call our Resize method for us.
2483 * If our size did change, but the new size is later refused,
2484 * then SetValuesAlmost will call Resize to layout.
2485 */
2486 if (EQ(core.width) && EQ(core.height) && relayout)
2487 xbaeResize(new);
2488
2489 /*
2490 * The user forced a new top_row or something changed to force
2491 * us to recheck the current top_row.
2492 */
2493 if (NE(matrix.top_row) || do_top_row)
2494 {
2495 XmScrollBarCallbackStruct call_data;
2496
2497 xbaeAdjustTopRow(new);
2498 call_data.value = VERT_ORIGIN(new);
2499 /*
2500 * Trick xbaeScrollVertCB() into believing it needs to scroll
2501 */
2502 VERT_ORIGIN(new) = VERT_ORIGIN(current);
2503 xbaeScrollVertCB((Widget)VertScrollChild(new), NULL, &call_data);
2504 VERT_ORIGIN(new) = call_data.value; /* and reset VERT_ORIGIN */
2505
2506 XtVaSetValues(VertScrollChild(new),
2507 XmNvalue, VERT_ORIGIN(new),
2508 NULL);
2509 }
2510
2511 if (NE(matrix.left_column) || do_left_column)
2512 {
2513 XmScrollBarCallbackStruct call_data;
2514
2515 xbaeAdjustLeftColumn(new);
2516 call_data.value = HORIZ_ORIGIN(new);
2517 HORIZ_ORIGIN(new) = HORIZ_ORIGIN(current);
2518 xbaeScrollHorizCB((Widget)HorizScrollChild(new), NULL, &call_data);
2519 HORIZ_ORIGIN(new) = call_data.value;
2520 XtVaSetValues(HorizScrollChild(new),
2521 XmNvalue, HORIZ_ORIGIN(new),
2522 NULL);
2523 }
2524
2525 /*
2526 * Force the Clip widget to redisplay. Note: this may generate an
2527 * expose event for the current size of the Clip widget, and the Clip
2528 * widget may be sized smaller in set_values_almost. The ClipRedisplay
2529 * function can handle this case.
2530 *
2531 * JDS: Don't need to force a redisplay on a relayout, since the Clip
2532 * widget's resize method (now non-NULL) will be called and Xt will
2533 * automatically do an expose after that occurs. Seems to work, anyways :).
2534 */
2535 if (redisplay)
2536 XbaeMatrixRefresh((Widget)new);
2537
2538 /*
2539 * We want to return True when we need to redisplay or relayout.
2540 */
2541 return redisplay || relayout;
2542
2543 #undef NE
2544 #undef EQ
2545 }
2546
2547 /* ARGSUSED */
2548 static void
SetValuesAlmost(old,new,request,reply)2549 SetValuesAlmost(old, new, request, reply)
2550 XbaeMatrixWidget old;
2551 XbaeMatrixWidget new;
2552 XtWidgetGeometry *request;
2553 XtWidgetGeometry *reply;
2554 {
2555 /*
2556 * If XtGeometryAlmost, accept compromize - Resize will take care of it
2557 */
2558 if (reply->request_mode)
2559 {
2560 *request = *reply;
2561
2562 #if XtSpecificationRelease > 4
2563 /*
2564 * In R5, XtSetValues changed so that when a widgets parent
2565 * returns XtGeometryAlmost, Xt will only call the widgets resize
2566 * method if the widgets size actually changed. It turns out that
2567 * some manager widgets (old Wcl XmpTable and 1.1.x XmForm) return
2568 * XtGeometryAlmost with a compromise size which is the widgets
2569 * original size (not much of a compromise)! This means as of R5,
2570 * Matrix's resize method won't get called in that case.
2571 *
2572 * So, for R5 we explicitly call our resize method here for the
2573 * case of XtGeometryAlmost where our size did not change.
2574 */
2575 if ((reply->request_mode & CWWidth ||
2576 reply->request_mode & CWHeight)
2577 &&
2578 (old->core.width == new->core.width &&
2579 old->core.height == new->core.height))
2580 xbaeResize(new);
2581 #endif
2582 }
2583
2584 /*
2585 * If XtGeometryNo, call Resize to relayout if it was a size change
2586 * that was denied.
2587 * Accept the original geometry.
2588 * (we need to call Resize even though the size
2589 * didn't change to force a relayout - set_values relies on this)
2590 */
2591 else
2592 {
2593 if ((request->request_mode & CWWidth ||
2594 request->request_mode & CWHeight))
2595 xbaeResize(new);
2596
2597 request->request_mode = 0;
2598 }
2599 }
2600
2601 static void
Destroy(mw)2602 Destroy(mw)
2603 XbaeMatrixWidget mw;
2604 {
2605 #if XmVersion >= 1002
2606 if (TraverseID)
2607 XtRemoveTimeOut(TraverseID);
2608 #endif
2609
2610 XtReleaseGC((Widget) mw, mw->matrix.grid_line_gc);
2611 XFreeGC(XtDisplay(mw), mw->matrix.cell_grid_line_gc);
2612
2613 XFreeGC(XtDisplay(mw), mw->matrix.label_gc);
2614 XFreeGC(XtDisplay(mw), mw->matrix.label_clip_gc);
2615 XFreeGC(XtDisplay(mw), mw->matrix.draw_gc);
2616 XFreeGC(XtDisplay(mw), mw->matrix.pixmap_gc);
2617 XFreeGC(XtDisplay(mw), mw->matrix.cell_top_shadow_clip_gc);
2618 XFreeGC(XtDisplay(mw), mw->matrix.cell_bottom_shadow_clip_gc);
2619 XtReleaseGC((Widget) mw, mw->matrix.resize_top_shadow_gc);
2620 XtReleaseGC((Widget) mw, mw->matrix.resize_bottom_shadow_gc);
2621
2622 xbaeFreeCells(mw);
2623 #if CELL_WIDGETS
2624 xbaeFreeCellWidgets(mw);
2625 #endif
2626 xbaeFreeRowLabels(mw);
2627 xbaeFreeColumnLabels(mw);
2628 xbaeFreeColumnWidths(mw);
2629 xbaeFreeColumnMaxLengths(mw);
2630 xbaeFreeColumnPositions(mw);
2631 xbaeFreeColumnAlignments(mw);
2632 xbaeFreeColumnButtonLabels(mw);
2633 xbaeFreeRowButtonLabels(mw);
2634 xbaeFreeColumnLabelAlignments(mw);
2635 xbaeFreeCellUserData(mw);
2636 xbaeFreeRowUserData(mw);
2637 xbaeFreeColumnUserData(mw);
2638 xbaeFreeCellShadowTypes(mw);
2639 xbaeFreeRowShadowTypes(mw);
2640 xbaeFreeColumnShadowTypes(mw);
2641 xbaeFreeColors(mw);
2642 xbaeFreeBackgrounds(mw);
2643 xbaeFreeSelectedCells(mw);
2644 #if XmVersion >= 1002
2645 xbaeFreeHighlightedCells(mw);
2646 #endif
2647
2648 XmFontListFree(mw->matrix.font_list);
2649 XmFontListFree(mw->matrix.label_font_list);
2650
2651 xbaeSmDestroyScrollMgr(mw->matrix.matrix_scroll_mgr);
2652 xbaeSmDestroyScrollMgr(mw->matrix.clip_scroll_mgr);
2653 }
2654
2655 /*
2656 * Since we totally control our childrens geometry, allow anything.
2657 */
2658 /* ARGSUSED */
2659 static XtGeometryResult
GeometryManager(w,desired,allowed)2660 GeometryManager(w, desired, allowed)
2661 Widget w;
2662 XtWidgetGeometry *desired, *allowed;
2663 {
2664 #define Wants(flag) (desired->request_mode & flag)
2665
2666 if (Wants(XtCWQueryOnly))
2667 return (XtGeometryYes);
2668
2669 if (Wants(CWWidth))
2670 w->core.width = desired->width;
2671 if (Wants(CWHeight))
2672 w->core.height = desired->height;
2673 if (Wants(CWX))
2674 w->core.x = desired->x;
2675 if (Wants(CWY))
2676 w->core.y = desired->y;
2677 if (Wants(CWBorderWidth))
2678 w->core.border_width = desired->border_width;
2679
2680 return (XtGeometryYes);
2681
2682 #undef Wants
2683 }
2684
2685 /*
2686 * We would prefer to be the size calculated in ComputeSize and saved in
2687 * desired_width/height
2688 */
2689 static XtGeometryResult
QueryGeometry(mw,proposed,desired)2690 QueryGeometry(mw, proposed, desired)
2691 XbaeMatrixWidget mw;
2692 XtWidgetGeometry *proposed, *desired;
2693 {
2694 #define Set(bit) (proposed->request_mode & bit)
2695
2696 desired->width = mw->matrix.desired_width;
2697 desired->height = mw->matrix.desired_height;
2698 desired->request_mode = CWWidth | CWHeight;
2699
2700 if (Set(CWWidth) && proposed->width == desired->width &&
2701 Set(CWHeight) && proposed->height == desired->height)
2702 return (XtGeometryYes);
2703
2704 if (desired->width == mw->core.width && desired->height == mw->core.height)
2705 return (XtGeometryNo);
2706
2707 return (XtGeometryAlmost);
2708
2709 #undef Set
2710 }
2711
2712 /*
2713 * This function is called from either the Clip focus CB or a timeout proc.
2714 * It is called as a result of the Clip getting the focus. We want to give
2715 * the focus to the textField if a cell is being edited. If no cells are
2716 * being edited, force an edit on the top left most visible cell.
2717 */
2718 static void
TraverseIn(mw)2719 TraverseIn(mw)
2720 XbaeMatrixWidget mw;
2721 {
2722 /*
2723 * If the traversing flag is set, then Clip got the focus because
2724 * textField was trying to traverse out of mw. We'll help it along.
2725 * Sickening.
2726 */
2727 if (mw->matrix.traversing != NOT_TRAVERSING)
2728 {
2729 XmProcessTraversal(ClipChild(mw), mw->matrix.traversing);
2730 return;
2731 }
2732
2733 /*
2734 * If the textField is managed and not visible, scroll it onto the screen
2735 * and traverse to it.
2736 */
2737 if (XtIsManaged(TextChild(mw)))
2738 {
2739 if (mw->matrix.scroll_select)
2740 xbaeMakeCellVisible(mw, mw->matrix.current_row,
2741 mw->matrix.current_column);
2742 XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
2743 }
2744
2745 /*
2746 * Otherwise, no cell is being edited. Force an edit on the top-left
2747 * most visible cell.
2748 */
2749 else
2750 {
2751 int column = xbaeXtoCol(mw, FIXED_COLUMN_WIDTH(mw) + HORIZ_ORIGIN(mw));
2752 int row = VERT_ORIGIN(mw) + mw->matrix.fixed_rows;
2753
2754 /*
2755 * Call the traverseCellCallback to allow the application to
2756 * perform custom traversal.
2757 */
2758 if (mw->matrix.traverse_cell_callback)
2759 {
2760 XbaeMatrixTraverseCellCallbackStruct call_data;
2761
2762 call_data.reason = XbaeTraverseCellReason;
2763 call_data.event = (XEvent *)NULL;
2764 call_data.row = 0;
2765 call_data.column = 0;
2766 call_data.next_row = row;
2767 call_data.next_column = column;
2768 call_data.fixed_rows = mw->matrix.fixed_rows;
2769 call_data.fixed_columns = mw->matrix.fixed_columns;
2770 call_data.trailing_fixed_rows = mw->matrix.trailing_fixed_rows;
2771 call_data.trailing_fixed_columns =
2772 mw->matrix.trailing_fixed_columns;
2773 call_data.num_rows = mw->matrix.rows;
2774 call_data.num_columns = mw->matrix.columns;
2775 call_data.param = NULL;
2776 call_data.qparam = NULLQUARK;
2777
2778 XtCallCallbackList((Widget) mw, mw->matrix.traverse_cell_callback,
2779 (XtPointer) & call_data);
2780
2781 row = call_data.next_row;
2782 column = call_data.next_column;
2783 }
2784
2785 (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.edit_cell)
2786 (mw, NULL, row, column, NULL, 0);
2787
2788 XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
2789 }
2790 }
2791
2792 #if XmVersion >= 1002
2793 /*
2794 * Under Motif 1.2, TraverseInCB can't call TraverseIn directly, so it
2795 * adds a zero length timeout and we call it from here.
2796 */
2797 /* ARGSUSED */
2798 static void
TraverseInTimeOut(mw,timer)2799 TraverseInTimeOut(mw, timer)
2800 XtPointer mw;
2801 XtIntervalId *timer;
2802 {
2803 TraverseIn((XbaeMatrixWidget)mw);
2804 }
2805
2806 #endif /* XmVersion >= 1002 */
2807
2808 /*
2809 * This is the Clip widgets focusCallback. We want to give the focus to
2810 * the textField if a cell is being edited. If no cells are being edited,
2811 * force an edit on the top left most visible cell.
2812 */
2813 /* ARGSUSED */
2814 static void
TraverseInCB(w,mw,call_data)2815 TraverseInCB(w, mw, call_data)
2816 Widget w;
2817 XbaeMatrixWidget mw;
2818 XtPointer call_data;
2819 {
2820 #if XmVersion < 1002
2821 TraverseIn(mw);
2822 #else
2823 /*
2824 * Under Motif 1.2, we can't call TraverseIn directly because it
2825 * calls XmProcessTraversal and recursive calls to XmProcessTraversal
2826 * are disallowed in 1.2 (we may be in this CB as a result of someone
2827 * calling XmProcessTraversal). So we add a zero length timeout
2828 * and call TraverseIn from there.
2829 */
2830 TraverseID = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) w), 0L,
2831 TraverseInTimeOut, (XtPointer) mw);
2832 #endif
2833 }
2834
2835 /*
2836 * Add rows/columns of cells when set_values changes our rows/columns
2837 */
2838 static void
ResizeCells(current,new)2839 ResizeCells(current, new)
2840 XbaeMatrixWidget current;
2841 XbaeMatrixWidget new;
2842 {
2843 int i, j;
2844 int safe_rows = 0;
2845
2846 /*
2847 * If there is a draw cell callback, we don't need to allocate any
2848 * memory for the cells so get outta here. If there is a draw cell
2849 * callback, no memory should have been allocated when this point is
2850 * reached.
2851 */
2852 if (!new->matrix.cells)
2853 return;
2854
2855 if (new->matrix.rows == current->matrix.rows)
2856 safe_rows = new->matrix.rows;
2857
2858 /*
2859 * Adding rows
2860 */
2861 if (new->matrix.rows > current->matrix.rows)
2862 {
2863 /*
2864 * Realloc a larger array of row pointers
2865 */
2866 new->matrix.cells =
2867 (String **) XtRealloc((char *) new->matrix.cells,
2868 new->matrix.rows * sizeof(String *));
2869
2870 /*
2871 * Malloc a new row array for each row. Initialize it with
2872 * NULL Strings. Use the new column size.
2873 */
2874 for (i = current->matrix.rows; i < new->matrix.rows; i++)
2875 {
2876 new->matrix.cells[i] =
2877 (String *) XtMalloc(new->matrix.columns * sizeof(String));
2878 for (j = 0; j < new->matrix.columns; j++)
2879 new->matrix.cells[i][j] = XtNewString("");
2880 }
2881
2882 safe_rows = current->matrix.rows;
2883 }
2884
2885 /*
2886 * Deleting rows
2887 */
2888 if (new->matrix.rows < current->matrix.rows)
2889 {
2890 /*
2891 * Free the cells in the rows being deleted and the rows themselves
2892 */
2893 for (i = new->matrix.rows; i < current->matrix.rows; i++)
2894 {
2895 for (j = 0; j < current->matrix.columns; j++)
2896 XtFree((XtPointer) new->matrix.cells[i][j]);
2897 XtFree((XtPointer) new->matrix.cells[i]);
2898 }
2899
2900 safe_rows = new->matrix.rows;
2901 }
2902
2903 /*
2904 * Adding columns
2905 */
2906 if (new->matrix.columns > current->matrix.columns)
2907 {
2908 /*
2909 * Realloc each row array. Do not touch any rows added/deleted above
2910 * (use safe_rows)
2911 */
2912 for (i = 0; i < safe_rows; i++)
2913 {
2914 new->matrix.cells[i] =
2915 (String *) XtRealloc((char *) new->matrix.cells[i],
2916 new->matrix.columns * sizeof(String));
2917 for (j = current->matrix.columns; j < new->matrix.columns; j++)
2918 new->matrix.cells[i][j] = XtNewString("");
2919 }
2920 }
2921
2922 /*
2923 * Deleting columns
2924 */
2925 if (new->matrix.columns < current->matrix.columns)
2926 {
2927 /*
2928 * Free all the cells in the deleted columns. Do not touch any
2929 * rows added/deleted above (use safe_rows).
2930 * We don't bother to realloc each row, just leave some wasted space.
2931 * XXX is this a problem?
2932 */
2933 for (i = 0; i < safe_rows; i++)
2934 for (j = new->matrix.columns; j < current->matrix.columns; j++)
2935 XtFree((XtPointer) new->matrix.cells[i][j]);
2936 }
2937 }
2938
2939 /*
2940 * Add rows/columns of selected flags when set_values changes our rows/columns
2941 */
2942 static void
ResizeSelectedCells(current,new)2943 ResizeSelectedCells(current, new)
2944 XbaeMatrixWidget current;
2945 XbaeMatrixWidget new;
2946 {
2947 int i;
2948 int safe_rows = 0;
2949
2950 /*
2951 * selectedCells is allocated when the first cell is selected. If it
2952 * is still NULL, no cells have been selected up to this point.
2953 */
2954 if (!new->matrix.selected_cells)
2955 return;
2956
2957 if (new->matrix.rows == current->matrix.rows)
2958 safe_rows = new->matrix.rows;
2959
2960 /*
2961 * Adding rows
2962 */
2963 if (new->matrix.rows > current->matrix.rows)
2964 {
2965 /*
2966 * Realloc a larger array of row pointers
2967 */
2968 new->matrix.selected_cells =
2969 (Boolean **) XtRealloc((char *) new->matrix.selected_cells,
2970 new->matrix.rows * sizeof(Boolean *));
2971
2972 /*
2973 * Calloc a new row array for each row. Use the new column size.
2974 */
2975 for (i = current->matrix.rows; i < new->matrix.rows; i++)
2976 new->matrix.selected_cells[i] =
2977 (Boolean *) XtCalloc(new->matrix.columns, sizeof(Boolean));
2978
2979 safe_rows = current->matrix.rows;
2980 }
2981
2982 /*
2983 * Deleting rows
2984 */
2985 if (new->matrix.rows < current->matrix.rows)
2986 {
2987 for (i = new->matrix.rows; i < current->matrix.rows; i++)
2988 XtFree((XtPointer) new->matrix.selected_cells[i]);
2989 safe_rows = new->matrix.rows;
2990 }
2991
2992 /*
2993 * Adding columns
2994 */
2995 if (new->matrix.columns > current->matrix.columns)
2996 {
2997 /*
2998 * Realloc each row array. Do not touch any rows added/deleted above
2999 * (use safe_rows)
3000 */
3001 for (i = 0; i < safe_rows; i++)
3002 {
3003 int j;
3004
3005 new->matrix.selected_cells[i] =
3006 (Boolean *) XtRealloc((char *) new->matrix.selected_cells[i],
3007 new->matrix.columns * sizeof(Boolean));
3008 for (j = current->matrix.columns; j < new->matrix.columns; j++)
3009 new->matrix.selected_cells[i][j] = False;
3010 }
3011 }
3012
3013 /*
3014 * Deleting columns
3015 * if (new->matrix.columns < current->matrix.columns)
3016 * We don't bother to realloc, just leave some wasted space.
3017 * XXX is this a problem?
3018 */
3019 }
3020
3021 #if XmVersion >= 1002
3022 /*
3023 * Add rows/columns of highlighted flags when set_values changes our rows/columns
3024 */
3025 static void
ResizeHighlightedCells(current,new)3026 ResizeHighlightedCells(current, new)
3027 XbaeMatrixWidget current;
3028 XbaeMatrixWidget new;
3029 {
3030 int i;
3031 int safe_rows = 0;
3032
3033 if (!new->matrix.highlighted_cells)
3034 return;
3035
3036 if (new->matrix.rows == current->matrix.rows)
3037 safe_rows = new->matrix.rows;
3038
3039 /*
3040 * Adding rows
3041 */
3042 if (new->matrix.rows > current->matrix.rows)
3043 {
3044 /*
3045 * Realloc a larger array of row pointers
3046 */
3047 new->matrix.highlighted_cells =
3048 (unsigned char **) XtRealloc(
3049 (char *) new->matrix.highlighted_cells,
3050 new->matrix.rows * sizeof(unsigned char *));
3051
3052 /*
3053 * Calloc a new row array for each row. Use the new column size.
3054 */
3055 for (i = current->matrix.rows; i < new->matrix.rows; i++)
3056 new->matrix.highlighted_cells[i] =
3057 (unsigned char *) XtCalloc(new->matrix.columns,
3058 sizeof(unsigned char));
3059
3060 safe_rows = current->matrix.rows;
3061 }
3062
3063 /*
3064 * Deleting rows
3065 */
3066 if (new->matrix.rows < current->matrix.rows)
3067 {
3068 for (i = new->matrix.rows; i < current->matrix.rows; i++)
3069 XtFree((XtPointer) new->matrix.highlighted_cells[i]);
3070 safe_rows = new->matrix.rows;
3071 }
3072
3073 /*
3074 * Adding columns
3075 */
3076 if (new->matrix.columns > current->matrix.columns)
3077 {
3078 /*
3079 * Realloc each row array. Do not touch any rows added/deleted above
3080 * (use safe_rows)
3081 */
3082 for (i = 0; i < safe_rows; i++)
3083 {
3084 int j;
3085
3086 new->matrix.highlighted_cells[i] =
3087 (unsigned char *) XtRealloc(
3088 (char *) new->matrix.highlighted_cells[i],
3089 new->matrix.columns * sizeof(unsigned char));
3090 for (j = current->matrix.columns; j < new->matrix.columns; j++)
3091 new->matrix.highlighted_cells[i][j] = HighlightNone;
3092 }
3093 }
3094
3095 /*
3096 * Deleting columns
3097 * if (new->matrix.columns < current->matrix.columns)
3098 * We don't bother to realloc, just leave some wasted space.
3099 * XXX is this a problem?
3100 */
3101 }
3102 #endif
3103
3104 /*
3105 * Add rows/columns of colors when set_values changes our rows/columns
3106 */
3107 static void
3108 #if NeedFunctionPrototypes
ResizeColors(XbaeMatrixWidget current,XbaeMatrixWidget new,Boolean bg)3109 ResizeColors(XbaeMatrixWidget current, XbaeMatrixWidget new, Boolean bg)
3110 #else
3111 ResizeColors(current, new, bg)
3112 XbaeMatrixWidget current;
3113 XbaeMatrixWidget new;
3114 Boolean bg;
3115 #endif
3116 {
3117 int i, j;
3118 int safe_rows = 0;
3119
3120 if (! new->matrix.rows)
3121 return;
3122
3123 if (new->matrix.rows == current->matrix.rows)
3124 safe_rows = new->matrix.rows;
3125
3126 /*
3127 * Adding rows
3128 */
3129 if (new->matrix.rows > current->matrix.rows)
3130 {
3131 /*
3132 * Realloc a larger array of row pointers
3133 */
3134 if (bg)
3135 {
3136 new->matrix.cell_background =
3137 (Pixel **) XtRealloc((char *) new->matrix.cell_background,
3138 new->matrix.rows * sizeof(Pixel *));
3139 for (i = current->matrix.rows; i < new->matrix.rows; i++)
3140 {
3141 new->matrix.cell_background[i] =
3142 (Pixel *) XtMalloc(new->matrix.columns * sizeof(Pixel));
3143
3144 for (j = 0; j < new->matrix.columns; j++)
3145 new->matrix.cell_background[i][j] =
3146 new->core.background_pixel;
3147 }
3148 }
3149 else
3150 {
3151 new->matrix.colors =
3152 (Pixel **) XtRealloc((char *) new->matrix.colors,
3153 new->matrix.rows * sizeof(Pixel *));
3154 for (i = current->matrix.rows; i < new->matrix.rows; i++)
3155 {
3156 new->matrix.colors[i] =
3157 (Pixel *) XtMalloc(new->matrix.columns * sizeof(Pixel));
3158
3159 for (j = 0; j < new->matrix.columns; j++)
3160 new->matrix.colors[i][j] = new->manager.foreground;
3161 }
3162 }
3163 /*
3164 * Malloc a new row array for each row. Initialize it with foreground.
3165 * Use the new column size.
3166 */
3167 safe_rows = current->matrix.rows;
3168 }
3169
3170 /*
3171 * Deleting rows
3172 */
3173 if (new->matrix.rows < current->matrix.rows)
3174 {
3175 if (bg)
3176 for (i = new->matrix.rows; i < current->matrix.rows; i++)
3177 XtFree((XtPointer) new->matrix.cell_background[i]);
3178 else
3179 for (i = new->matrix.rows; i < current->matrix.rows; i++)
3180 XtFree((XtPointer) new->matrix.colors[i]);
3181
3182 safe_rows = new->matrix.rows;
3183 }
3184
3185 /*
3186 * Adding columns
3187 */
3188 if (new->matrix.columns > current->matrix.columns)
3189 {
3190 /*
3191 * Realloc each row array. Do not touch any rows added/deleted above
3192 * (use safe_rows)
3193 */
3194 if (bg)
3195 {
3196 for (i = 0; i < safe_rows; i++)
3197 {
3198 int k;
3199
3200 new->matrix.cell_background[i] =
3201 (Pixel *) XtRealloc(
3202 (char *) new->matrix.cell_background[i],
3203 new->matrix.columns * sizeof(Pixel));
3204
3205 for (k = current->matrix.columns; k < new->matrix.columns;
3206 k++)
3207 new->matrix.cell_background[i][k] =
3208 new->core.background_pixel;
3209 }
3210 }
3211 else
3212 {
3213 for (i = 0; i < safe_rows; i++)
3214 {
3215 int k;
3216
3217 new->matrix.colors[i] =
3218 (Pixel *) XtRealloc(
3219 (char *) new->matrix.colors[i],
3220 new->matrix.columns * sizeof(Pixel));
3221
3222 for (k = current->matrix.columns; k < new->matrix.columns;
3223 k++)
3224 new->matrix.colors[i][k] = new->manager.foreground;
3225 }
3226 }
3227 }
3228
3229 /*
3230 * Deleting columns
3231 * if (new->matrix.columns < current->matrix.columns)
3232 * We don't bother to realloc, just leave some wasted space.
3233 * XXX is this a problem? AL: Probably! If you are deleting enough
3234 * columns, it would be nice to make the memory available again.
3235 * I'll get to it later.
3236 */
3237 }
3238
3239