home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume17 / xbae / part06 < prev    next >
Encoding:
Text File  |  1992-03-22  |  50.5 KB  |  1,812 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!zaphod.mps.ohio-state.edu!mips!msi!dcmartin
  3. From: Andrew Wason <aw@bae.bellcore.com>
  4. Subject: v17i033: Xbae widgets (MOTIF), Part06/12
  5. Message-ID: <1992Mar23.180106.16103@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. References: <csx-17i028-xbae@uunet.UU.NET>
  10. Date: Mon, 23 Mar 1992 18:01:06 GMT
  11. Approved: dcmartin@msi.com
  12.  
  13. Submitted-by: Andrew Wason <aw@bae.bellcore.com>
  14. Posting-number: Volume 17, Issue 33
  15. Archive-name: xbae/part06
  16.  
  17. Submitted-by: aw@jello
  18. Archive-name: Xbae/part06
  19.  
  20. ---- Cut Here and feed the following to sh ----
  21. #!/bin/sh
  22. # this is Xbae.shar.06 (part 6 of Xbae)
  23. # do not concatenate these parts, unpack them in order with /bin/sh
  24. # file Xbae/src/Matrix.c continued
  25. #
  26. if test ! -r _shar_seq_.tmp; then
  27.     echo 'Please unpack part 1 first!'
  28.     exit 1
  29. fi
  30. (read Scheck
  31.  if test "$Scheck" != 6; then
  32.     echo Please unpack part "$Scheck" next!
  33.     exit 1
  34.  else
  35.     exit 0
  36.  fi
  37. ) < _shar_seq_.tmp || exit 1
  38. if test ! -f _shar_wnt_.tmp; then
  39.     echo 'x - still skipping Xbae/src/Matrix.c'
  40. else
  41. echo 'x - continuing file Xbae/src/Matrix.c'
  42. sed 's/^X//' << 'SHAR_EOF' >> 'Xbae/src/Matrix.c' &&
  43. X     */
  44. X    values.foreground = mw->manager.top_shadow_color;
  45. X    values.background = mw->manager.foreground;
  46. X
  47. X    if (mw->manager.top_shadow_pixmap != XmUNSPECIFIED_PIXMAP) {
  48. X    mask |= GCFillStyle | GCTile;
  49. X    values.fill_style = FillTiled;
  50. X    values.tile = mw->manager.top_shadow_pixmap;
  51. X    }
  52. X    mw->matrix.cell_top_shadow_clip_gc =
  53. X    XCreateGC(XtDisplay(mw),
  54. X          RootWindowOfScreen(XtScreen(mw)),
  55. X          mask, &values);
  56. }
  57. X
  58. static void
  59. CreateBottomShadowClipGC(mw)
  60. XXbaeMatrixWidget mw;
  61. {
  62. X    XGCValues values;
  63. X    XtGCMask mask = GCForeground | GCBackground;
  64. X
  65. X    /*
  66. X     * GC for drawing bottom shadow inside cells with clipping.
  67. X     */
  68. X    values.foreground = mw->manager.bottom_shadow_color;
  69. X    values.background = mw->manager.foreground;
  70. X
  71. X    if (mw->manager.bottom_shadow_pixmap != XmUNSPECIFIED_PIXMAP) {
  72. X    mask |= GCFillStyle | GCTile;
  73. X    values.fill_style = FillTiled;
  74. X    values.tile = mw->manager.bottom_shadow_pixmap;
  75. X    }
  76. X    mw->matrix.cell_bottom_shadow_clip_gc =
  77. X    XCreateGC(XtDisplay(mw),
  78. X          RootWindowOfScreen(XtScreen(mw)),
  79. X          mask, &values);
  80. }
  81. X
  82. /*
  83. X * Set the clip_mask in our draw and shadow GCs.  This is necessary for
  84. X * drawing non-fixed column labels and fixed rows.
  85. X */
  86. static void
  87. SetClipMask(mw)
  88. XXbaeMatrixWidget mw;
  89. {
  90. X    XRectangle r;
  91. X
  92. X    /*
  93. X     * XRectangle enclosing column labels and fixed rows
  94. X     */
  95. X    r.x = FIXED_COLUMN_LABEL_OFFSET(mw);
  96. X    r.y = 0;
  97. X    r.width = ClipChild(mw)->core.width;
  98. X    r.height = FIXED_ROW_LABEL_OFFSET(mw);
  99. X
  100. X    /*
  101. X     * Reset the clip_mask in our clipping GCs
  102. X     */
  103. X    XSetClipRectangles(XtDisplay(mw), mw->matrix.draw_clip_gc,
  104. X               0, 0, &r, 1, Unsorted);
  105. X    XSetClipRectangles(XtDisplay(mw), mw->matrix.inverse_clip_gc,
  106. X               0, 0, &r, 1, Unsorted);
  107. X    XSetClipRectangles(XtDisplay(mw), mw->matrix.cell_top_shadow_clip_gc,
  108. X               0, 0, &r, 1, Unsorted);
  109. X    XSetClipRectangles(XtDisplay(mw), mw->matrix.cell_bottom_shadow_clip_gc,
  110. X               0, 0, &r, 1, Unsorted);
  111. }
  112. X
  113. static void
  114. NewFont(mw)
  115. XXbaeMatrixWidget mw;
  116. {
  117. X    XmFontContext context;
  118. X    XmStringCharSet charset;
  119. X    XFontStruct *font;
  120. X
  121. X    /*
  122. X     * Make a private copy of the FontList
  123. X     */
  124. X    mw->matrix.font_list = XmFontListCopy(mw->matrix.font_list);
  125. X
  126. X    /*
  127. X     * Get XFontStruct from FontList
  128. X     */
  129. X
  130. X    if (!XmFontListInitFontContext(&context, mw->matrix.font_list))
  131. X    XtAppErrorMsg(XtWidgetToApplicationContext((Widget)mw),
  132. X              "newFont", "badFont", "XbaeMatrix",
  133. X              "XbaeMatrix: XmFontListInitFontContext failed, bad fontList",
  134. X              NULL, 0);
  135. X
  136. X    if (!XmFontListGetNextFont(context, &charset, &font))
  137. X    XtAppErrorMsg(XtWidgetToApplicationContext((Widget)mw),
  138. X              "newFont", "badFont", "XbaeMatrix",
  139. X              "XbaeMatrix: XmFontListGetNextFont failed, cannot get font from fontList",
  140. X              NULL, 0);
  141. X
  142. X    XtFree(charset);
  143. X    XmFontListFreeFontContext(context);
  144. X
  145. X    mw->matrix.font = font;
  146. }
  147. X
  148. /*
  149. X * Return the length of the longest row label
  150. X */
  151. static short
  152. MaxRowLabel(mw)
  153. XXbaeMatrixWidget mw;
  154. {
  155. X    int i;
  156. X    short max = 0, len;
  157. X
  158. X    /*
  159. X     * Determine the length of the longest row label
  160. X     */
  161. X    for (i = 0; i < mw->matrix.rows; i++) {
  162. X    len = strlen(mw->matrix.row_labels[i]);
  163. X    if (len > max)
  164. X        max = len;
  165. X    }
  166. X    return max;
  167. }
  168. X
  169. /*
  170. X * Get the total pixel width of the non-fixed cell area
  171. X */
  172. static void
  173. GetCellTotalWidth(mw)
  174. XXbaeMatrixWidget mw;
  175. {
  176. X    int i;
  177. X
  178. X    /*
  179. X     * Calculate width of non-fixed cell area.
  180. X     */
  181. X    for (i = mw->matrix.fixed_columns, mw->matrix.cell_total_width = 0;
  182. X     i < mw->matrix.columns;
  183. X     i++)
  184. X    mw->matrix.cell_total_width += COLUMN_WIDTH(mw, i);
  185. }
  186. X
  187. /*
  188. X * Cache the pixel position of each column
  189. X */
  190. static void
  191. GetColumnPositions(mw)
  192. XXbaeMatrixWidget mw;
  193. {
  194. X    int i, x;
  195. X
  196. X    for (i = 0, x = 0;
  197. X     i < mw->matrix.columns;
  198. X     x += COLUMN_WIDTH(mw, i), i++)
  199. X    mw->matrix.column_positions[i] = x;
  200. }
  201. X
  202. X
  203. /*
  204. X * Callbacks for our scrollbars.
  205. X */
  206. static XtCallbackRec VSCallback[] =
  207. {
  208. X    {(XtCallbackProc) ScrollVertCB, (XtPointer) NULL},
  209. X    {(XtCallbackProc) NULL, NULL}
  210. };
  211. static XtCallbackRec HSCallback[] =
  212. {
  213. X    {(XtCallbackProc) ScrollHorizCB, (XtPointer) NULL},
  214. X    {(XtCallbackProc) NULL, NULL}
  215. };
  216. X
  217. /* ARGSUSED */
  218. static void
  219. Initialize(request, new, args, num_args)
  220. XXbaeMatrixWidget request, new;
  221. ArgList args;
  222. Cardinal *num_args;
  223. {
  224. X    /*
  225. X     * Check rows/cols set by resources for consistency/validity
  226. X     */
  227. X    if (new->matrix.rows == 0 || new->matrix.columns == 0) {
  228. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  229. X            "initialize", "badSize", "XbaeMatrix",
  230. X            "XbaeMatrix: Number of rows or columns is zero",
  231. X            (String *) NULL, (Cardinal *) NULL);
  232. X    if (!new->matrix.rows)
  233. X        new->matrix.rows = 1;
  234. X    if (!new->matrix.columns)
  235. X        new->matrix.columns = 1;
  236. X    }
  237. X
  238. X    /*
  239. X     * Make sure column_widths were specified
  240. X     */
  241. X    if (new->matrix.column_widths == NULL)
  242. X    XtAppErrorMsg(XtWidgetToApplicationContext((Widget)new),
  243. X              "initialize", "noColumnWidths", "XbaeMatrix",
  244. X              "XbaeMatrix: No columnWidths specified",
  245. X              (String *) NULL, (Cardinal *) NULL);
  246. X
  247. X    /*
  248. X     * Only one of fixed_rows/fixed_columns may be specified
  249. X     */
  250. X    if (new->matrix.fixed_rows && new->matrix.fixed_columns) {
  251. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  252. X              "initialize", "bothFixed", "XbaeMatrix",
  253. X              "XbaeMatrix: Cannot specify both fixedRows and fixedColumns",
  254. X              (String *) NULL, (Cardinal *) NULL);
  255. X    new->matrix.fixed_rows = 0;
  256. X    new->matrix.fixed_columns = 0;
  257. X    }
  258. X
  259. X
  260. X    /*
  261. X     * We must have at least one non-fixed row/column
  262. X     */
  263. X    if ((new->matrix.fixed_rows &&
  264. X     new->matrix.fixed_rows >= new->matrix.rows) ||
  265. X    (new->matrix.fixed_columns &&
  266. X     new->matrix.fixed_columns >= new->matrix.columns)) {
  267. X    String params[1];
  268. X    Cardinal num_params = 1;
  269. X    params[0] = new->matrix.fixed_rows ? "row" : "column";
  270. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  271. X            "initialize", "tooManyFixed", "XbaeMatrix",
  272. X            "XbaeMatrix: At least one %s must not be fixed",
  273. X            (String *) params, (Cardinal *) &num_params);
  274. X    if (new->matrix.fixed_rows)
  275. X        new->matrix.fixed_rows = 0;
  276. X    else if (new->matrix.fixed_columns)
  277. X        new->matrix.fixed_columns = 0;
  278. X    }
  279. X
  280. X    /*
  281. X     * We can't have too many visible rows
  282. X     */
  283. X    if (new->matrix.visible_rows > new->matrix.rows - new->matrix.fixed_rows) {
  284. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  285. X            "initialize", "tooManyVisibleRows", "XbaeMatrix",
  286. X            "XbaeMatrix: Too many visible rows",
  287. X            (String *) NULL, (Cardinal *) NULL);
  288. X    new->matrix.visible_rows = 0;
  289. X    }
  290. X
  291. X    /*
  292. X     * We can't have too many visible columns
  293. X     */
  294. X    if (new->matrix.visible_columns >
  295. X    new->matrix.columns - new->matrix.fixed_columns) {
  296. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  297. X            "initialize", "tooManyVisibleColumns", "XbaeMatrix",
  298. X            "XbaeMatrix: Too many visible columns",
  299. X            (String *) NULL, (Cardinal *) NULL);
  300. X    new->matrix.visible_columns = 0;
  301. X    }
  302. X
  303. X    /*
  304. X     * Copy the pointed to resources.
  305. X     * If cells is NULL, we create an array of "" strings.
  306. X     */
  307. X
  308. X    CopyCells(new);
  309. X
  310. X    if (new->matrix.row_labels)
  311. X    CopyRowLabels(new);
  312. X    if (new->matrix.column_labels)
  313. X    CopyColumnLabels(new);
  314. X    else {
  315. X    new->matrix.column_label_lines = NULL;
  316. X    new->matrix.column_label_maxlines = 0;
  317. X    }
  318. X
  319. X    CopyColumnWidths(new);
  320. X
  321. X    if (new->matrix.column_max_lengths)
  322. X    CopyColumnMaxLengths(new);
  323. X
  324. X    if (new->matrix.column_alignments)
  325. X    CopyColumnAlignments(new);
  326. X    if (new->matrix.column_label_alignments)
  327. X    CopyColumnLabelAlignments(new);
  328. X
  329. X    if (new->matrix.colors)
  330. X    CopyColors(new);
  331. X
  332. X    CopySelectedCells(new);
  333. X
  334. X    /*
  335. X     * If user didn't specify a rowLabelWidth, then calculate one based on
  336. X     * the widest label
  337. X     */
  338. X    if (new->matrix.row_label_width == 0 && new->matrix.row_labels)
  339. X    new->matrix.row_label_width = MaxRowLabel(new);
  340. X
  341. X    /*
  342. X     * Copy the fontList. Get fontStruct from fontList.
  343. X     */
  344. X    NewFont(new);
  345. X
  346. X    /*
  347. X     * Create our 4 children (SBs and textField are unmanaged for now)
  348. X     * they must be created in this order so our macros work
  349. X     * (horiz scroll, vert scroll and then clip and textField).
  350. X     * We scroll horizontally by pixels, vertically by rows.
  351. X     */
  352. X
  353. X    (void) XtVaCreateWidget("horizScroll",
  354. X                xmScrollBarWidgetClass, new,
  355. X                XmNorientation,    XmHORIZONTAL,
  356. X                XmNdragCallback,    HSCallback,
  357. X                XmNvalueChangedCallback, HSCallback,
  358. X                XmNincrement,    FONT_WIDTH(new),
  359. X                XmNsliderSize,    1,
  360. X                XmNbackground,    new->core.background_pixel,
  361. X                XmNforeground,    new->manager.foreground,
  362. X                XmNbottomShadowColor,
  363. X                new->manager.bottom_shadow_color,
  364. X                XmNbottomShadowPixmap,
  365. X                new->manager.bottom_shadow_pixmap,
  366. X                XmNhighlightColor,    new->manager.highlight_color,
  367. X                XmNhighlightPixmap,    new->manager.highlight_pixmap,
  368. X                XmNshadowThickness,    new->manager.shadow_thickness,
  369. X                XmNtopShadowColor,    new->manager.top_shadow_color,
  370. X                XmNtopShadowPixmap, new->manager.top_shadow_pixmap,
  371. X                NULL);
  372. X    HORIZ_ORIGIN(new) = 0;
  373. X
  374. X    (void) XtVaCreateWidget("vertScroll",
  375. X                xmScrollBarWidgetClass, new,
  376. X                XmNorientation,        XmVERTICAL,
  377. X                XmNdragCallback,        VSCallback,
  378. X                XmNvalueChangedCallback,    VSCallback,
  379. X                XmNincrement,    1,
  380. X                XmNminimum,        0,
  381. X                XmNmaximum,        (new->matrix.rows -
  382. X                         (int) new->matrix.fixed_rows),
  383. X                XmNsliderSize,    1,
  384. X                XmNbackground,    new->core.background_pixel,
  385. X                XmNforeground,    new->manager.foreground,
  386. X                XmNbottomShadowColor,
  387. X                new->manager.bottom_shadow_color,
  388. X                XmNbottomShadowPixmap,
  389. X                new->manager.bottom_shadow_pixmap,
  390. X                XmNhighlightColor,    new->manager.highlight_color,
  391. X                XmNhighlightPixmap,    new->manager.highlight_pixmap,
  392. X                XmNshadowThickness,    new->manager.shadow_thickness,
  393. X                XmNtopShadowColor,    new->manager.top_shadow_color,
  394. X                XmNtopShadowPixmap, new->manager.top_shadow_pixmap,
  395. X                NULL);
  396. X
  397. X    /*
  398. X     * Create the Clip widget managed so we can use it for traversal
  399. X     */
  400. X    (void) XtVaCreateManagedWidget("clip",
  401. X                   xbaeClipWidgetClass, new,
  402. X                   XmNexposeProc,    ClipRedisplay,
  403. X                   XmNtraversalOn,
  404. X                       new->manager.traversal_on,
  405. X                   XmNbackground,
  406. X                    new->core.background_pixel,
  407. X                   NULL);
  408. X
  409. X    /*
  410. X     * Add a callback to the Clip widget so we know when it gets the focus
  411. X     * and can use it in traversal.
  412. X     */
  413. X    XtAddCallback(ClipChild(new), XmNfocusCallback, TraverseInCB,
  414. X          (XtPointer)new);
  415. X
  416. X    /*
  417. X     * Create text field (unmanaged for now) - its window will be reparented
  418. X     * in Realize to be a subwindow of Clip
  419. X     */
  420. X    (void) XtVaCreateWidget("textField",
  421. X                xmTextFieldWidgetClass,  new,
  422. X                XmNmarginWidth,    new->matrix.cell_margin_width,
  423. X                XmNmarginHeight,    new->matrix.cell_margin_height,
  424. X                XmNtranslations,    new->matrix.text_translations,
  425. X                XmNfontList,    new->matrix.font_list,
  426. X                XmNshadowThickness,
  427. X                    new->matrix.cell_shadow_thickness,
  428. X                XmNhighlightThickness,
  429. X                    new->matrix.cell_highlight_thickness,
  430. X                XmNbackground,    new->core.background_pixel,
  431. X                XmNforeground,    new->manager.foreground,
  432. X                XmNbottomShadowColor,
  433. X                    new->manager.bottom_shadow_color,
  434. X                XmNbottomShadowPixmap,
  435. X                    new->manager.bottom_shadow_pixmap,
  436. X                XmNhighlightColor,    new->manager.highlight_color,
  437. X                XmNhighlightPixmap,    new->manager.highlight_pixmap,
  438. X                XmNtopShadowColor,    new->manager.top_shadow_color,
  439. X                XmNtopShadowPixmap,    new->manager.top_shadow_pixmap,
  440. X                NULL);
  441. X
  442. X    /*
  443. X     * We need a hook onto textField for the modifyVerifyCallback
  444. X     * XXX we always have a modifyVerifyCallback even if the user
  445. X     * doesn't want one - how else can we tell when we need to
  446. X     * reinstall callbacks on the textField?
  447. X     */
  448. X    XtAddCallback(TextChild(new), XmNmodifyVerifyCallback, ModifyVerifyCB,
  449. X          (XtPointer)new);
  450. X
  451. X    /*
  452. X     * Compute cell text baseline based on TextField widget
  453. X     */
  454. X    new->matrix.text_baseline = XmTextFieldGetBaseline(TextChild(new));
  455. X
  456. X    /*
  457. X     * Calculate total pixel width of cell area
  458. X     */
  459. X    GetCellTotalWidth(new);
  460. X
  461. X    /*
  462. X     * Cache the pixel position of each column
  463. X     */
  464. X    new->matrix.column_positions = CreateColumnPositions(new);
  465. X    GetColumnPositions(new);
  466. X
  467. X    /*
  468. X     * Now we can set the VSB maximum (relies on data from
  469. X     * GetCellTotalWidth above)
  470. X     */
  471. X    XtVaSetValues(HorizScrollChild(new),
  472. X          XmNmaximum,    CELL_TOTAL_WIDTH(new),
  473. X          NULL);
  474. X
  475. X    /*
  476. X     * Current position starts at the top left editable cell.
  477. X     */
  478. X    new->matrix.current_row = new->matrix.fixed_rows;
  479. X    new->matrix.current_column = new->matrix.fixed_columns;
  480. X
  481. X    /*
  482. X     * We aren't trying to traverse out
  483. X     */
  484. X    new->matrix.traversing = NOT_TRAVERSING;
  485. X
  486. X    /*
  487. X     * Get/create our GCs
  488. X     */
  489. X    CreateDrawGC(new);
  490. X    GetInverseGC(new);
  491. X    CreateDrawClipGC(new);
  492. X    CreateInverseClipGC(new);
  493. X    CreateTopShadowClipGC(new);
  494. X    CreateBottomShadowClipGC(new);
  495. X
  496. X    /*
  497. X     * Create ScrollMgrs to manage scrolling events
  498. X     */
  499. X    new->matrix.matrix_scroll_mgr = SmCreateScrollMgr();
  500. X    new->matrix.clip_scroll_mgr = SmCreateScrollMgr();
  501. X
  502. X    /*
  503. X     * Compute our size.  If either dimension was explicitly set to 0,
  504. X     * then that dimension is computed.
  505. X     * Use request because superclasses modify width/height.
  506. X     */
  507. X    if (request->core.width == 0 || request->core.height == 0)
  508. X    ComputeSize(new, request->core.width == 0, request->core.height == 0);
  509. X
  510. X    /*
  511. X     * Make sure top_row is sensible before we call Resize
  512. X     */
  513. X    if (VERT_ORIGIN(new) < 0)
  514. X    VERT_ORIGIN(new) = 0;
  515. X    else if (VERT_ORIGIN(new) > new->matrix.rows)
  516. X    VERT_ORIGIN(new) = new->matrix.rows;
  517. X
  518. X    /*
  519. X     * Tweak top_row to make sure it is valid before calling Resize
  520. X     */
  521. X    if (VERT_ORIGIN(new))
  522. X    AdjustTopRow(new);
  523. X
  524. X    /*
  525. X     * Layout the scrollbars and clip widget based on our size
  526. X     */
  527. X    Resize(new);
  528. }
  529. X
  530. static void
  531. Realize(mw, valueMask, attributes)
  532. XXbaeMatrixWidget mw;
  533. XXtValueMask *valueMask;
  534. XXSetWindowAttributes *attributes;
  535. {
  536. X    *valueMask |= CWDontPropagate;
  537. X    attributes->do_not_propagate_mask =
  538. X    ButtonPressMask | ButtonReleaseMask |
  539. X    KeyPressMask | KeyReleaseMask | PointerMotionMask;
  540. X
  541. X    /*
  542. X     * Don't call our superclasses realize method, because Manager sets
  543. X     * bit_gravity
  544. X     */
  545. X    XtCreateWindow((Widget)mw, InputOutput, CopyFromParent,
  546. X           *valueMask, attributes);
  547. X
  548. X    /*
  549. X     * Reparent the textFields window to be a subwindow of Clip widget
  550. X     * (we need to realize them first)
  551. X     */
  552. X    XtRealizeWidget(TextChild(mw));
  553. X    XtRealizeWidget(ClipChild(mw));
  554. X    XReparentWindow(XtDisplay(mw), XtWindow(TextChild(mw)),
  555. X            XtWindow(ClipChild(mw)), 0, 0);
  556. }
  557. X
  558. static void
  559. InsertChild(w)
  560. Widget w;
  561. {
  562. X    if (((CompositeWidget)XtParent(w))->composite.num_children > 3) {
  563. X    String params[1];
  564. X    Cardinal num_params = 1;
  565. X        params[0] = XtClass(XtParent(w))->core_class.class_name;
  566. X        XtAppWarningMsg(XtWidgetToApplicationContext(w),
  567. X                        "insertChild", "badChild", "XbaeMatrix",
  568. X                        "XbaeMatrix: Applications cannot add children to %s widgets",
  569. X                        params, &num_params);
  570. X        return;
  571. X    }
  572. X
  573. X    (*((XmManagerWidgetClass)
  574. X       (xbaeMatrixWidgetClass->core_class.superclass))->composite_class.
  575. X     insert_child) (w);
  576. }
  577. X
  578. /*
  579. X * Convert a pixel position to the column it is contained in.
  580. X */
  581. static int
  582. XXtoCol(mw, x)
  583. XXbaeMatrixWidget mw;
  584. int x;
  585. {
  586. X    int i;
  587. X
  588. X    for (i = 1; i < mw->matrix.columns; i++)
  589. X    if (mw->matrix.column_positions[i] > x)
  590. X        return i-1;
  591. X
  592. X    return i-1;
  593. }
  594. X
  595. /*
  596. X * Convert a row/column cell position to the x/y of its upper left corner
  597. X * wrt the window it will be drawn in (either the matrix window for
  598. X * fixed cells, or the clip window for non-fixed).
  599. X */
  600. static void
  601. RowColToXY(mw, row, column, x, y)
  602. XXbaeMatrixWidget mw;
  603. int row, column;
  604. int *x, *y;
  605. {
  606. X    /*
  607. X     * If we are in a fixed cell, calculate x/y relative to Matrixs
  608. X     * window (take into account labels etc)
  609. X     */
  610. X    if (column < mw->matrix.fixed_columns || row < mw->matrix.fixed_rows) {
  611. X
  612. X    /*
  613. X     * Ignore horiz_origin if we are in a fixed column
  614. X     */
  615. X    if (column < mw->matrix.fixed_columns)
  616. X        *x = COLUMN_LABEL_OFFSET(mw) + mw->matrix.column_positions[column];
  617. X    else
  618. X        *x = COLUMN_LABEL_OFFSET(mw) +
  619. X        mw->matrix.column_positions[column] - HORIZ_ORIGIN(mw);
  620. X
  621. X    /*
  622. X     * Ignore vert_origin if we are in a fixed row
  623. X     */
  624. X    if (row < mw->matrix.fixed_rows)
  625. X        *y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * row;
  626. X    else
  627. X        *y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) *
  628. X        (row - VERT_ORIGIN(mw));
  629. X    }
  630. X
  631. X    /*
  632. X     * If we are not fixed we must account for fixed rows/columns
  633. X     * and scrolling origins.
  634. X     */
  635. X    else {
  636. X    *x = (mw->matrix.column_positions[column] -
  637. X          mw->matrix.column_positions[mw->matrix.fixed_columns]) -
  638. X          HORIZ_ORIGIN(mw);
  639. X    *y = ROW_HEIGHT(mw) * ((row - (int)mw->matrix.fixed_rows) -
  640. X                   VERT_ORIGIN(mw));
  641. X    }
  642. }
  643. X
  644. /*
  645. X * Convert an x/y pixel position to the row/column cell position it picks.
  646. X * 'cell' specifies whether the x/y coord is relative to the fixed cells
  647. X * window or the non-fixed cells window.
  648. X * The coords x,y are adjusted so they are relative to the origin of the
  649. X * picked cell.
  650. X */
  651. static Boolean
  652. XXYToRowCol(mw, x, y, row, column, cell)
  653. XXbaeMatrixWidget mw;
  654. int *x, *y;
  655. int *row, *column;
  656. CellType cell;
  657. {
  658. X    Rectangle rect;
  659. X
  660. X    switch (cell) {
  661. X
  662. X    case FixedCell:
  663. X
  664. X    /*
  665. X     * Get the Rectangle enclosing the cells in fixed rows or columns.
  666. X     * If we don't have fixed rows or columns, then we didn't hit a cell.
  667. X     */
  668. X    if (mw->matrix.fixed_columns) {
  669. X        SETRECT(rect,
  670. X            COLUMN_LABEL_OFFSET(mw), ROW_LABEL_OFFSET(mw),
  671. X            FIXED_COLUMN_LABEL_OFFSET(mw) - 1,
  672. X            ROW_LABEL_OFFSET(mw) + VISIBLE_HEIGHT(mw) - 1);
  673. X    }
  674. X    else if (mw->matrix.fixed_rows) {
  675. X        SETRECT(rect,
  676. X            COLUMN_LABEL_OFFSET(mw), ROW_LABEL_OFFSET(mw),
  677. X            COLUMN_LABEL_OFFSET(mw) + VISIBLE_WIDTH(mw) - 1,
  678. X            FIXED_ROW_LABEL_OFFSET(mw) - 1);
  679. X    }
  680. X    else
  681. X        return False;
  682. X
  683. X    /*
  684. X     * If the point is in this rectangle, calculate the row/column
  685. X     * it hits. Otherwise we didn't hit a cell.
  686. X     */
  687. X    if (INBOX(rect, *x, *y)) {
  688. X
  689. X        /*
  690. X         * Translate the point to rect's coord system
  691. X         */
  692. X        *x -= rect.x1;
  693. X        *y -= rect.y1;
  694. X
  695. X        /*
  696. X         * Convert this point to a row/column. We only take into
  697. X         * account the scrolling origins if we are not fixed in that
  698. X         * dimension.
  699. X         */
  700. X        *row = YtoRow(mw, *y) + (mw->matrix.fixed_rows
  701. X                     ? 0
  702. X                     : VERT_ORIGIN(mw));
  703. X        *column = XtoCol(mw, *x + (mw->matrix.fixed_columns
  704. X                       ? 0
  705. X                       : HORIZ_ORIGIN(mw)));
  706. X
  707. X        /*
  708. X         * Sanity check the result
  709. X         */
  710. X        if ((mw->matrix.fixed_rows && *row >= mw->matrix.fixed_rows) ||
  711. X        (mw->matrix.fixed_columns && *column >=
  712. X         mw->matrix.fixed_columns) ||
  713. X        *row < 0 || *column < 0)
  714. X        return False;
  715. X
  716. X        /*
  717. X         * Adjust x,y so they are relative to this cells origin.
  718. X         */
  719. X        *x -= mw->matrix.column_positions[*column] -
  720. X        (mw->matrix.fixed_columns
  721. X         ? 0
  722. X         : HORIZ_ORIGIN(mw));
  723. X        *y %= ROW_HEIGHT(mw);
  724. X
  725. X        return True;
  726. X    }
  727. X    else
  728. X        return False;
  729. X
  730. X    /* NOTREACHED */
  731. X    break;
  732. X
  733. X    case NonFixedCell:
  734. X
  735. X    /*
  736. X     * Translate the point to take into account fixed rows or columns.
  737. X     */
  738. X    *x += FIXED_COLUMN_WIDTH(mw);
  739. X    *y += FIXED_ROW_HEIGHT(mw);
  740. X
  741. X    /*
  742. X     * Convert the new point to a row/column position
  743. X     */
  744. X    *row = YtoRow(mw, *y) + VERT_ORIGIN(mw);
  745. X    *column = XtoCol(mw, *x + HORIZ_ORIGIN(mw));
  746. X
  747. X    /*
  748. X     * Sanity check the result
  749. X     */
  750. X    if (*row >= mw->matrix.rows || *column >= mw->matrix.columns ||
  751. X        *row < 0 || *column < 0)
  752. X        return False;
  753. X
  754. X    /*
  755. X     * Adjust x,y so they are relative to this cells origin.
  756. X     */
  757. X    *x -= mw->matrix.column_positions[*column] - HORIZ_ORIGIN(mw);
  758. X    *y %= ROW_HEIGHT(mw);
  759. X
  760. X    return True;
  761. X        
  762. X    /* NOTREACHED */
  763. X    break;
  764. X
  765. X    default:
  766. X    return False;
  767. X    }
  768. }
  769. X
  770. /*
  771. X * Width in pixels of a character in a given font
  772. X */
  773. #define charWidth(fs,c) ((fs)->per_char\
  774. X                         ? (fs)->per_char[(unsigned char)(c) -\
  775. X                                          (fs)->min_char_or_byte2].width\
  776. X                         : (fs)->min_bounds.width)
  777. X
  778. X
  779. /*
  780. X * Draw a string with specified attributes. We want to avoid having to
  781. X * use a GC clip_mask, so we clip by characters. This complicates the code.
  782. X */
  783. static void
  784. DrawString(mw, win, string, length, x, y, maxlen, alignment, highlight,
  785. X       bold, clip, color)
  786. XXbaeMatrixWidget mw;
  787. Window win;
  788. String string;
  789. int length;
  790. int x, y;
  791. int maxlen;
  792. unsigned char alignment;
  793. Boolean highlight;
  794. Boolean bold;
  795. Boolean clip;
  796. Pixel color;
  797. {
  798. X    int start, width, maxwidth;
  799. X    GC gc;
  800. X
  801. X    /*
  802. X     * Initialize starting character in string
  803. X     */
  804. X    start = 0;
  805. X
  806. X    /*
  807. X     * Calculate max width in pixels and actual pixel width of string.
  808. X     * XXX XTextWidth only sums the width of each char.     A char could
  809. X     * have an rbearing greater than the width.     So we might not clip
  810. X     * a char which really should be.
  811. X     */
  812. X    maxwidth = maxlen * FONT_WIDTH(mw);
  813. X    width = XTextWidth(mw->matrix.font, string, length);
  814. X
  815. X    /*
  816. X     * If the width of the string is greater than the width of this cell,
  817. X     * we need to clip. We don't want to use the server to clip because
  818. X     * it is slow, so we truncate characters if we exceed a cells pixel width.
  819. X     */
  820. X    if (width > maxwidth) {
  821. X    
  822. X    switch (alignment) {
  823. X
  824. X    case XmALIGNMENT_CENTER: {
  825. X        int startx = x;
  826. X        int endx = x + maxwidth - 1;
  827. X        int newendx;
  828. X
  829. X        /*
  830. X         * Figure out our x for the centered string.  Then loop and chop
  831. X         * characters off the front until we are within the cell.
  832. X         * Adjust x, the starting character and the length of the string
  833. X         * for each char.
  834. X         */
  835. X        x += maxwidth / 2 - width / 2;
  836. X        while (x < startx) {
  837. X        int cw = charWidth(mw->matrix.font, string[start]);
  838. X        x += cw;
  839. X        width -= cw;
  840. X        length--;
  841. X        start++;
  842. X        }
  843. X
  844. X        /*
  845. X         * Now figure out the end x of the string.    Then loop and chop
  846. X         * characters off the end until we are within the cell.
  847. X         */
  848. X        newendx = x + width - 1;
  849. X        while (newendx > endx) {
  850. X        newendx -= charWidth(mw->matrix.font,
  851. X                     string[start + length - 1]);
  852. X        length--;
  853. X        }
  854. X
  855. X        break;
  856. X    }
  857. X
  858. X    case XmALIGNMENT_END: {
  859. X
  860. X        /*
  861. X         * Figure out our x for the right justified string.
  862. X         * Then loop and chop characters off the front until we fit.
  863. X         * Adjust x for each char lopped off. Also adjust the starting
  864. X         * character and length of the string for each char.
  865. X         */
  866. X        x += maxwidth - width;
  867. X        while (width > maxwidth) {
  868. X        int cw = charWidth(mw->matrix.font, string[start]);
  869. X        width -= cw;
  870. X        x += cw;
  871. X        length--;
  872. X        start++;
  873. X        }
  874. X        break;
  875. X    }
  876. X
  877. X    case XmALIGNMENT_BEGINNING:
  878. X    default:
  879. X        /*
  880. X         * Leave x alone, but chop characters off the end until we fit
  881. X         */
  882. X        while (width > maxwidth) {
  883. X        width -= charWidth(mw->matrix.font, string[length - 1]);
  884. X        length--;
  885. X        }
  886. X        break;
  887. X    }
  888. X    }
  889. X
  890. X    /*
  891. X     * We fit inside our cell, so just compute the x of the start of our string
  892. X     */
  893. X    else {
  894. X    switch (alignment) {
  895. X
  896. X    case XmALIGNMENT_CENTER:
  897. X        x += maxwidth / 2 - width / 2;
  898. X        break;
  899. X
  900. X    case XmALIGNMENT_END:
  901. X        x += maxwidth - width;
  902. X        break;
  903. X
  904. X    case XmALIGNMENT_BEGINNING:
  905. X    default:
  906. X        /*
  907. X         * Leave x alone
  908. X         */
  909. X        break;
  910. X    }
  911. X    }
  912. X
  913. X    /*
  914. X     * Figure out which GC to use
  915. X     */
  916. X    if (highlight) {
  917. X    if (clip)
  918. X        gc = mw->matrix.inverse_clip_gc;
  919. X    else
  920. X        gc = mw->matrix.inverse_gc;
  921. X    }
  922. X    else {
  923. X    if (clip)
  924. X        gc = mw->matrix.draw_clip_gc;
  925. X    else
  926. X        gc = mw->matrix.draw_gc;
  927. X    }
  928. X
  929. X    /*
  930. X     * Don't worry, XSetForeground is smart about avoiding unnecessary
  931. X     * protocol requests.
  932. X     */
  933. X    if (!highlight)
  934. X    XSetForeground(XtDisplay(mw), gc, color);
  935. X
  936. X    /*
  937. X     * Now draw the string at x starting at char 'start' and of length 'length'
  938. X     */
  939. X    XDrawString(XtDisplay(mw), win, gc, x, y, &string[start], length);
  940. X
  941. X    /*
  942. X     * If bold is on, draw the string again offset by 1 pixel (overstrike)
  943. X     */
  944. X    if (bold)
  945. X    XDrawString(XtDisplay(mw), win, gc, x - 1, y, &string[start], length);
  946. }
  947. X
  948. /*
  949. X * Draw the column label for the specified column.  Handles labels in
  950. X * fixed and non-fixed columns.
  951. X */
  952. static void
  953. DrawColumnLabel(mw, column)
  954. XXbaeMatrixWidget mw;
  955. int column;
  956. {
  957. X    String label;
  958. X    int x, y, i;
  959. X
  960. X    if (mw->matrix.column_labels[column][0] == '\0')
  961. X    return;
  962. X
  963. X    /*
  964. X     * If the column label is in a fixed column, we don't need to account
  965. X     * for the horiz_origin
  966. X     */
  967. X    if (column < mw->matrix.fixed_columns)
  968. X    x = COLUMN_LABEL_OFFSET(mw) + mw->matrix.column_positions[column] +
  969. X        TEXT_X_OFFSET(mw);
  970. X    else
  971. X    x = COLUMN_LABEL_OFFSET(mw) + (mw->matrix.column_positions[column] -
  972. X                       HORIZ_ORIGIN(mw)) + TEXT_X_OFFSET(mw);
  973. X
  974. X    /*
  975. X     * Set our y to the baseline of the first line in this column
  976. X     */
  977. X    y = TEXT_Y_OFFSET(mw) + (mw->matrix.column_label_maxlines -
  978. X                 mw->matrix.column_label_lines[column].lines) *
  979. X                 TEXT_HEIGHT(mw);
  980. X
  981. X    label = mw->matrix.column_labels[column];
  982. X    for (i = 0; i < mw->matrix.column_label_lines[column].lines; i++) {
  983. X    DrawString(mw, XtWindow(mw),
  984. X           label, mw->matrix.column_label_lines[column].lengths[i],
  985. X           x, y,
  986. X           mw->matrix.column_widths[column],
  987. X           mw->matrix.column_label_alignments
  988. X           ? mw->matrix.column_label_alignments[column]
  989. X           : XmALIGNMENT_BEGINNING,
  990. X           False,
  991. X           mw->matrix.bold_labels,
  992. X           column >= mw->matrix.fixed_columns,
  993. X           mw->manager.foreground);
  994. X    y += TEXT_HEIGHT(mw);
  995. X    label += mw->matrix.column_label_lines[column].lengths[i] + 1;
  996. X    }
  997. }
  998. X
  999. /*
  1000. X * Draw the row label for the specified row. Handles labels in fixed and
  1001. X * non-fixed rows.
  1002. X */
  1003. static void
  1004. DrawRowLabel(mw, row)
  1005. XXbaeMatrixWidget mw;
  1006. int row;
  1007. {
  1008. X    int y;
  1009. X
  1010. X    if (mw->matrix.row_labels[row][0] == '\0')
  1011. X    return;
  1012. X
  1013. X    /*
  1014. X     * If the row label is in a fixed row we don't need to account
  1015. X     * for the vert_origin
  1016. X     */
  1017. X    if (row < mw->matrix.fixed_rows)
  1018. X    y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * row + TEXT_Y_OFFSET(mw);
  1019. X    else
  1020. X    y = ROW_LABEL_OFFSET(mw) + ROW_HEIGHT(mw) * (row - VERT_ORIGIN(mw)) +
  1021. X        TEXT_Y_OFFSET(mw);
  1022. X
  1023. X    DrawString(mw, XtWindow(mw),
  1024. X           mw->matrix.row_labels[row],
  1025. X           strlen(mw->matrix.row_labels[row]),
  1026. X           TEXT_X_OFFSET(mw), y,
  1027. X           mw->matrix.row_label_width,
  1028. X           mw->matrix.row_label_alignment,
  1029. X           False,
  1030. X           mw->matrix.bold_labels,
  1031. X           False,
  1032. X           mw->manager.foreground);
  1033. }
  1034. X
  1035. /*
  1036. X * Draw a fixed or non-fixed cell. The coordinates are calculated relative
  1037. X * to the correct window and the cell is drawn in that window.
  1038. X */
  1039. static void
  1040. DrawCell(mw, row, column)
  1041. XXbaeMatrixWidget mw;
  1042. int row, column;
  1043. {
  1044. X    int x, y;
  1045. X    Pixel color;
  1046. X    Window win = CELL_WINDOW(mw, row, column);
  1047. X    Boolean clipped = row < mw->matrix.fixed_rows;
  1048. X
  1049. X    if (!win)
  1050. X    return;
  1051. X
  1052. X    /*
  1053. X     * Convert the row/column to the coordinates relative to the correct
  1054. X     * window
  1055. X     */
  1056. X    RowColToXY(mw, row, column, &x, &y);
  1057. X
  1058. X    /*
  1059. X     * Figure out what color this cell is
  1060. X     */
  1061. X    if (mw->matrix.colors)
  1062. X    color = mw->matrix.colors[row][column];
  1063. X    else
  1064. X    color = mw->manager.foreground;
  1065. X
  1066. X    /*
  1067. X     * If this cell is selected, fill the cell with the foreground color
  1068. X     */
  1069. X    if (mw->matrix.selected_cells[row][column]) {
  1070. X    GC gc = (clipped
  1071. X         ? mw->matrix.draw_clip_gc
  1072. X         : mw->matrix.draw_gc);
  1073. X
  1074. X    /*
  1075. X     * Don't worry, XSetForeground is smart about avoiding
  1076. X     * unnecessary protocol requests.
  1077. X     */
  1078. X    XSetForeground(XtDisplay(mw), gc, color);
  1079. X
  1080. X    XFillRectangle(XtDisplay(mw), win,
  1081. X               gc,
  1082. X               x + (mw->matrix.cell_highlight_thickness +
  1083. X                mw->matrix.cell_shadow_thickness),
  1084. X               y + (mw->matrix.cell_highlight_thickness +
  1085. X                mw->matrix.cell_shadow_thickness),
  1086. X               COLUMN_WIDTH(mw, column) -
  1087. X                (mw->matrix.cell_highlight_thickness +
  1088. X                 mw->matrix.cell_shadow_thickness) * 2,
  1089. X               ROW_HEIGHT(mw) -
  1090. X                (mw->matrix.cell_highlight_thickness +
  1091. X                 mw->matrix.cell_shadow_thickness) * 2);
  1092. X    }
  1093. X
  1094. X    /*
  1095. X     * Draw the string in the cell.
  1096. X     */
  1097. X    if (*mw->matrix.cells[row][column] != '\0') {
  1098. X    DrawString(mw, win,
  1099. X           mw->matrix.cells[row][column],
  1100. X           strlen(mw->matrix.cells[row][column]),
  1101. X           x + TEXT_X_OFFSET(mw), y + TEXT_Y_OFFSET(mw),
  1102. X           mw->matrix.column_widths[column],
  1103. X           mw->matrix.column_alignments
  1104. X           ? mw->matrix.column_alignments[column]
  1105. X           : XmALIGNMENT_BEGINNING,
  1106. X           mw->matrix.selected_cells[row][column],
  1107. X           False, clipped, color);
  1108. X    }
  1109. X
  1110. X    /*
  1111. X     * Surround the cell with a shadow.
  1112. X     */
  1113. X    if (mw->matrix.cell_shadow_thickness) {
  1114. X    if (clipped)
  1115. X        _XmDrawShadow(XtDisplay(mw), win,
  1116. X              mw->matrix.cell_bottom_shadow_clip_gc,
  1117. X              mw->matrix.cell_top_shadow_clip_gc,
  1118. X              mw->matrix.cell_shadow_thickness,
  1119. X              x + (int)mw->matrix.cell_highlight_thickness,
  1120. X              y + (int)mw->matrix.cell_highlight_thickness,
  1121. X              COLUMN_WIDTH(mw, column) -
  1122. X                2 * mw->matrix.cell_highlight_thickness,
  1123. X              ROW_HEIGHT(mw) -
  1124. X                2 * mw->matrix.cell_highlight_thickness);
  1125. X    else
  1126. X        _XmDrawShadow(XtDisplay(mw), win,
  1127. X              mw->manager.bottom_shadow_GC,
  1128. X              mw->manager.top_shadow_GC,
  1129. X              mw->matrix.cell_shadow_thickness,
  1130. X              x + (int)mw->matrix.cell_highlight_thickness,
  1131. X              y + (int)mw->matrix.cell_highlight_thickness,
  1132. X              COLUMN_WIDTH(mw, column) -
  1133. X                2 * mw->matrix.cell_highlight_thickness,
  1134. X              ROW_HEIGHT(mw) -
  1135. X                2 * mw->matrix.cell_highlight_thickness);
  1136. X    }
  1137. }
  1138. X
  1139. /*
  1140. X * Redraw the row and column labels and the cells in fixed rows/columns
  1141. X * that are overlapped by the Rectangle argument.
  1142. X */
  1143. static void
  1144. RedrawLabelsAndFixed(mw, expose)
  1145. XXbaeMatrixWidget mw;
  1146. Rectangle *expose;
  1147. {
  1148. X    /*
  1149. X     * Handle the row labels that are in fixed rows
  1150. X     */
  1151. X    if (mw->matrix.fixed_rows && mw->matrix.row_labels) {
  1152. X    Rectangle rect;
  1153. X
  1154. X    /*
  1155. X     * Get the Rectangle enclosing the fixed row labels
  1156. X     */
  1157. X    SETRECT(rect,
  1158. X        0, ROW_LABEL_OFFSET(mw),
  1159. X        ROW_LABEL_WIDTH(mw) - 1, FIXED_ROW_LABEL_OFFSET(mw) - 1);
  1160. X
  1161. X    /*
  1162. X     * If the expose Rectangle overlaps, then some labels must be redrawn
  1163. X     */
  1164. X    if (OVERLAP(*expose, rect)) {
  1165. X        Rectangle intersect;
  1166. X        int endRow, i;
  1167. X
  1168. X        /*
  1169. X         * Intersect the fixed-row-labels Rectangle with the expose
  1170. X         * Rectangle along the Y axis.  The resulting Rectangle will
  1171. X         * be in 'rect's coordinate system.
  1172. X         */
  1173. X        Y_INTERSECT(rect, *expose, intersect);
  1174. X
  1175. X        /*
  1176. X         * Redraw each label that was intersected
  1177. X         */
  1178. X        endRow = YtoRow(mw, intersect.y2);
  1179. X        for (i = YtoRow(mw, intersect.y1); i <= endRow; i++)
  1180. X        DrawRowLabel(mw, i);
  1181. X    }
  1182. X    }
  1183. X
  1184. X    /*
  1185. X     * Handle row labels that aren't in fixed rows
  1186. X     */
  1187. X    if (mw->matrix.row_labels) {
  1188. X    Rectangle rect;
  1189. X
  1190. X    /*
  1191. X     * Get the Rectangle enclosing the non-fixed row labels
  1192. X     */
  1193. X    SETRECT(rect,
  1194. X        0, FIXED_ROW_LABEL_OFFSET(mw),
  1195. X        ROW_LABEL_WIDTH(mw) - 1,
  1196. X        FIXED_ROW_LABEL_OFFSET(mw) + VISIBLE_HEIGHT(mw) - 1);
  1197. X
  1198. X    /*
  1199. X     * If the expose Rectangle overlaps, then some labels must be redrawn
  1200. X     */
  1201. X    if (OVERLAP(*expose, rect)) {
  1202. X        Rectangle intersect;
  1203. X        int endRow, i;
  1204. X
  1205. X        /*
  1206. X         * Intersect the fixed-row-labels Rectangle with the expose
  1207. X         * Rectangle along the Y axis.  The resulting Rectangle will
  1208. X         * be in 'rect's coordinate system.
  1209. X         */
  1210. X        Y_INTERSECT(rect, *expose, intersect);
  1211. X
  1212. X        /*
  1213. X         * Translate 'intersect' to take into account any fixed rows.
  1214. X         * This gets it back into the coord system expected by YtoRow().
  1215. X         */
  1216. X        intersect.y1 += FIXED_ROW_HEIGHT(mw);
  1217. X        intersect.y2 += FIXED_ROW_HEIGHT(mw);
  1218. X    
  1219. X        /*
  1220. X         * Redraw each label that was intersected
  1221. X         */
  1222. X        endRow = YtoRow(mw, intersect.y2) + VERT_ORIGIN(mw);
  1223. X        for (i = YtoRow(mw, intersect.y1) + VERT_ORIGIN(mw);
  1224. X         i <= endRow;
  1225. X         i++)
  1226. X        DrawRowLabel(mw, i);
  1227. X    }
  1228. X    }
  1229. X
  1230. X    /*
  1231. X     * Handle the column labels that are in fixed columns
  1232. X     */
  1233. X    if (mw->matrix.fixed_columns && mw->matrix.column_labels) {
  1234. X    Rectangle rect;
  1235. X
  1236. X    /*
  1237. X     * Get the Rectangle enclosing the portion of the column labels
  1238. X     * that are in fixed columns
  1239. X     */
  1240. X    SETRECT(rect,
  1241. X        COLUMN_LABEL_OFFSET(mw), 0,
  1242. X        FIXED_COLUMN_LABEL_OFFSET(mw) - 1,
  1243. X        COLUMN_LABEL_HEIGHT(mw) - 1);
  1244. X
  1245. X    /*
  1246. X     * If the expose Rectangle overlaps, then some labels must be redrawn
  1247. X     */
  1248. X    if (OVERLAP(*expose, rect)) {
  1249. X        Rectangle intersect;
  1250. X        int endCol, i;
  1251. X
  1252. X        /*
  1253. X         * Intersect the fixed-column-labels Rectangle with the expose
  1254. X         * Rectangle along the X axis.  The resulting Rectangle will
  1255. X         * be in 'rect's coordinate system.
  1256. X         */
  1257. X        X_INTERSECT(rect, *expose, intersect);
  1258. X
  1259. X        /*
  1260. X         * Redraw each label that was intersected
  1261. X         */
  1262. X        endCol = XtoCol(mw, intersect.x2);
  1263. X        for (i = XtoCol(mw, intersect.x1); i <= endCol; i++)
  1264. X        DrawColumnLabel(mw, i);
  1265. X    }
  1266. X    }
  1267. X
  1268. X    /*
  1269. X     * Handle column labels that aren't in fixed columns
  1270. X     */
  1271. X    if (mw->matrix.column_labels) {
  1272. X    Rectangle rect;
  1273. X
  1274. X    /*
  1275. X     * Get the Rectangle enclosing the non-fixed column labels
  1276. X     */
  1277. X    SETRECT(rect,
  1278. X        FIXED_COLUMN_LABEL_OFFSET(mw), 0,
  1279. X        FIXED_COLUMN_LABEL_OFFSET(mw) + VISIBLE_WIDTH(mw) - 1,
  1280. X        COLUMN_LABEL_HEIGHT(mw) - 1);
  1281. X
  1282. X    /*
  1283. X     * If the expose Rectangle overlaps, then some labels must be redrawn
  1284. X     */
  1285. X    if (OVERLAP(*expose, rect)) {
  1286. X        Rectangle intersect;
  1287. X        int endCol, i;
  1288. X
  1289. X        /*
  1290. X         * Intersect the non-fixed-column-labels Rectangle with the expose
  1291. X         * Rectangle along the X axis.  The resulting Rectangle will
  1292. X         * be in 'rect's coordinate system.
  1293. X         */
  1294. X        X_INTERSECT(rect, *expose, intersect);
  1295. X
  1296. X        /*
  1297. X         * Translate 'intersect' to take into account any fixed columns.
  1298. X         * This gets it back into the coord system expected by XtoCol().
  1299. X         */
  1300. X        intersect.x1 += FIXED_COLUMN_WIDTH(mw);
  1301. X        intersect.x2 += FIXED_COLUMN_WIDTH(mw);
  1302. X
  1303. X        /*
  1304. X         * Redraw each label that was intersected
  1305. X         */
  1306. X        endCol = XtoCol(mw, intersect.x2 + HORIZ_ORIGIN(mw));
  1307. X        for (i = XtoCol(mw, intersect.x1 + HORIZ_ORIGIN(mw));
  1308. X         i <= endCol;
  1309. X         i++)
  1310. X        DrawColumnLabel(mw, i);
  1311. X    }
  1312. X    }
  1313. X
  1314. X    /*
  1315. X     * Handle cells in fixed rows or fixed columns
  1316. X     */
  1317. X    if (mw->matrix.fixed_rows || mw->matrix.fixed_columns) {
  1318. X    Rectangle rect;
  1319. X
  1320. X    /*
  1321. X     * Get the Rectangle enclosing the cells in fixed rows or columns
  1322. X     */
  1323. X    if (mw->matrix.fixed_columns) {
  1324. X        SETRECT(rect,
  1325. X            COLUMN_LABEL_OFFSET(mw), ROW_LABEL_OFFSET(mw),
  1326. X            FIXED_COLUMN_LABEL_OFFSET(mw) - 1,
  1327. X            ROW_LABEL_OFFSET(mw) + VISIBLE_HEIGHT(mw) - 1);
  1328. X    }
  1329. X    else if (mw->matrix.fixed_rows) {
  1330. X        SETRECT(rect,
  1331. X            COLUMN_LABEL_OFFSET(mw), ROW_LABEL_OFFSET(mw),
  1332. X            COLUMN_LABEL_OFFSET(mw) + VISIBLE_WIDTH(mw) - 1,
  1333. X            FIXED_ROW_LABEL_OFFSET(mw) - 1);
  1334. X    }
  1335. X
  1336. X    /*
  1337. X     * If the expose Rectangle overlaps, then some cells must be redrawn
  1338. X     */
  1339. X    if (OVERLAP(*expose, rect)) {
  1340. X        Rectangle intersect;
  1341. X        int startCol, endCol, startRow, endRow, i, j;
  1342. X
  1343. X        /*
  1344. X         * Intersect the fixed-cells Rectangle with the expose
  1345. X         * Rectangle along the X and Y axis.  The resulting Rectangle will
  1346. X         * be in 'rect's coordinate system.
  1347. X         */
  1348. X        INTERSECT(rect, *expose, intersect);
  1349. X
  1350. X        /*
  1351. X         * Get starting and ending rows/columns.  We only take into
  1352. X         * account the scrolling origins if we are not fixed in that
  1353. X         * dimension.
  1354. X         */
  1355. X        startCol = XtoCol(mw, intersect.x1 +
  1356. X                  (mw->matrix.fixed_columns
  1357. X                   ? 0
  1358. X                   : HORIZ_ORIGIN(mw)));
  1359. X        endCol = XtoCol(mw, intersect.x2 +
  1360. X                (mw->matrix.fixed_columns
  1361. X                 ? 0
  1362. X                 : HORIZ_ORIGIN(mw)));
  1363. X        startRow = YtoRow(mw, intersect.y1) +
  1364. X        (mw->matrix.fixed_rows
  1365. X         ? 0
  1366. X         : VERT_ORIGIN(mw));
  1367. X        endRow = YtoRow(mw, intersect.y2) +
  1368. X        (mw->matrix.fixed_rows
  1369. X         ? 0
  1370. X         : VERT_ORIGIN(mw));
  1371. X
  1372. X        /*
  1373. X         * Redraw each cell that was intersected
  1374. X         */
  1375. X        for (i = startRow; i <= endRow; i++)
  1376. X        for (j = startCol; j <= endCol; j++)
  1377. X            DrawCell(mw, i, j);
  1378. X    }
  1379. X    }
  1380. X
  1381. X    /*
  1382. X     * Draw a shadow just inside row/column labels and around outer edge
  1383. X     * of clip widget.    We can't use height of clip widget because it is
  1384. X     * truncated to nearest row.  We use cell_visible_height instead.
  1385. X     */
  1386. X    if (mw->manager.shadow_thickness)
  1387. X    _XmDrawShadow(XtDisplay(mw), XtWindow(mw),
  1388. X              mw->manager.bottom_shadow_GC,
  1389. X              mw->manager.top_shadow_GC,
  1390. X              mw->manager.shadow_thickness,
  1391. X              ROW_LABEL_WIDTH(mw),
  1392. X              COLUMN_LABEL_HEIGHT(mw),
  1393. X              ClipChild(mw)->core.width + FIXED_COLUMN_WIDTH(mw) +
  1394. X              2 * mw->manager.shadow_thickness,
  1395. X              mw->matrix.cell_visible_height + FIXED_ROW_HEIGHT(mw) +
  1396. X              2 * mw->manager.shadow_thickness);
  1397. }
  1398. X
  1399. /*
  1400. X * This is the expose method for the Matrix widget.
  1401. X * It redraws the row and column labels, the cells in fixed rows and columns
  1402. X * and the clip window shadow.
  1403. X */
  1404. /* ARGSUSED */
  1405. static void
  1406. Redisplay(mw, event, region)
  1407. XXbaeMatrixWidget mw;
  1408. XXEvent *event;
  1409. Region region;
  1410. {
  1411. X    Rectangle expose;
  1412. X
  1413. X    /*
  1414. X     * Send our events to the mw ScrollMgr to be adjusted.
  1415. X     */
  1416. X    switch (event->type) {
  1417. X
  1418. X    case Expose:
  1419. X    /*
  1420. X     * The Expose event will be translated into our scrolled
  1421. X     * coordinate system.  Then it is put in a Rectangle.
  1422. X     */
  1423. X    SmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
  1424. X    SETRECT(expose,
  1425. X        event->xexpose.x, event->xexpose.y,
  1426. X        event->xexpose.x + event->xexpose.width,
  1427. X        event->xexpose.y + event->xexpose.height);
  1428. X    break;
  1429. X
  1430. X    case GraphicsExpose:
  1431. X    /*
  1432. X     * The GraphicsExpose event will cause a scroll to be removed
  1433. X     * from the managers queue, then the event will be translated
  1434. X     * into our scrolled coordinate system.     Then it is put in a Rectangle.
  1435. X     */
  1436. X    SmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
  1437. X    SETRECT(expose,
  1438. X        event->xgraphicsexpose.x, event->xgraphicsexpose.y,
  1439. X        event->xgraphicsexpose.x + event->xgraphicsexpose.width,
  1440. X        event->xgraphicsexpose.y + event->xgraphicsexpose.height);
  1441. X    break;
  1442. X
  1443. X    case NoExpose:
  1444. X    /*
  1445. X     * The NoExpose event means we won't be getting any GraphicsExpose
  1446. X     * events, so the scroll well be removed from the queue and
  1447. X     * we are done.
  1448. X     */
  1449. X    SmScrollEvent(mw->matrix.matrix_scroll_mgr, event);
  1450. X    return;
  1451. X
  1452. X    default:
  1453. X    return;
  1454. X    }
  1455. X
  1456. X    /*
  1457. X     * Redraw the row/column labels and fixed rows/columns which are
  1458. X     * overlapped by the expose Rectangle.
  1459. X     */
  1460. X    RedrawLabelsAndFixed(mw, &expose);
  1461. }
  1462. X
  1463. /*
  1464. X * Redraw all cells in the clip widget damaged by the passed Rectangle.
  1465. X * The Rectangle must be within the bounds of the cells. These are the
  1466. X * non-fixed cells.
  1467. X */
  1468. static void
  1469. RedrawCells(mw, expose)
  1470. XXbaeMatrixWidget mw;
  1471. Rectangle *expose;
  1472. {
  1473. X    int startCol, endCol, startRow, endRow, i, j;
  1474. X    Rectangle rect;
  1475. X
  1476. X    /*
  1477. X     * Translate the 'expose' Rectangle to take into account the
  1478. X     * fixed rows or columns.
  1479. X     */
  1480. X    SETRECT(rect,
  1481. X        expose->x1 + FIXED_COLUMN_WIDTH(mw),
  1482. X        expose->y1 + FIXED_ROW_HEIGHT(mw),
  1483. X        expose->x2 + FIXED_COLUMN_WIDTH(mw),
  1484. X        expose->y2 + FIXED_ROW_HEIGHT(mw));
  1485. X
  1486. X    /*
  1487. X     * Calculate the starting and ending rows/columns of the cells
  1488. X     * which must be redrawn.
  1489. X     */
  1490. X    startCol = XtoCol(mw, rect.x1 + HORIZ_ORIGIN(mw));
  1491. X    endCol = XtoCol(mw, rect.x2 + HORIZ_ORIGIN(mw));
  1492. X    startRow = YtoRow(mw, rect.y1) + VERT_ORIGIN(mw);
  1493. X    endRow = YtoRow(mw, rect.y2) + VERT_ORIGIN(mw);
  1494. X
  1495. X    /*
  1496. X     * Redraw all cells which were exposed.
  1497. X     */
  1498. X    for (i = startRow; i <= endRow; i++)
  1499. X    for (j = startCol; j <= endCol; j++)
  1500. X        DrawCell(mw, i, j);
  1501. }
  1502. X
  1503. /*
  1504. X * This is the exposeProc function for the Clip widget.
  1505. X * It handles expose events for the Clip widget by redrawing those
  1506. X * non-fixed cells which were damaged.
  1507. X * It recieves Expose, GraphicsExpose and NoExpose events.
  1508. X */
  1509. /* ARGSUSED */
  1510. static void
  1511. ClipRedisplay(w, event, region)
  1512. Widget w;
  1513. XXEvent *event;
  1514. Region region;
  1515. {
  1516. X    XbaeMatrixWidget mw = (XbaeMatrixWidget) XtParent(w);
  1517. X    Rectangle expose, clip, intersect;
  1518. X
  1519. X    /*
  1520. X     * Send our events to the clip ScrollMgr to be adjusted.
  1521. X     */
  1522. X    switch (event->type) {
  1523. X
  1524. X    case Expose:
  1525. X    /*
  1526. X     * The Expose event will be translated into our scrolled
  1527. X     * coordinate system.  Then it is put in a Rectangle.
  1528. X     */
  1529. X    SmScrollEvent(mw->matrix.clip_scroll_mgr, event);
  1530. X    SETRECT(expose,
  1531. X        event->xexpose.x, event->xexpose.y,
  1532. X        event->xexpose.x + event->xexpose.width - 1,
  1533. X        event->xexpose.y + event->xexpose.height - 1);
  1534. X    break;
  1535. X
  1536. X    case GraphicsExpose:
  1537. X    /*
  1538. X     * The GraphicsExpose event will cause a scroll to be removed
  1539. X     * from the managers queue, then the event will be translated
  1540. X     * into our scrolled coordinate system.     Then it is put in a Rectangle.
  1541. X     */
  1542. X    SmScrollEvent(mw->matrix.clip_scroll_mgr, event);
  1543. X    SETRECT(expose,
  1544. X        event->xgraphicsexpose.x, event->xgraphicsexpose.y,
  1545. X        event->xgraphicsexpose.x + event->xgraphicsexpose.width - 1,
  1546. X        event->xgraphicsexpose.y + event->xgraphicsexpose.height - 1);
  1547. X    break;
  1548. X
  1549. X    case NoExpose:
  1550. X    /*
  1551. X     * The NoExpose event means we won't be getting any GraphicsExpose
  1552. X     * events, so the scroll well be removed from the queue and
  1553. X     * we are done.
  1554. X     */
  1555. X    SmScrollEvent(mw->matrix.clip_scroll_mgr, event);
  1556. X    return;
  1557. X
  1558. X    default:
  1559. X    return;
  1560. X    }
  1561. X
  1562. X    /*
  1563. X     * We may get an expose event larger than the size of the Clip widget.
  1564. X     * This is because in set_values we may clear the Clip widget
  1565. X     * before it gets resized smaller (maybe in set_values_almost).
  1566. X     * So here we intersect the expose event with the clip widget
  1567. X     * to ensure the expose Rectangle is not larger than the Clip widget.
  1568. X     */
  1569. X    SETRECT(clip,
  1570. X        0, 0,
  1571. X        w->core.width - 1, w->core.height - 1);
  1572. X    INTERSECT(clip, expose, intersect);
  1573. X
  1574. X    /*
  1575. X     * Redraw those cells which overlap the intersect Rectangle.
  1576. X     */
  1577. X    RedrawCells(mw, &intersect);
  1578. }
  1579. X
  1580. X
  1581. /* ARGSUSED */
  1582. static Boolean
  1583. SetValues(current, request, new, args, num_args)
  1584. XXbaeMatrixWidget current, request, new;
  1585. ArgList args;
  1586. Cardinal *num_args;
  1587. {
  1588. X    Boolean redisplay = False;        /* need to redraw */
  1589. X    Boolean relayout = False;        /* need to layout, but same size */
  1590. X    Boolean new_column_widths = False;    /* column widths changed */
  1591. X    Boolean new_cells = False;        /* cells changed */
  1592. X    Boolean do_top_row = False;        /* reset top_row */
  1593. X    int n;
  1594. X    Arg wargs[9];
  1595. X
  1596. #define NE(field)    (current->field != new->field)
  1597. #define EQ(field)    (current->field == new->field)
  1598. X
  1599. X
  1600. X
  1601. X    /*
  1602. X     * If rows changed, then:
  1603. X     *    row_labels must change or be NULL
  1604. X     */
  1605. X    if (NE(matrix.rows) &&
  1606. X     (new->matrix.row_labels && EQ(matrix.row_labels))) {
  1607. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1608. X            "setValues", "rows",
  1609. X            "XbaeMatrix",
  1610. X            "XbaeMatrix: Number of rows changed but dependent resources did not",
  1611. X            NULL, 0);
  1612. X    new->matrix.rows = current->matrix.rows;
  1613. X    new->matrix.row_labels = current->matrix.row_labels;
  1614. X    }
  1615. X
  1616. X    /*
  1617. X     * If columns changed, then:
  1618. X     *    column_widths must change
  1619. X     *    column_max_lengths must change or be NULL
  1620. X     *    column_labels must change or be NULL
  1621. X     *    column_alignments must change or be NULL
  1622. X     *    column_label_alignments must change or be NULL
  1623. X     */
  1624. X    if (NE(matrix.columns) &&
  1625. X     ((new->matrix.column_labels && EQ(matrix.column_labels)) ||
  1626. X      (new->matrix.column_max_lengths && EQ(matrix.column_max_lengths)) ||
  1627. X      (new->matrix.column_alignments && EQ(matrix.column_alignments)) ||
  1628. X      (new->matrix.column_label_alignments &&
  1629. X       EQ(matrix.column_label_alignments)) ||
  1630. X      EQ(matrix.column_widths))) {
  1631. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1632. X            "setValues", "columns", "XbaeMatrix",
  1633. X            "XbaeMatrix: Number of columns changed but dependent resources did not",
  1634. X            NULL, 0);
  1635. X    new->matrix.columns = current->matrix.columns;
  1636. X    new->matrix.column_widths = current->matrix.column_widths;
  1637. X    new->matrix.column_max_lengths = current->matrix.column_max_lengths;
  1638. X    new->matrix.column_labels = current->matrix.column_labels;
  1639. X    new->matrix.column_alignments = current->matrix.column_alignments;
  1640. X    new->matrix.column_label_alignments =
  1641. X        current->matrix.column_label_alignments;
  1642. X    }
  1643. X
  1644. X    /*
  1645. X     * Make sure we have at least one row/column.
  1646. X     */
  1647. X    if (new->matrix.columns <= 0 || new->matrix.rows <= 0) {
  1648. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1649. X            "setValues", "size", "XbaeMatrix",
  1650. X            "XbaeMatrix: Must have at least one row and column",
  1651. X            NULL, 0);
  1652. X    if (new->matrix.columns <= 0)
  1653. X        new->matrix.columns = current->matrix.columns;
  1654. X    if (new->matrix.rows <= 0)
  1655. X        new->matrix.rows = current->matrix.rows;
  1656. X    }
  1657. X
  1658. X    /*
  1659. X     * We cannot have both fixed rows and fixed columns
  1660. X     */
  1661. X    if (new->matrix.fixed_rows && new->matrix.fixed_columns) {
  1662. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1663. X            "setValues", "bothFixed", "XbaeMatrix",
  1664. X            "XbaeMatrix: Cannot have both fixed rows and columns",
  1665. X            NULL, 0);
  1666. X    if (NE(matrix.fixed_rows))
  1667. X        new->matrix.fixed_rows = current->matrix.fixed_rows;
  1668. X    if (NE(matrix.fixed_columns))
  1669. X        new->matrix.fixed_columns = current->matrix.fixed_columns;
  1670. X    }
  1671. X
  1672. X    /*
  1673. X     * We must have at least one non-fixed row/column.
  1674. X     * This could be caused by fixed_rows/columns or rows/columns changing.
  1675. X     */
  1676. X    if ((new->matrix.fixed_rows &&
  1677. X     new->matrix.fixed_rows >= new->matrix.rows) ||
  1678. X    (new->matrix.fixed_columns &&
  1679. X     new->matrix.fixed_columns >= new->matrix.columns)) {
  1680. X    String params[1];
  1681. X    Cardinal num_params = 1;
  1682. X    params[0] = new->matrix.fixed_rows ? "row" : "column";
  1683. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1684. X            "setValues", "tooManyFixed", "XbaeMatrix",
  1685. X            "XbaeMatrix: At least one %s must not be fixed",
  1686. X            (String *) params, (Cardinal *) &num_params);
  1687. X    if (new->matrix.fixed_rows) {
  1688. X        if (NE(matrix.fixed_rows))
  1689. X        new->matrix.fixed_rows = current->matrix.fixed_rows;
  1690. X        if (NE(matrix.rows))
  1691. X        new->matrix.rows = current->matrix.rows;
  1692. X    }
  1693. X    else if (new->matrix.fixed_columns) {
  1694. X        if (NE(matrix.fixed_columns))
  1695. X        new->matrix.fixed_columns = current->matrix.fixed_columns;
  1696. X        if (NE(matrix.columns))
  1697. X        new->matrix.columns = current->matrix.columns;
  1698. X    }
  1699. X    }
  1700. X
  1701. X    /*
  1702. X     * We can't have too many visible rows.
  1703. X     * This could be caused by visible_rows or rows or fixed_rows changing.
  1704. X     */
  1705. X    if (new->matrix.visible_rows >
  1706. X    new->matrix.rows - new->matrix.fixed_rows) {
  1707. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1708. X              "setValues", "tooManyVisibleRows", "XbaeMatrix",
  1709. X              "XbaeMatrix: visibleRows must not be greater than (rows - fixedRows)",
  1710. X              (String *) NULL, (Cardinal *) NULL);
  1711. X    if (NE(matrix.visible_rows))
  1712. X        new->matrix.visible_rows = current->matrix.visible_rows;
  1713. X    if (NE(matrix.rows))
  1714. X        new->matrix.rows = current->matrix.rows;
  1715. X    if (NE(matrix.fixed_rows))
  1716. X        new->matrix.fixed_rows = current->matrix.fixed_rows;
  1717. X    }
  1718. X
  1719. X    /*
  1720. X     * We can't have too many visible columns.
  1721. X     * This could be caused by visible_columns or columns or fixed_columns
  1722. X     * changing.
  1723. X     */
  1724. X    if (new->matrix.visible_columns >
  1725. X    new->matrix.columns - new->matrix.fixed_columns) {
  1726. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1727. X              "setValues", "tooManyVisibleColumns", "XbaeMatrix",
  1728. X              "XbaeMatrix: visibleColumns must not be greater than (columns - fixedColumns)",
  1729. X              (String *) NULL, (Cardinal *) NULL);
  1730. X    if (NE(matrix.visible_columns))
  1731. X        new->matrix.visible_columns = current->matrix.visible_columns;
  1732. X    if (NE(matrix.columns))
  1733. X        new->matrix.columns = current->matrix.columns;
  1734. X    if (NE(matrix.fixed_columns))
  1735. X        new->matrix.fixed_columns = current->matrix.fixed_columns;
  1736. X    }
  1737. X
  1738. X    /*
  1739. X     * Make sure we have column_widths
  1740. X     */
  1741. X    if (new->matrix.column_widths == NULL) {
  1742. X    XtAppWarningMsg(XtWidgetToApplicationContext((Widget)new),
  1743. X            "setValues", "columnWidths", "XbaeMatrix",
  1744. X            "XbaeMatrix: Must specify columnWidths",
  1745. X            NULL, 0);
  1746. X    new->matrix.column_widths = current->matrix.column_widths;
  1747. X    }
  1748. X
  1749. X
  1750. X    /*
  1751. X     * If rows or columns or fixed rows/columns changed,
  1752. X     * then we need to relayout.
  1753. X     */
  1754. X    if (NE(matrix.rows) || NE(matrix.fixed_rows)) {
  1755. X    /*
  1756. X     * Reset VSB maximum. sliderSize will be reset later in Resize.
  1757. X     */
  1758. X    XtVaSetValues(VertScrollChild(new),
  1759. X              XmNmaximum,    (new->matrix.rows -
  1760. X                     (int) new->matrix.fixed_rows),
  1761. X              XmNvalue,        0,
  1762. X              XmNsliderSize,    1,
  1763. X              NULL);
  1764. X    do_top_row = True;
  1765. X    relayout = True;
  1766. X    }
  1767. X    if (NE(matrix.columns) || NE(matrix.fixed_columns))
  1768. X    relayout = True;
  1769. X
  1770. X    /*
  1771. X     * Copy any pointed to resources if they changed
  1772. X     */
  1773. X
  1774. X    if (NE(matrix.cells)) {
  1775. X    FreeCells(current);
  1776. X    CopyCells(new);
  1777. X    redisplay = True;
  1778. X    new_cells = True;
  1779. X    }
  1780. X    else if (NE(matrix.rows) || NE(matrix.columns))
  1781. X    ResizeCells(current, new);
  1782. X    if (NE(matrix.row_labels)) {
  1783. X    /*
  1784. X     * If we added or deleted row_labels, we need to layout.
  1785. X     */
  1786. X    if (!current->matrix.row_labels || !new->matrix.row_labels)
  1787. X        relayout = True;
  1788. X    else
  1789. X        redisplay = True;
  1790. X
  1791. X    FreeRowLabels(current);
  1792. X    if (new->matrix.row_labels)
  1793. X        CopyRowLabels(new);
  1794. X    }
  1795. X    if (NE(matrix.column_labels)) {
  1796. X    FreeColumnLabels(current);
  1797. X    if (new->matrix.column_labels)
  1798. X        CopyColumnLabels(new);
  1799. X    else {
  1800. SHAR_EOF
  1801. true || echo 'restore of Xbae/src/Matrix.c failed'
  1802. fi
  1803. echo 'End of Xbae part 6'
  1804. echo 'File Xbae/src/Matrix.c is continued in part 7'
  1805. echo 7 > _shar_seq_.tmp
  1806. exit 0
  1807. -- 
  1808. --
  1809. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1810. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1811. Sunnyvale, California 94086            at&t: 408/522-9236
  1812.