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

  1. Newsgroups: comp.sources.x
  2. Path: uunet!cis.ohio-state.edu!zaphod.mps.ohio-state.edu!mips!msi!dcmartin
  3. From: Andrew Wason <aw@bae.bellcore.com>
  4. Subject: v17i034: Xbae widgets (MOTIF), Part07/12
  5. Message-ID: <1992Mar23.180124.16162@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:24 GMT
  11. Approved: dcmartin@msi.com
  12.  
  13. Submitted-by: Andrew Wason <aw@bae.bellcore.com>
  14. Posting-number: Volume 17, Issue 34
  15. Archive-name: xbae/part07
  16.  
  17. Submitted-by: aw@jello
  18. Archive-name: Xbae/part07
  19.  
  20. ---- Cut Here and feed the following to sh ----
  21. #!/bin/sh
  22. # this is Xbae.shar.07 (part 7 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" != 7; 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        new->matrix.column_label_lines = NULL;
  44. X        new->matrix.column_label_maxlines = 0;
  45. X    }
  46. X
  47. X    /*
  48. X     * If the number of lines in column labels changed, we need to relayout
  49. X     */
  50. X    if (current->matrix.column_label_maxlines !=
  51. X        new->matrix.column_label_maxlines)
  52. X        relayout = True;
  53. X    else
  54. X        redisplay = True;
  55. X    }
  56. X    if (NE(matrix.column_max_lengths)) {
  57. X    FreeColumnMaxLengths(current);
  58. X    if (new->matrix.column_max_lengths)
  59. X        CopyColumnMaxLengths(new);
  60. X    redisplay = True;
  61. X    }
  62. X    if (NE(matrix.column_alignments)) {
  63. X    FreeColumnAlignments(current);
  64. X    if (new->matrix.column_alignments)
  65. X        CopyColumnAlignments(new);
  66. X    redisplay = True;
  67. X    }
  68. X    if (NE(matrix.column_label_alignments)) {
  69. X    FreeColumnLabelAlignments(current);
  70. X    if (new->matrix.column_label_alignments)
  71. X        CopyColumnLabelAlignments(new);
  72. X    redisplay = True;
  73. X    }
  74. X    if (NE(matrix.colors)) {
  75. X    FreeColors(current);
  76. X    if (new->matrix.colors)
  77. X        CopyColors(new);
  78. X    redisplay = True;
  79. X    }
  80. X    else if(new->matrix.colors && (NE(matrix.rows) || NE(matrix.columns)))
  81. X    ResizeColors(current, new);
  82. X    if (NE(matrix.column_widths)) {
  83. X    FreeColumnWidths(current);
  84. X    CopyColumnWidths(new);
  85. X    relayout = True;
  86. X    new_column_widths = True;
  87. X    }
  88. X    if (NE(matrix.selected_cells)) {
  89. X    FreeSelectedCells(current);
  90. X    CopySelectedCells(new);
  91. X    redisplay = True;
  92. X    }
  93. X    else if (NE(matrix.rows) || NE(matrix.columns))
  94. X    ResizeSelectedCells(current, new);
  95. X
  96. X    /*
  97. X     * If traversal changes, pass through to Clip and textField children.
  98. X     */
  99. X    if (NE(manager.traversal_on)) {
  100. X    XtVaSetValues(ClipChild(new),
  101. X              XmNtraversalOn,    new->manager.traversal_on,
  102. X              NULL);
  103. X    }
  104. X
  105. X    /*
  106. X     * Pass through primitive/manager resources to our children
  107. X     */
  108. X    n = 0;
  109. X    if (NE(core.background_pixel)) {
  110. X    XtVaSetValues(ClipChild(new),
  111. X              XmNbackground,        new->core.background_pixel,
  112. X              NULL);
  113. X    XtSetArg(wargs[n], XmNbackground, new->core.background_pixel); n++;
  114. X    }
  115. X    if (NE(manager.foreground)) {
  116. X    XtSetArg(wargs[n], XmNforeground, new->manager.foreground); n++;
  117. X    }
  118. X    if (NE(manager.bottom_shadow_color)) {
  119. X    XtSetArg(wargs[n], XmNbottomShadowColor,
  120. X         new->manager.bottom_shadow_color); n++;
  121. X    }
  122. X    if (NE(manager.bottom_shadow_pixmap)) {
  123. X    XtSetArg(wargs[n], XmNbottomShadowPixmap,
  124. X         new->manager.bottom_shadow_pixmap); n++;
  125. X    }
  126. X    if (NE(manager.highlight_color)) {
  127. X    XtSetArg(wargs[n], XmNhighlightColor,
  128. X         new->manager.highlight_color); n++;
  129. X    }
  130. X    if (NE(manager.highlight_pixmap)) {
  131. X    XtSetArg(wargs[n], XmNhighlightPixmap,
  132. X         new->manager.highlight_pixmap); n++;
  133. X    }
  134. X    if (NE(manager.top_shadow_color)) {
  135. X    XtSetArg(wargs[n], XmNtopShadowColor,
  136. X         new->manager.top_shadow_color); n++;
  137. X    }
  138. X    if (NE(manager.top_shadow_pixmap)) {
  139. X    XtSetArg(wargs[n], XmNtopShadowPixmap,
  140. X         new->manager.top_shadow_pixmap); n++;
  141. X    }
  142. X    if (n) {
  143. X    XtSetValues(VertScrollChild(new), wargs, n);
  144. X    XtSetValues(HorizScrollChild(new), wargs, n);
  145. X    XtSetValues(TextChild(new), wargs, n);
  146. X    }
  147. X
  148. X
  149. X    /*
  150. X     * Get a new XFontStruct and copy the fontList if it changed
  151. X     * and pass it to the textField.
  152. X     * Reset the HSB increment.
  153. X     * redisplay and relayout will be set below.
  154. X     */
  155. X    if (NE(matrix.font_list)) {
  156. X    XmFontListFree(current->matrix.font_list);
  157. X    NewFont(new);
  158. X    XtVaSetValues(TextChild(new),
  159. X              XmNfontList,    new->matrix.font_list,
  160. X              NULL);
  161. X    XtVaSetValues(HorizScrollChild(new),
  162. X              XmNincrement,    FONT_WIDTH(new),
  163. X              NULL);
  164. X    }
  165. X
  166. X    /*
  167. X     * Pass the cell resources on to the textField.
  168. X     * Both redisplay and relayout will be set below.
  169. X     * XXX XmTextField has a bug where it will not recompute it's size when
  170. X     * XmNshadowThickness changes.
  171. X     */
  172. X    if (NE(matrix.cell_margin_width) ||
  173. X    NE(matrix.cell_margin_height) ||
  174. X    NE(matrix.cell_shadow_thickness) ||
  175. X    NE(matrix.cell_highlight_thickness)) {
  176. X    XtVaSetValues(TextChild(new),
  177. X              XmNmarginWidth,    new->matrix.cell_margin_width,
  178. X              XmNmarginHeight,    new->matrix.cell_margin_height,
  179. X              XmNshadowThickness, new->matrix.cell_shadow_thickness,
  180. X              XmNhighlightThickness,
  181. X                new->matrix.cell_highlight_thickness,
  182. X              NULL);
  183. X    }
  184. X
  185. X    /*
  186. X     * If anything changed which affects text offsets, recalc them
  187. X     */
  188. X    if (NE(matrix.font->fid) || NE(matrix.cell_margin_width) ||
  189. X    NE(matrix.cell_margin_height) ||
  190. X    NE(matrix.cell_shadow_thickness) ||
  191. X    NE(matrix.cell_highlight_thickness)) {
  192. X
  193. X    new->matrix.text_baseline =
  194. X        XmTextFieldGetBaseline(TextChild(new));
  195. X    relayout = True;
  196. X    }
  197. X    
  198. X    /*
  199. X     * If anything changed to affect cell total width or column positions,
  200. X     * recalc them
  201. X     */
  202. X    if (new_cells || NE(matrix.font->fid) ||
  203. X    NE(matrix.cell_margin_width) ||
  204. X    NE(matrix.cell_margin_height) ||
  205. X    NE(matrix.cell_shadow_thickness) ||
  206. X    NE(matrix.cell_highlight_thickness) ||
  207. X    NE(matrix.fixed_columns) ||
  208. X    new_column_widths) {
  209. X
  210. X    GetCellTotalWidth(new);
  211. X
  212. X    /*
  213. X     * Reset the HSB maximum.  sliderSize will be reset later in Resize.
  214. X     */
  215. X    XtVaSetValues(HorizScrollChild(new),
  216. X              XmNmaximum,    CELL_TOTAL_WIDTH(new),
  217. X              XmNvalue,        0,
  218. X              XmNsliderSize,    1,
  219. X              NULL);
  220. X    HORIZ_ORIGIN(new) = 0;
  221. X
  222. X    /*
  223. X     * If the number of columns changed, we need to allocate a new array.
  224. X     */
  225. X    if (NE(matrix.columns)) {
  226. X        FreeColumnPositions(current);
  227. X        new->matrix.column_positions = CreateColumnPositions(new);
  228. X    }
  229. X
  230. X    /*
  231. X     * If anything but fixed_columns changed, we need to recalc
  232. X     * column positions.
  233. X     */
  234. X    if (new_cells || NE(matrix.font->fid) ||
  235. X        NE(matrix.cell_margin_width) ||
  236. X        NE(matrix.cell_margin_height) ||
  237. X        NE(matrix.cell_shadow_thickness) ||
  238. X        NE(matrix.cell_highlight_thickness) ||
  239. X        new_column_widths)
  240. X        GetColumnPositions(new);
  241. X
  242. X    relayout = True;
  243. X    }
  244. X
  245. X    /*
  246. X     * Install text_translations on textField
  247. X     */
  248. X    if (NE(matrix.text_translations))
  249. X    XtVaSetValues(TextChild(new),
  250. X              XmNtranslations,    new->matrix.text_translations,
  251. X              NULL);
  252. X
  253. X    /*
  254. X     * If row_label_width was set to 0, calculate it.
  255. X     * Otherwise if it was changed, set flags.
  256. X     */
  257. X    if (new->matrix.row_label_width == 0 && new->matrix.row_labels) {
  258. X    new->matrix.row_label_width = MaxRowLabel(new);
  259. X    relayout = True;
  260. X    }
  261. X    else if (NE(matrix.row_label_width))
  262. X    relayout = True;
  263. X
  264. X
  265. X    /*
  266. X     * Get new cached GC if needed
  267. X     */
  268. X    if (NE(core.background_pixel) || NE(matrix.font->fid)) {
  269. X    XtReleaseGC((Widget)new, new->matrix.inverse_gc);
  270. X    GetInverseGC(new);
  271. X    redisplay = True;
  272. X    }
  273. X
  274. X    /*
  275. X     * Change created GCs if needed
  276. X     */
  277. X
  278. X    if (NE(manager.foreground)) {
  279. X    /*
  280. X     * We don't need to put the new foreground in draw_gc or
  281. X     * draw_clip_gc because they get a new foreground when they are used.
  282. X     */
  283. X
  284. X    XSetForeground(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
  285. X               new->manager.foreground);
  286. X    XSetBackground(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
  287. X               new->manager.foreground);
  288. X    redisplay = True;
  289. X    }
  290. X    if (NE(core.background_pixel)) {
  291. X    XSetForeground(XtDisplay(new), new->matrix.inverse_clip_gc,
  292. X               new->core.background_pixel);
  293. X    redisplay = True;
  294. X    }
  295. X    if (NE(manager.top_shadow_color)) {
  296. X    XSetForeground(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
  297. X               new->manager.top_shadow_color);
  298. X    redisplay = True;
  299. X    }
  300. X    if (NE(manager.top_shadow_pixmap)) {
  301. X    XSetTile(XtDisplay(new), new->matrix.cell_top_shadow_clip_gc,
  302. X         new->manager.top_shadow_pixmap);
  303. X    redisplay = True;
  304. X    }
  305. X    if (NE(manager.bottom_shadow_color)) {
  306. X    XSetForeground(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
  307. X               new->manager.bottom_shadow_color);
  308. X    redisplay = True;
  309. X    }
  310. X    if (NE(manager.bottom_shadow_pixmap)) {
  311. X    XSetTile(XtDisplay(new), new->matrix.cell_bottom_shadow_clip_gc,
  312. X         new->manager.bottom_shadow_pixmap);
  313. X    redisplay = True;
  314. X    }
  315. X    if (NE(matrix.font->fid)) {
  316. X    XSetFont(XtDisplay(new), new->matrix.draw_gc, new->matrix.font->fid);
  317. X    XSetFont(XtDisplay(new), new->matrix.draw_clip_gc,
  318. X         new->matrix.font->fid);
  319. X    XSetFont(XtDisplay(new), new->matrix.inverse_clip_gc,
  320. X         new->matrix.font->fid);
  321. X    redisplay = True;
  322. X    }
  323. X
  324. X    /*
  325. X     * See if any other resources changed which will require a relayout
  326. X     */
  327. X    if (NE(matrix.space) || NE(matrix.cell_shadow_thickness) ||
  328. X    NE(manager.shadow_thickness))
  329. X    relayout = True;
  330. X
  331. X    /*
  332. X     * If bold_labels changed, and we have labels, we must redisplay
  333. X     */
  334. X    if (NE(matrix.bold_labels) &&
  335. X    (new->matrix.row_labels || new->matrix.column_labels))
  336. X    redisplay = True;
  337. X
  338. X    /*
  339. X     * Compute a new size if:
  340. X     *     visible_rows or visible_columns changed.
  341. X     *     user set our width or height to zero.
  342. X     */
  343. X    if (NE(matrix.visible_rows) || NE(matrix.visible_columns) ||
  344. X    request->core.height == 0 || request->core.width == 0)
  345. X    ComputeSize(new, request->core.width == 0, request->core.height == 0);
  346. X
  347. X    /*
  348. X     * If our size didn't change, but we need to layout, call Resize.
  349. X     * If our size did change, then Xt will call our Resize method for us.
  350. X     * If our size did change, but the new size is later refused,
  351. X     *     then SetValuesAlmost will call Resize to layout.
  352. X     */
  353. X    if (EQ(core.width) && EQ(core.height) && relayout)
  354. X    Resize(new);
  355. X
  356. X    /*
  357. X     * The user forced a new top_row or something changed to force
  358. X     * us to recheck the current top_row.
  359. X     */
  360. X    if (NE(matrix.top_row) || do_top_row) {
  361. X    AdjustTopRow(new);
  362. X    XtVaSetValues(VertScrollChild(new),
  363. X              XmNvalue,    VERT_ORIGIN(new),
  364. X              NULL);
  365. X    redisplay = True;
  366. X    }
  367. X
  368. X    /*
  369. X     * Cancel any current edit.
  370. X     * Force the Clip widget to redisplay.  Note: this may generate an
  371. X     * expose event for the current size of the Clip widget, and the Clip
  372. X     * widget may be sized smaller in set_values_almost.  The ClipRedisplay
  373. X     * function can handle this case.
  374. X     * XXX If the Clip widget has been/will be resized, then we don't need
  375. X     * to force a redraw.  But how can set_values_almost for XtGeometryAlmost
  376. X     * determine if Resize will really resize the Clip widget?
  377. X     */
  378. X    if (redisplay || relayout) {
  379. X    (*((XbaeMatrixWidgetClass) XtClass(new))->matrix_class.cancel_edit)
  380. X        (new, True);
  381. X
  382. X    XbaeClipRedraw(ClipChild(new));
  383. X    }
  384. X
  385. X    /*
  386. X     * We want to return True when we need to redisplay or relayout.
  387. X     */
  388. X    return redisplay || relayout;
  389. X
  390. #undef NE
  391. #undef EQ
  392. }
  393. X
  394. /* ARGSUSED */
  395. static void
  396. SetValuesAlmost(old, new, request, reply)
  397. XXbaeMatrixWidget old;
  398. XXbaeMatrixWidget new;
  399. XXtWidgetGeometry *request;
  400. XXtWidgetGeometry *reply;
  401. {
  402. X    /*
  403. X     * If XtGeometryAlmost, accept compromize - Resize will take care of it
  404. X     */
  405. X    if (reply->request_mode)
  406. X    *request = *reply;
  407. X
  408. X    /*
  409. X     * If XtGeometryNo, call Resize to relayout if it was a size change
  410. X     * that was denied.
  411. X     * Accept the original geometry.
  412. X     * (we need to call Resize even though the size
  413. X     * didn't change to force a relayout - set_values relies on this)
  414. X     */
  415. X    else {
  416. X        if ((request->request_mode & CWWidth ||
  417. X             request->request_mode & CWHeight))
  418. X        Resize(new);
  419. X
  420. X    request->request_mode = 0;
  421. X    }
  422. }
  423. X
  424. static void
  425. ComputeSize(mw, compute_width, compute_height)
  426. XXbaeMatrixWidget mw;
  427. Boolean compute_width, compute_height;
  428. {
  429. X    unsigned long full_width = CELL_TOTAL_WIDTH(mw) + FIXED_COLUMN_WIDTH(mw) +
  430. X    ROW_LABEL_WIDTH(mw) + 2 * mw->manager.shadow_thickness;
  431. X    unsigned long full_height = CELL_TOTAL_HEIGHT(mw) + FIXED_ROW_HEIGHT(mw) +
  432. X    COLUMN_LABEL_HEIGHT(mw) + 2 * mw->manager.shadow_thickness;
  433. X    unsigned long width, height;
  434. X
  435. X    /*
  436. X     * Calculate our width.
  437. X     * If visible_columns is set, then base it on that.
  438. X     * Otherwise, if the compute_width flag is set, then we are full width.
  439. X     * Otherwise we keep whatever width we are.
  440. X     */
  441. X    if (mw->matrix.visible_columns)
  442. X    width = ROW_LABEL_WIDTH(mw) + 2 * mw->manager.shadow_thickness +
  443. X        mw->matrix.column_positions[mw->matrix.fixed_columns +
  444. X                    mw->matrix.visible_columns];
  445. X    else if (compute_width)
  446. X    width = full_width;
  447. X    else
  448. X    width = mw->core.width;
  449. X
  450. X    /*
  451. X     * Calculate our height.
  452. X     * If visible_rows is set, then base it on that.
  453. X     * Otherwise, if the compute_height flag is set, then we are full height.
  454. X     * Otherwise we keep whatever height we are.
  455. X     */
  456. X    if (mw->matrix.visible_rows)
  457. X    height = mw->matrix.visible_rows * ROW_HEIGHT(mw) +
  458. X        FIXED_ROW_HEIGHT(mw) + COLUMN_LABEL_HEIGHT(mw) +
  459. X        2 * mw->manager.shadow_thickness;
  460. X    else if (compute_height)
  461. X    height = full_height;
  462. X    else
  463. X    height = mw->core.height;
  464. X
  465. X    /*
  466. X     * Store our calculated size.
  467. X     */
  468. X    mw->core.width = width;
  469. X    mw->core.height = height;
  470. X
  471. X    /*
  472. X     * If we are less than full width, then we need an HSB, so increment
  473. X     * our height by the size of the HSB (if we are allowed to modify our
  474. X     * height).
  475. X     */
  476. X    if (width < full_width)
  477. X    if (compute_height || mw->matrix.visible_rows)
  478. X        mw->core.height += HSCROLL_HEIGHT(mw);
  479. X
  480. X    /*
  481. X     * If we are less than full height, then we need a VSB, so increment
  482. X     * our width by the size of the VSB (if we are allowed to modify our
  483. X     * width).
  484. X     */
  485. X    if (height < full_height)
  486. X    if (compute_width || mw->matrix.visible_columns)
  487. X        mw->core.width += VSCROLL_WIDTH(mw);
  488. X
  489. X    /*
  490. X     * Save our calculated size for use in our query_geometry method.
  491. X     * This is the size we really want to be (not necessarily the size
  492. X     * we will end up being).
  493. X     */
  494. X    mw->matrix.desired_width = mw->core.width;
  495. X    mw->matrix.desired_height = mw->core.height;
  496. }
  497. X
  498. X
  499. static void
  500. Destroy(mw)
  501. XXbaeMatrixWidget mw;
  502. {
  503. X    XtReleaseGC((Widget)mw, mw->matrix.inverse_gc);
  504. X
  505. X    XFreeGC(XtDisplay(mw), mw->matrix.draw_gc);
  506. X    XFreeGC(XtDisplay(mw), mw->matrix.draw_clip_gc);
  507. X    XFreeGC(XtDisplay(mw), mw->matrix.inverse_clip_gc);
  508. X    XFreeGC(XtDisplay(mw), mw->matrix.cell_top_shadow_clip_gc);
  509. X    XFreeGC(XtDisplay(mw), mw->matrix.cell_bottom_shadow_clip_gc);
  510. X
  511. X    FreeCells(mw);
  512. X    FreeRowLabels(mw);
  513. X    FreeColumnLabels(mw);
  514. X    FreeColumnWidths(mw);
  515. X    FreeColumnMaxLengths(mw);
  516. X    FreeColumnPositions(mw);
  517. X    FreeColumnAlignments(mw);
  518. X    FreeColumnLabelAlignments(mw);
  519. X    FreeColors(mw);
  520. X    FreeSelectedCells(mw);
  521. X
  522. X    XmFontListFree(mw->matrix.font_list);
  523. X
  524. X    SmDestroyScrollMgr(mw->matrix.matrix_scroll_mgr);
  525. X    SmDestroyScrollMgr(mw->matrix.clip_scroll_mgr);
  526. }
  527. X
  528. X
  529. /*
  530. X * Position and size the scrollbars and clip widget for our new size.
  531. X */
  532. static void
  533. Resize(mw)
  534. XXbaeMatrixWidget mw;
  535. {
  536. X    int cell_width, cell_height, rows_visible;
  537. X    Boolean has_horiz, has_vert;
  538. X    int width = mw->core.width;
  539. X    int height = mw->core.height;
  540. X
  541. X    /*
  542. X     * Full size of widget (no SBs needed) - may be very large
  543. X     */
  544. X    long int full_width = CELL_TOTAL_WIDTH(mw) + FIXED_COLUMN_WIDTH(mw) +
  545. X    ROW_LABEL_WIDTH(mw) + 2 * mw->manager.shadow_thickness;
  546. X    long int full_height = CELL_TOTAL_HEIGHT(mw) + FIXED_ROW_HEIGHT(mw) +
  547. X    COLUMN_LABEL_HEIGHT(mw) + 2 * mw->manager.shadow_thickness;
  548. X
  549. X    /*
  550. X     * Portion of cells which are visible in clip widget
  551. X     */
  552. X    int horiz_visible = CELL_TOTAL_WIDTH(mw) - HORIZ_ORIGIN(mw);
  553. X    int vert_visible = CELL_TOTAL_HEIGHT(mw) -
  554. X    VERT_ORIGIN(mw) * ROW_HEIGHT(mw);
  555. X
  556. X
  557. X    /*
  558. X     * If matrix is bigger in both dimensions, then we don't need either
  559. X     * SB. If both dimensions are smaller than matrix, then we need both
  560. X     * SBs. Otherwise, only one or the other dimension must be too small:
  561. X     *    - Get the dimensions assuming both SBs are mapped (subtract size
  562. X     *      of SBs)
  563. X     *    - Flag both SBs as mapped
  564. X     *    - If the full_width is small enough that we won't need a HSB even
  565. X     *      if the VSB is mapped, then unflag the HSB and reset the height
  566. X     *    - Next compare the full_height to the height just computed and decide
  567. X     *      if we need a VSB (if we didn't need a HSB above, then we had reset
  568. X     *      the height to not count the HSB)
  569. X     *
  570. X     * The whole point is, if we map one SB then we may need to map the
  571. X     * other one because of the space taken by the first one
  572. X     */
  573. X    if (mw->core.width >= full_width && mw->core.height >= full_height)
  574. X    has_horiz = has_vert = False;
  575. X    else if (mw->core.width < full_width && mw->core.height < full_height)
  576. X    has_horiz = has_vert = True;
  577. X    else {
  578. X    height -= HSCROLL_HEIGHT(mw);
  579. X    width -= VSCROLL_WIDTH(mw);
  580. X
  581. X    has_horiz = has_vert = True;
  582. X    if (full_width <= width) {
  583. X        height = mw->core.height;
  584. X        has_horiz = False;
  585. X    }
  586. X    if (full_height <= height)
  587. X        has_vert = False;
  588. X    }
  589. X
  590. X
  591. X    /*
  592. X     * If widget is smaller than full size, move/resize the scrollbar and
  593. X     * set sliderSize, also if cell_width/cell_height is greater than
  594. X     * the amount of cell area visible, then we need to drag the cells
  595. X     * back into the visible part of the clip widget and set the
  596. X     * scrollbar value.
  597. X     *
  598. X     * Otherwise, the widget is larger than full size, so set
  599. X     * cell_width/cell_height to size of cells and set origin to 0
  600. X     * to force full cell area to be displayed
  601. X     *
  602. X     * We also need to move the textField correspondingly
  603. X     */
  604. X
  605. X    /*
  606. X     * We were resized smaller than our max width.
  607. X     */
  608. X    if (width < full_width) {
  609. X
  610. X    /*
  611. X     * Calculate the width of the non-fixed visible cells.
  612. X     */
  613. X    cell_width = mw->core.width -
  614. X        (FIXED_COLUMN_WIDTH(mw) + ROW_LABEL_WIDTH(mw) +
  615. X         2 * mw->manager.shadow_thickness);
  616. X
  617. X    /*
  618. X     * Subtract the VSB if we have one.
  619. X     */
  620. X    if (has_vert)
  621. X        cell_width -= VSCROLL_WIDTH(mw);
  622. X
  623. X    if (cell_width <= 0)
  624. X        cell_width = 1;
  625. X
  626. X    /*
  627. X     * If the window is not full height, then place the HSB at the edge
  628. X     * of the window.  Is the window is larger than full height, then
  629. X     * place the HSB immediately below the cell region.
  630. X     */
  631. X    XtConfigureWidget(HorizScrollChild(mw),
  632. X              FIXED_COLUMN_LABEL_OFFSET(mw),
  633. X              height < full_height
  634. X              ? (Position)(mw->core.height -
  635. X                       (HorizScrollChild(mw)->core.height +
  636. X                    2 * HorizScrollChild(mw)->
  637. X                        core.border_width))
  638. X              : (Position) (full_height + mw->matrix.space),
  639. X              cell_width,
  640. X              HorizScrollChild(mw)->core.height,
  641. X              HorizScrollChild(mw)->core.border_width);
  642. X
  643. X    /*
  644. X     * If the cells are scrolled off to the left, then drag them
  645. X     * back onto the screen.
  646. X     */
  647. X    if (cell_width > horiz_visible) {
  648. X        HORIZ_ORIGIN(mw) -= (cell_width - horiz_visible);
  649. X
  650. X        if (XtIsManaged(TextChild(mw)))
  651. X        XtMoveWidget(TextChild(mw),
  652. X                 TextChild(mw)->core.x +
  653. X                (cell_width - horiz_visible),
  654. X                 TextChild(mw)->core.y);
  655. X    }
  656. X
  657. X    /*
  658. X     * Setup the HSB to reflect our new size.
  659. X     */
  660. X    XtVaSetValues(HorizScrollChild(mw),
  661. X              XmNpageIncrement,    cell_width,
  662. X              XmNsliderSize,    cell_width,
  663. X              XmNvalue,        HORIZ_ORIGIN(mw),
  664. X              NULL);
  665. X    }
  666. X
  667. X    /*
  668. X     * We were resized larger than the our max width.  Drag the cells back
  669. X     * onto the screen if they were scrolled off to the left.
  670. X     */
  671. X    else {
  672. X    if (XtIsManaged(TextChild(mw)))
  673. X        XtMoveWidget(TextChild(mw),
  674. X             TextChild(mw)->core.x + HORIZ_ORIGIN(mw),
  675. X             TextChild(mw)->core.y);
  676. X
  677. X    cell_width = CELL_TOTAL_WIDTH(mw);
  678. X    HORIZ_ORIGIN(mw) = 0;
  679. X    }
  680. X
  681. X    /*
  682. X     * We were resized smaller than our max height.
  683. X     */
  684. X    if (height < full_height) {
  685. X
  686. X    /*
  687. X     * Calculate the height of the non-fixed visible cells.
  688. X     */
  689. X    cell_height = mw->core.height -
  690. X        (FIXED_ROW_HEIGHT(mw) + COLUMN_LABEL_HEIGHT(mw) +
  691. X         2 * mw->manager.shadow_thickness);
  692. X
  693. X    /*
  694. X     * Subtract the HSB if we have one.
  695. X     */
  696. X    if (has_horiz)
  697. X        cell_height -= HSCROLL_HEIGHT(mw);
  698. X
  699. X    if (cell_height <= 0)
  700. X        cell_height = 1;
  701. X
  702. X    /*
  703. X     * If the window is not full width, then place the VSB at the edge
  704. X     * of the window.  Is the window is larger than full width, then
  705. X     * place the VSB immediately to the right of the cell region.
  706. X     */
  707. X    XtConfigureWidget(VertScrollChild(mw),
  708. X              width < full_width
  709. X              ? (Position)(mw->core.width -
  710. X                       (VertScrollChild(mw)->core.width +
  711. X                    2 * VertScrollChild(mw)->
  712. X                        core.border_width))
  713. X              : (Position) full_width + mw->matrix.space,
  714. X              FIXED_ROW_LABEL_OFFSET(mw),
  715. X              VertScrollChild(mw)->core.width,
  716. X              cell_height,
  717. X              VertScrollChild(mw)->core.border_width);
  718. X
  719. X    /*
  720. X     * If the cells are scrolled off the top, then drag them
  721. X     * back onto the screen.
  722. X     */
  723. X    if (cell_height > vert_visible) {
  724. X        int rows = (cell_height - vert_visible) / ROW_HEIGHT(mw);
  725. X
  726. X        VERT_ORIGIN(mw) -= rows;
  727. X
  728. X        if (XtIsManaged(TextChild(mw)))
  729. X        XtMoveWidget(TextChild(mw),
  730. X                 TextChild(mw)->core.x,
  731. X                 TextChild(mw)->core.y + rows * ROW_HEIGHT(mw));
  732. X    }
  733. X
  734. X    /*
  735. X     * Setup the VSB to reflect our new size.
  736. X     */
  737. X    rows_visible = cell_height / ROW_HEIGHT(mw);
  738. X    XtVaSetValues(VertScrollChild(mw),
  739. X              XmNpageIncrement,    rows_visible <= 0 ? 1 : rows_visible,
  740. X              XmNsliderSize,    rows_visible <= 0 ? 1 : rows_visible,
  741. X              XmNvalue,        VERT_ORIGIN(mw),
  742. X              NULL);
  743. X    }
  744. X
  745. X    /*
  746. X     * We were resized larger than the our max height.    Drag the cells back
  747. X     * onto the screen if they were scrolled off the top.
  748. X     */
  749. X    else {
  750. X    if (XtIsManaged(TextChild(mw)))
  751. X        XtMoveWidget(TextChild(mw),
  752. X             TextChild(mw)->core.x,
  753. X             TextChild(mw)->core.y +
  754. X                 VERT_ORIGIN(mw) * ROW_HEIGHT(mw));
  755. X
  756. X    cell_height = CELL_TOTAL_HEIGHT(mw);
  757. X    rows_visible = mw->matrix.rows - mw->matrix.fixed_rows;
  758. X    VERT_ORIGIN(mw) = 0;
  759. X    }
  760. X
  761. X    /*
  762. X     * Map/unmap scrollbars based on flags set above
  763. X     */
  764. X    if (has_horiz)
  765. X    XtManageChild(HorizScrollChild(mw));
  766. X    else
  767. X    XtUnmanageChild(HorizScrollChild(mw));
  768. X
  769. X    if (has_vert)
  770. X    XtManageChild(VertScrollChild(mw));
  771. X    else
  772. X    XtUnmanageChild(VertScrollChild(mw));
  773. X
  774. X    /*
  775. X     * Now that we have cell_width & cell_height,
  776. X     * make the clip widget this size.    Height is truncated to the
  777. X     * nearest row.
  778. X     */
  779. X    XtConfigureWidget(ClipChild(mw),
  780. X              FIXED_COLUMN_LABEL_OFFSET(mw),
  781. X              FIXED_ROW_LABEL_OFFSET(mw),
  782. X              cell_width,
  783. X              rows_visible <= 0
  784. X            ? cell_height
  785. X            : rows_visible * ROW_HEIGHT(mw),
  786. X              0);
  787. X
  788. X    /*
  789. X     * Save the non-truncated height.  We need this so we can draw
  790. X     * the shadow correctly.
  791. X     */
  792. X    mw->matrix.cell_visible_height = cell_height;
  793. X
  794. X    /*
  795. X     * Set the clip_mask in our clipping GCs.  This function relies on
  796. X     * the Clip widget being the correct size (above).
  797. X     */
  798. X    SetClipMask(mw);
  799. }
  800. X
  801. /*
  802. X * Since we totally control our childrens geometry, allow anything.
  803. X */
  804. /* ARGSUSED */
  805. static XtGeometryResult
  806. GeometryManager(w, desired, allowed)
  807. Widget w;
  808. XXtWidgetGeometry *desired, *allowed;
  809. {
  810. #define Wants(flag) (desired->request_mode & flag)
  811. X
  812. X    if (Wants(XtCWQueryOnly))
  813. X    return(XtGeometryYes);
  814. X
  815. X    if (Wants(CWWidth))
  816. X    w->core.width = desired->width;
  817. X    if (Wants(CWHeight))
  818. X    w->core.height = desired->height;
  819. X    if (Wants(CWX))
  820. X    w->core.x = desired->x;
  821. X    if (Wants(CWY))
  822. X    w->core.y = desired->y;
  823. X    if (Wants(CWBorderWidth))
  824. X    w->core.border_width = desired->border_width;
  825. X
  826. X    return(XtGeometryYes);
  827. X
  828. #undef Wants
  829. }
  830. X
  831. /*
  832. X * We would prefer to be the size calculated in ComputeSize and saved in
  833. X * desired_width/height
  834. X */
  835. static XtGeometryResult
  836. QueryGeometry(mw, proposed, desired)
  837. XXbaeMatrixWidget mw;
  838. XXtWidgetGeometry *proposed, *desired;
  839. {
  840. #define Set(bit) (proposed->request_mode & bit)
  841. X
  842. X    desired->width = mw->matrix.desired_width;
  843. X    desired->height = mw->matrix.desired_height;
  844. X    desired->request_mode = CWWidth | CWHeight;
  845. X
  846. X    if (Set(CWWidth) && proposed->width == desired->width &&
  847. X    Set(CWHeight) && proposed->height == desired->height)
  848. X    return(XtGeometryYes);
  849. X
  850. X    if (desired->width == mw->core.width && desired->height == mw->core.height)
  851. X    return(XtGeometryNo);
  852. X
  853. X    return(XtGeometryAlmost);
  854. X
  855. #undef Set
  856. }
  857. X
  858. /*
  859. X * Callback for vertical scrollbar
  860. X */
  861. /* ARGSUSED */
  862. static void
  863. ScrollVertCB(w, client_data, call_data)
  864. Widget w;
  865. XXtPointer client_data;
  866. XXmScrollBarCallbackStruct *call_data;
  867. {
  868. X    XbaeMatrixWidget mw = (XbaeMatrixWidget)XtParent(w);
  869. X    int src_y, dest_y, height;
  870. X
  871. X    /*
  872. X     * Didn't scroll
  873. X     */
  874. X    if (call_data->value == VERT_ORIGIN(mw))
  875. X    return;
  876. X
  877. X    /*
  878. X     * Scrolled forward. We want to copy a chunk starting at src_y up
  879. X     * to the top (dest_y=0)
  880. X     */
  881. X    else if (call_data->value > VERT_ORIGIN(mw)) {
  882. X    dest_y = 0;
  883. X    src_y = (call_data->value - VERT_ORIGIN(mw)) * ROW_HEIGHT(mw);
  884. X    height = ClipChild(mw)->core.height - src_y;
  885. X    }
  886. X
  887. X    /*
  888. X     * Scrolled backward. We want to copy a chunk starting at the top
  889. X     * (src_y=0) down to dest_y.
  890. X     */
  891. X    else {
  892. X    dest_y = (VERT_ORIGIN(mw) - call_data->value) * ROW_HEIGHT(mw);
  893. X    src_y = 0;
  894. X    height = ClipChild(mw)->core.height - dest_y;
  895. X    }
  896. X
  897. X    /*
  898. X     * The textField needs to scroll along with the cells.
  899. X     */
  900. X    if (XtIsManaged(TextChild(mw)))
  901. X    XtMoveWidget(TextChild(mw),
  902. X             TextChild(mw)->core.x,
  903. X             TextChild(mw)->core.y +
  904. X             (VERT_ORIGIN(mw) - call_data->value) * ROW_HEIGHT(mw));
  905. X
  906. X    /*
  907. X     * Now we can adjust our vertical origin
  908. X     */
  909. X    VERT_ORIGIN(mw) = call_data->value;
  910. X
  911. X    /*
  912. X     * If we scrolled more than a screenful, just clear and
  913. X     * redraw the whole thing
  914. X     */
  915. X    if (height <= 0) {
  916. X    Rectangle rect;
  917. X
  918. X    /*
  919. X     * Clear the whole clip window.
  920. X     */
  921. X    XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
  922. X           0, 0,
  923. X           0 /*Full Width*/, 0 /*Full Height*/,
  924. X           False);
  925. X
  926. X    /*
  927. X     * Redraw all the non-fixed cells in the clip window
  928. X     */
  929. X    SETRECT(rect,
  930. X        0, 0,
  931. X        ClipChild(mw)->core.width - 1,
  932. X        ClipChild(mw)->core.height - 1);
  933. X    RedrawCells(mw, &rect);
  934. X
  935. X    /*
  936. X     * Clear the non-fixed row labels and the cells in fixed columns
  937. X     */
  938. X    XClearArea(XtDisplay(mw), XtWindow(mw),
  939. X           0, FIXED_ROW_LABEL_OFFSET(mw),
  940. X           FIXED_COLUMN_LABEL_OFFSET(mw), 0 /*Full Height*/,
  941. X           False);
  942. X
  943. X    /*
  944. X     * Redraw non-fixed row labels and cells in fixed columns
  945. X     */
  946. X    SETRECT(rect,
  947. X        0, FIXED_ROW_LABEL_OFFSET(mw),
  948. X        FIXED_COLUMN_LABEL_OFFSET(mw), mw->core.height);
  949. X    RedrawLabelsAndFixed(mw, &rect);
  950. X    }
  951. X
  952. X    /*
  953. X     * If we scrolled less than a screenful, we want to copy as many
  954. X     * pixels as we can and then clear and redraw the newly scrolled data.
  955. X     */
  956. X    else {
  957. X    Rectangle rect;
  958. X    int y_clear = src_y > dest_y ? height : 0;
  959. X
  960. X    /*
  961. X     * Queue this scroll with the ScrollMgr
  962. X     */
  963. X    SmAddScroll(mw->matrix.clip_scroll_mgr, 0, dest_y - src_y);
  964. X
  965. X    /*
  966. X     * Copy the non-fixed cells in the clip widget
  967. X     */
  968. X    XCopyArea(XtDisplay(mw),
  969. X          XtWindow(ClipChild(mw)), XtWindow(ClipChild(mw)),
  970. X          mw->matrix.draw_gc,
  971. X          0, src_y,
  972. X          ClipChild(mw)->core.width, height,
  973. X          0, dest_y);
  974. X
  975. X    /*
  976. X     * Clear the newly scrolled chunk of the clip widget
  977. X     */
  978. X    XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
  979. X           0, y_clear,
  980. X           0 /*Full Width*/, ClipChild(mw)->core.height - height,
  981. X           False);
  982. X
  983. X    /*
  984. X     * Redraw the non-fixed cells into the new chunk
  985. X     */
  986. X    SETRECT(rect,
  987. X        0, y_clear,
  988. X        ClipChild(mw)->core.width - 1,
  989. X        (y_clear + (ClipChild(mw)->core.height - height)) - 1);
  990. X    RedrawCells(mw, &rect);
  991. X
  992. X    /*
  993. X     * Translate coordinates for fixed columns and row labels.
  994. X     */
  995. X    src_y += FIXED_ROW_LABEL_OFFSET(mw);
  996. X    dest_y += FIXED_ROW_LABEL_OFFSET(mw);
  997. X    y_clear += FIXED_ROW_LABEL_OFFSET(mw);
  998. X
  999. X    /*
  1000. X     * Queue this scroll with the ScrollMgr
  1001. X     */
  1002. X    SmAddScroll(mw->matrix.matrix_scroll_mgr, 0, dest_y - src_y);
  1003. X
  1004. X    /*
  1005. X     * Copy the fixed columns and row labels
  1006. X     */
  1007. X    XCopyArea(XtDisplay(mw),
  1008. X          XtWindow(mw), XtWindow(mw),
  1009. X          mw->matrix.draw_gc,
  1010. X          0, src_y,
  1011. X          FIXED_COLUMN_LABEL_OFFSET(mw), height,
  1012. X          0, dest_y);
  1013. X
  1014. X    /*
  1015. X     * Clear the newly scrolled chunk of fixed columns and row labels
  1016. X     */
  1017. X    XClearArea(XtDisplay(mw), XtWindow(mw),
  1018. X           0, y_clear,
  1019. X           FIXED_COLUMN_LABEL_OFFSET(mw),
  1020. X           ClipChild(mw)->core.height - height,
  1021. X           False);
  1022. X
  1023. X    /*
  1024. X     * Redraw the new chunk of fixed columns and row labels
  1025. X     */
  1026. X    SETRECT(rect,
  1027. X        0, y_clear,
  1028. X        FIXED_COLUMN_LABEL_OFFSET(mw) - 1,
  1029. X        (y_clear + (ClipChild(mw)->core.height - height)) - 1);
  1030. X    RedrawLabelsAndFixed(mw, &rect);
  1031. X    }
  1032. }
  1033. X
  1034. /*
  1035. X * Callback for horizontal scrollbar
  1036. X */
  1037. /* ARGSUSED */
  1038. static void
  1039. ScrollHorizCB(w, client_data, call_data)
  1040. Widget w;
  1041. XXtPointer client_data;
  1042. XXmScrollBarCallbackStruct *call_data;
  1043. {
  1044. X    XbaeMatrixWidget mw = (XbaeMatrixWidget)XtParent(w);
  1045. X    int src_x, dest_x, width;
  1046. X
  1047. X    /*
  1048. X     * Didn't scroll
  1049. X     */
  1050. X    if (call_data->value == HORIZ_ORIGIN(mw))
  1051. X    return;
  1052. X
  1053. X    /*
  1054. X     * Scrolled right. We want to copy a chunk starting at src_x over to
  1055. X     * the left (dest_x=0)
  1056. X     */
  1057. X    else if (call_data->value > HORIZ_ORIGIN(mw)) {
  1058. X    dest_x = 0;
  1059. X    src_x = call_data->value - HORIZ_ORIGIN(mw);
  1060. X    width = ClipChild(mw)->core.width - src_x;
  1061. X    }
  1062. X
  1063. X    /*
  1064. X     * Scrolled left. We want to copy a chunk starting at the left (src_x=0)
  1065. X     * over to the right to dest_x
  1066. X     */
  1067. X    else {
  1068. X    dest_x = HORIZ_ORIGIN(mw) - call_data->value;
  1069. X    src_x = 0;
  1070. X    width = ClipChild(mw)->core.width - dest_x;
  1071. X    }
  1072. X
  1073. X    /*
  1074. X     * The textField needs to scroll along with the cells.
  1075. X     */
  1076. X    if (XtIsManaged(TextChild(mw)))
  1077. X    XtMoveWidget(TextChild(mw),
  1078. X             TextChild(mw)->core.x + (HORIZ_ORIGIN(mw) -
  1079. X                          call_data->value),
  1080. X             TextChild(mw)->core.y);
  1081. X
  1082. X    /*
  1083. X     * Now we can adjust our horizontal origin
  1084. X     */
  1085. X    HORIZ_ORIGIN(mw) = call_data->value;
  1086. X
  1087. X    /*
  1088. X     * If we scrolled more than a screenful, just clear and
  1089. X     * redraw the whole thing
  1090. X     */
  1091. X    if (width <= 0) {
  1092. X    Rectangle rect;
  1093. X
  1094. X    /*
  1095. X     * Clear the whole clip window
  1096. X     */
  1097. X    XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
  1098. X           0, 0,
  1099. X           0 /*Full Width*/, 0 /*Full Height*/,
  1100. X           False);
  1101. X
  1102. X    /*
  1103. X     * Redraw all the non-fixed cells in the clip window
  1104. X     */
  1105. X    SETRECT(rect,
  1106. X        0, 0,
  1107. X        ClipChild(mw)->core.width - 1,
  1108. X        ClipChild(mw)->core.height - 1);
  1109. X    RedrawCells(mw, &rect);
  1110. X
  1111. X    /*
  1112. X     * Clear the non-fixed column labels and the cells in fixed rows
  1113. X     */
  1114. X    XClearArea(XtDisplay(mw), XtWindow(mw),
  1115. X           FIXED_COLUMN_LABEL_OFFSET(mw), 0,
  1116. X           0 /*Full Width*/, FIXED_ROW_LABEL_OFFSET(mw), False);
  1117. X
  1118. X    /*
  1119. X     * Redraw non-fixed column labels and cells in fixed rows
  1120. X     */
  1121. X    SETRECT(rect,
  1122. X        FIXED_COLUMN_LABEL_OFFSET(mw), 0,
  1123. X        mw->core.width, FIXED_ROW_LABEL_OFFSET(mw));
  1124. X    RedrawLabelsAndFixed(mw, &rect);
  1125. X    }
  1126. X
  1127. X    /*
  1128. X     * If we scrolled less than a screenful, we want to copy as many
  1129. X     * pixels as we can and then clear and redraw the newly scrolled data.
  1130. X     */
  1131. X    else {
  1132. X    Rectangle rect;
  1133. X    int x_clear = src_x > dest_x ? width : 0;
  1134. X
  1135. X    /*
  1136. X     * Queue this scroll with the ScrollMgr
  1137. X     */
  1138. X    SmAddScroll(mw->matrix.clip_scroll_mgr, dest_x - src_x, 0);
  1139. X
  1140. X    /*
  1141. X     * Copy the non-fixed cells in the clip widget
  1142. X     */
  1143. X    XCopyArea(XtDisplay(mw),
  1144. X          XtWindow(ClipChild(mw)), XtWindow(ClipChild(mw)),
  1145. X          mw->matrix.draw_gc,
  1146. X          src_x, 0,
  1147. X          width, ClipChild(mw)->core.height,
  1148. X          dest_x, 0);
  1149. X
  1150. X    /*
  1151. X     * Clear the newly scrolled chunk of the clip widget
  1152. X     */
  1153. X    XClearArea(XtDisplay(mw), XtWindow(ClipChild(mw)),
  1154. X           x_clear, 0,
  1155. X           ClipChild(mw)->core.width - width, 0 /*Full Height*/,
  1156. X           False);
  1157. X
  1158. X    /*
  1159. X     * Redraw the non-fixed cells into the new chunk
  1160. X     */
  1161. X    SETRECT(rect,
  1162. X        x_clear, 0,
  1163. X        (x_clear + (ClipChild(mw)->core.width - width)) - 1,
  1164. X        ClipChild(mw)->core.height - 1);
  1165. X    RedrawCells(mw, &rect);
  1166. X
  1167. X    /*
  1168. X     * Translate coordinates for fixed rows and column labels.
  1169. X     */
  1170. X    src_x += FIXED_COLUMN_LABEL_OFFSET(mw);
  1171. X    dest_x += FIXED_COLUMN_LABEL_OFFSET(mw);
  1172. X    x_clear += FIXED_COLUMN_LABEL_OFFSET(mw);
  1173. X
  1174. X    /*
  1175. X     * Queue this scroll with the ScrollMgr
  1176. X     */
  1177. X    SmAddScroll(mw->matrix.matrix_scroll_mgr, dest_x - src_x, 0);
  1178. X
  1179. X    /*
  1180. X     * Copy the fixed rows and column labels
  1181. X     */
  1182. X    XCopyArea(XtDisplay(mw),
  1183. X          XtWindow(mw), XtWindow(mw),
  1184. X          mw->matrix.draw_gc,
  1185. X          src_x, 0,
  1186. X          width, FIXED_ROW_LABEL_OFFSET(mw),
  1187. X          dest_x, 0);
  1188. X
  1189. X    /*
  1190. X     * Clear the newly scrolled chunk of fixed rows and column labels
  1191. X     */
  1192. X    XClearArea(XtDisplay(mw), XtWindow(mw),
  1193. X           x_clear, 0,
  1194. X           ClipChild(mw)->core.width - width,
  1195. X           FIXED_ROW_LABEL_OFFSET(mw),
  1196. X           False);
  1197. X
  1198. X    /*
  1199. X     * Redraw the new chunk of fixed rows and column labels
  1200. X     */
  1201. X    SETRECT(rect,
  1202. X        x_clear, 0,
  1203. X        (x_clear + (ClipChild(mw)->core.width - width)) - 1,
  1204. X        FIXED_ROW_LABEL_OFFSET(mw) - 1);
  1205. X    RedrawLabelsAndFixed(mw, &rect);
  1206. X    }
  1207. }
  1208. X
  1209. /*
  1210. X * This is the modifyVerifyCallback we added to textField. We need to
  1211. X * call Matrixs modifyVerifyCallback list with the textField info
  1212. X * and the row/col that is changing.
  1213. X */
  1214. /* ARGSUSED */
  1215. static void
  1216. ModifyVerifyCB(w, mw, verify)
  1217. Widget w;
  1218. XXbaeMatrixWidget mw;
  1219. XXmTextVerifyCallbackStruct *verify;
  1220. {
  1221. X    XbaeMatrixModifyVerifyCallbackStruct call_data;
  1222. X
  1223. X    if (mw->matrix.modify_verify_callback == NULL)
  1224. X    return;
  1225. X
  1226. X    call_data.reason = XbaeModifyVerifyReason;
  1227. X    call_data.row = mw->matrix.current_row;
  1228. X    call_data.column = mw->matrix.current_column;
  1229. X    call_data.verify = verify;
  1230. X
  1231. X    XtCallCallbackList((Widget)mw, mw->matrix.modify_verify_callback,
  1232. X               (XtPointer) &call_data);
  1233. }
  1234. X
  1235. /*
  1236. X * This is the Clip widgets focusCallback. We want to give the focus to
  1237. X * the textField if a cell is being edited.  If no cells are being edited,
  1238. X * force an edit on the top left most visible cell.
  1239. X */
  1240. /* ARGSUSED */
  1241. static void
  1242. TraverseInCB(w, mw, call_data)
  1243. Widget w;
  1244. XXbaeMatrixWidget mw;
  1245. XXtPointer call_data;
  1246. {
  1247. X    /*
  1248. X     * If the traversing flag is set, then Clip got the focus because
  1249. X     * textField was trying to traverse out of mw.  We'll help it along.
  1250. X     * Sickening.
  1251. X     */
  1252. X    if (mw->matrix.traversing != NOT_TRAVERSING) {
  1253. X    XmProcessTraversal(w, mw->matrix.traversing);
  1254. X    return;
  1255. X    }
  1256. X
  1257. X    /*
  1258. X     * If the textField is managed and not visible, scroll it onto the screen
  1259. X     * and traverse to it.
  1260. X     */
  1261. X    if (XtIsManaged(TextChild(mw))) {
  1262. X    if (!IsCellVisible(mw,
  1263. X               mw->matrix.current_row, mw->matrix.current_column))
  1264. X        MakeCellVisible(mw,
  1265. X                mw->matrix.current_row, mw->matrix.current_column);
  1266. X    XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
  1267. X    }
  1268. X
  1269. X    /*
  1270. X     * Otherwise, no cell is being edited.  Force an edit on the top-left
  1271. X     * most visible cell.
  1272. X     */
  1273. X    else {
  1274. X    int column = XtoCol(mw, FIXED_COLUMN_WIDTH(mw) +  HORIZ_ORIGIN(mw));
  1275. X
  1276. X    (*((XbaeMatrixWidgetClass) XtClass(mw))->matrix_class.edit_cell)
  1277. X        (mw, VERT_ORIGIN(mw) + mw->matrix.fixed_rows, column);
  1278. X
  1279. X    XmProcessTraversal(TextChild(mw), XmTRAVERSE_CURRENT);
  1280. X    }
  1281. }
  1282. X
  1283. static void
  1284. CopyCells(mw)
  1285. XXbaeMatrixWidget mw;
  1286. {
  1287. X    String **copy;
  1288. X    int i, j;
  1289. X
  1290. X    /*
  1291. X     * Malloc an array of row pointers
  1292. X     */
  1293. X    copy = (String **) XtMalloc(mw->matrix.rows * sizeof(String *));
  1294. X
  1295. X    /*
  1296. X     * Malloc an array of Strings for each row pointer
  1297. X     */
  1298. X    for (i = 0; i < mw->matrix.rows; i++)
  1299. X    copy[i] = (String *) XtMalloc(mw->matrix.columns * sizeof(String));
  1300. X
  1301. X    /*
  1302. X     * Create a bunch of "" cells if cells was NULL
  1303. X     */
  1304. X    if (!mw->matrix.cells) {
  1305. X    for (i = 0; i < mw->matrix.rows; i++)
  1306. X        for (j = 0; j < mw->matrix.columns; j++)
  1307. X        copy[i][j] = XtNewString("");
  1308. X    }
  1309. X
  1310. X    /*
  1311. X     * Otherwise copy the table passed in
  1312. X     */
  1313. X    else {
  1314. X    for (i = 0; i < mw->matrix.rows; i++)
  1315. X        for (j = 0; j < mw->matrix.columns; j++) {
  1316. X        if (!mw->matrix.cells[i][j]) {
  1317. X            XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1318. X                    "copyCells", "badValue", "XbaeMatrix",
  1319. X                    "XbaeMatrix: NULL entry found in cell table",
  1320. X                    NULL, 0);
  1321. X            copy[i][j] = XtNewString("");
  1322. X        }
  1323. X        else
  1324. X            copy[i][j] = XtNewString(mw->matrix.cells[i][j]);
  1325. X        }
  1326. X    }
  1327. X
  1328. X    mw->matrix.cells = copy;
  1329. }
  1330. X
  1331. static void
  1332. CopyRowLabels(mw)
  1333. XXbaeMatrixWidget mw;
  1334. {
  1335. X    String *copy;
  1336. X    int i;
  1337. X
  1338. X    copy = (String *) XtMalloc(mw->matrix.rows * sizeof(String));
  1339. X
  1340. X    for (i = 0; i < mw->matrix.rows; i++)
  1341. X    if (!mw->matrix.row_labels[i]) {
  1342. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1343. X                "copyRowLabels", "badValue", "XbaeMatrix",
  1344. X                "XbaeMatrix: NULL entry found in rowLabels array",
  1345. X                NULL, 0);
  1346. X        copy[i] = XtNewString("");
  1347. X    }
  1348. X    else
  1349. X        copy[i] = XtNewString(mw->matrix.row_labels[i]);
  1350. X
  1351. X    mw->matrix.row_labels = copy;
  1352. }
  1353. X
  1354. static void
  1355. CopyColumnLabels(mw)
  1356. XXbaeMatrixWidget mw;
  1357. {
  1358. X    String *copy;
  1359. X    int i;
  1360. X
  1361. X    copy = (String *) XtMalloc(mw->matrix.columns * sizeof(String));
  1362. X
  1363. X    mw->matrix.column_label_lines = (ColumnLabelLines)
  1364. X    XtMalloc(mw->matrix.columns * sizeof(ColumnLabelLinesRec));
  1365. X
  1366. X    for (i = 0; i < mw->matrix.columns; i++)
  1367. X    if (!mw->matrix.column_labels[i]) {
  1368. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1369. X                "copyColumnLabels", "badValue", "XbaeMatrix",
  1370. X                "XbaeMatrix: NULL entry found in columnLabels array",
  1371. X                NULL, 0);
  1372. X        copy[i] = XtNewString("");
  1373. X        ParseColumnLabel(copy[i], &mw->matrix.column_label_lines[i]);
  1374. X    }
  1375. X    else {
  1376. X        copy[i] = XtNewString(mw->matrix.column_labels[i]);
  1377. X        ParseColumnLabel(mw->matrix.column_labels[i],
  1378. X                 &mw->matrix.column_label_lines[i]);
  1379. X    }
  1380. X
  1381. X    /*
  1382. X     * Determine max number of lines in column labels
  1383. X     */
  1384. X    mw->matrix.column_label_maxlines = mw->matrix.column_label_lines[0].lines;
  1385. X    for (i = 1; i < mw->matrix.columns; i++)
  1386. X    if (mw->matrix.column_label_lines[i].lines >
  1387. X        mw->matrix.column_label_maxlines)
  1388. X        mw->matrix.column_label_maxlines =
  1389. X        mw->matrix.column_label_lines[i].lines;
  1390. X
  1391. X    mw->matrix.column_labels = copy;
  1392. }
  1393. X
  1394. static void
  1395. CopyColumnWidths(mw)
  1396. XXbaeMatrixWidget mw;
  1397. {
  1398. X    short *copy;
  1399. X    int i;
  1400. X    Boolean bad = False;
  1401. X
  1402. X    copy = (short *) XtMalloc(mw->matrix.columns * sizeof(short));
  1403. X
  1404. X    for (i = 0; i < mw->matrix.columns; i++) {
  1405. X    if (!bad && mw->matrix.column_widths[i] == BAD_WIDTH) {
  1406. X        bad = True;
  1407. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1408. X                "copyColumnWidths", "tooShort", "XbaeMatrix",
  1409. X                "XbaeMatrix: Column widths array is too short",
  1410. X                NULL, 0);
  1411. X        copy[i] = 1;
  1412. X    }
  1413. X    else if (bad)
  1414. X        copy[i] = 1;
  1415. X    else
  1416. X        copy[i] = mw->matrix.column_widths[i];
  1417. X    }
  1418. X
  1419. X    mw->matrix.column_widths = copy;
  1420. }
  1421. X
  1422. static void
  1423. CopyColumnMaxLengths(mw)
  1424. XXbaeMatrixWidget mw;
  1425. {
  1426. X    int *copy;
  1427. X    int i;
  1428. X    Boolean bad = False;
  1429. X
  1430. X    copy = (int *) XtMalloc(mw->matrix.columns * sizeof(int));
  1431. X
  1432. X    for (i = 0; i < mw->matrix.columns; i++) {
  1433. X    if (!bad && mw->matrix.column_max_lengths[i] == BAD_MAXLENGTH) {
  1434. X        bad = True;
  1435. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1436. X                "copyColumnMaxLengths", "tooShort", "XbaeMatrix",
  1437. X                "XbaeMatrix: Column max lengths array is too short",
  1438. X                NULL, 0);
  1439. X        copy[i] = 1;
  1440. X    }
  1441. X    else if (bad)
  1442. X        copy[i] = 1;
  1443. X    else
  1444. X        copy[i] = mw->matrix.column_max_lengths[i];
  1445. X    }
  1446. X
  1447. X    mw->matrix.column_max_lengths = copy;
  1448. }
  1449. X
  1450. static void
  1451. CopyColumnAlignments(mw)
  1452. XXbaeMatrixWidget mw;
  1453. {
  1454. X    unsigned char *copy;
  1455. X    int i;
  1456. X    Boolean bad = False;
  1457. X
  1458. X    copy = (unsigned char *) XtMalloc(mw->matrix.columns *
  1459. X                      sizeof(unsigned char));
  1460. X
  1461. X    for (i = 0; i < mw->matrix.columns; i++) {
  1462. X    if (!bad && mw->matrix.column_alignments[i] == BAD_ALIGNMENT) {
  1463. X        bad = True;
  1464. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1465. X                "copyColumnAlignments", "tooShort", "XbaeMatrix",
  1466. X                "XbaeMatrix: Column alignments array is too short",
  1467. X                NULL, 0);
  1468. X        copy[i] = XmALIGNMENT_BEGINNING;
  1469. X    }
  1470. X    else if (bad)
  1471. X        copy[i] = XmALIGNMENT_BEGINNING;
  1472. X    else
  1473. X        copy[i] = mw->matrix.column_alignments[i];
  1474. X    }
  1475. X
  1476. X    mw->matrix.column_alignments = copy;
  1477. }
  1478. X
  1479. static void
  1480. CopyColumnLabelAlignments(mw)
  1481. XXbaeMatrixWidget mw;
  1482. {
  1483. X    unsigned char *copy;
  1484. X    int i;
  1485. X    Boolean bad = False;
  1486. X
  1487. X    copy = (unsigned char *) XtMalloc(mw->matrix.columns *
  1488. X                      sizeof(unsigned char));
  1489. X
  1490. X    for (i = 0; i < mw->matrix.columns; i++) {
  1491. X    if (!bad &&
  1492. X        mw->matrix.column_label_alignments[i] == BAD_ALIGNMENT) {
  1493. X        bad = True;
  1494. X        XtAppWarningMsg(XtWidgetToApplicationContext((Widget)mw),
  1495. X                "copyColumnLabelAlignments", "tooShort",
  1496. X                "XbaeMatrix",
  1497. X                "XbaeMatrix: Column label alignments array is too short",
  1498. X                NULL, 0);
  1499. X        copy[i] = XmALIGNMENT_BEGINNING;
  1500. X    }
  1501. X    else if (bad)
  1502. X        copy[i] = XmALIGNMENT_BEGINNING;
  1503. X    else
  1504. X        copy[i] = mw->matrix.column_label_alignments[i];
  1505. X    }
  1506. X
  1507. X    mw->matrix.column_label_alignments = copy;
  1508. }
  1509. X
  1510. static void
  1511. CopyColors(mw)
  1512. XXbaeMatrixWidget mw;
  1513. {
  1514. X    Pixel **copy;
  1515. X    int i, j;
  1516. X
  1517. X    /*
  1518. X     * Malloc an array of row pointers
  1519. X     */
  1520. X    copy = (Pixel **) XtMalloc(mw->matrix.rows * sizeof(Pixel *));
  1521. X
  1522. X    /*
  1523. X     * Malloc an array of Pixels for each row pointer
  1524. X     */
  1525. X    for (i = 0; i < mw->matrix.rows; i++)
  1526. X    copy[i] = (Pixel *) XtMalloc(mw->matrix.columns * sizeof(Pixel));
  1527. X
  1528. X    for (i = 0; i < mw->matrix.rows; i++)
  1529. X    for (j = 0; j < mw->matrix.columns; j++)
  1530. X        copy[i][j] = mw->matrix.colors[i][j];
  1531. X
  1532. X    mw->matrix.colors = copy;
  1533. }
  1534. X
  1535. /*
  1536. X * Copy the selectedCells resource. Create a 2D array of Booleans to
  1537. X * represent selected cells if it is NULL.
  1538. X */
  1539. static void
  1540. CopySelectedCells(mw)
  1541. XXbaeMatrixWidget mw;
  1542. {
  1543. X    Boolean **copy;
  1544. X    int i, j;
  1545. X
  1546. X    /*
  1547. X     * Malloc an array of row pointers
  1548. X     */
  1549. X     copy = (Boolean **) XtMalloc(mw->matrix.rows * sizeof(Boolean *));
  1550. X
  1551. X    /*
  1552. X     * Malloc an array of Booleans for each row pointer
  1553. X     */
  1554. X    for (i = 0; i < mw->matrix.rows; i++)
  1555. X    copy[i] = (Boolean *) XtCalloc(mw->matrix.columns, sizeof(Boolean));
  1556. X
  1557. X    /*
  1558. X     * If selected_cells is not NULL, copy the table passed in
  1559. X     */
  1560. X    if (mw->matrix.selected_cells)
  1561. X    for (i = 0; i < mw->matrix.rows; i++)
  1562. X        for (j = 0; j < mw->matrix.columns; j++)
  1563. X        copy[i][j] = mw->matrix.selected_cells[i][j];
  1564. X
  1565. X    mw->matrix.selected_cells = copy;
  1566. }
  1567. X
  1568. static void
  1569. ParseColumnLabel(label, lines)
  1570. String label;
  1571. ColumnLabelLines lines;
  1572. {
  1573. X    char *nl;
  1574. X
  1575. X    /*
  1576. X     * First count the number of lines in the label
  1577. X     */
  1578. X    lines->lines = 1;
  1579. X    nl = label;
  1580. X    while ((nl = index(nl, '\n')) != NULL) {
  1581. X    nl++;
  1582. X    lines->lines++;
  1583. X    }
  1584. X
  1585. X    /*
  1586. X     * Now malloc a lengths array of the correct size.
  1587. X     */
  1588. X    lines->lengths = (int *) XtMalloc(lines->lines * sizeof(int));
  1589. X
  1590. X    /*
  1591. X     * An entry in the lengths array is the length of that line (substring).
  1592. X     */
  1593. X
  1594. X    /*
  1595. X     * Handle the case of one line (no index() needed)
  1596. X     */
  1597. X    if (lines->lines == 1)
  1598. X    lines->lengths[0] = strlen(label);
  1599. X    else {
  1600. X    int i;
  1601. X
  1602. X    nl = label;
  1603. X    i = 0;
  1604. X    while ((nl = index(nl, '\n')) != NULL) {
  1605. X        lines->lengths[i] = nl - label;
  1606. X        nl++;
  1607. X        label = nl;
  1608. X        i++;
  1609. X    }
  1610. X    lines->lengths[i] = strlen(label);
  1611. X    }
  1612. }
  1613. X
  1614. static void
  1615. FreeCells(mw)
  1616. XXbaeMatrixWidget mw;
  1617. {
  1618. X    int i, j;
  1619. X
  1620. X    if (!mw->matrix.cells)
  1621. X    return;
  1622. X
  1623. X    /*
  1624. X     * Free each cell in a row, then free the row and go to the next one
  1625. X     */
  1626. X    for (i = 0; i < mw->matrix.rows; i++) {
  1627. X    for (j = 0; j < mw->matrix.columns; j++)
  1628. X        XtFree((XtPointer) mw->matrix.cells[i][j]);
  1629. X    XtFree((XtPointer) mw->matrix.cells[i]);
  1630. X    }
  1631. X
  1632. X    /*
  1633. X     * Free the array of row pointers
  1634. X     */
  1635. X    XtFree((XtPointer) mw->matrix.cells);
  1636. }
  1637. X
  1638. static void
  1639. FreeRowLabels(mw)
  1640. XXbaeMatrixWidget mw;
  1641. {
  1642. X    int i;
  1643. X
  1644. X    if (!mw->matrix.row_labels)
  1645. X    return;
  1646. X
  1647. X    for (i = 0; i < mw->matrix.rows; i++)
  1648. X    XtFree((XtPointer)mw->matrix.row_labels[i]);
  1649. X
  1650. X    XtFree((XtPointer)mw->matrix.row_labels);
  1651. }
  1652. X
  1653. static void
  1654. FreeColumnLabels(mw)
  1655. XXbaeMatrixWidget mw;
  1656. {
  1657. X    int i;
  1658. X
  1659. X    if (!mw->matrix.column_labels)
  1660. X    return;
  1661. X
  1662. X    for (i = 0; i < mw->matrix.columns; i++) {
  1663. X    XtFree((XtPointer)mw->matrix.column_labels[i]);
  1664. X    XtFree((XtPointer)mw->matrix.column_label_lines[i].lengths);
  1665. X    }
  1666. X
  1667. X    XtFree((XtPointer)mw->matrix.column_label_lines);
  1668. X    XtFree((XtPointer)mw->matrix.column_labels);
  1669. }
  1670. X
  1671. X
  1672. static void
  1673. FreeColors(mw)
  1674. XXbaeMatrixWidget mw;
  1675. {
  1676. X    int i;
  1677. X
  1678. X    if (!mw->matrix.colors)
  1679. X    return;
  1680. X
  1681. X    /*
  1682. X     * Free each row of Pixels
  1683. X     */
  1684. X    for (i = 0; i < mw->matrix.rows; i++)
  1685. X    XtFree((XtPointer) mw->matrix.colors[i]);
  1686. X
  1687. X    /*
  1688. X     * Free the array of row pointers
  1689. X     */
  1690. X    XtFree((XtPointer) mw->matrix.colors);
  1691. }
  1692. X
  1693. static void
  1694. FreeSelectedCells(mw)
  1695. XXbaeMatrixWidget mw;
  1696. {
  1697. X    int i;
  1698. X
  1699. X    /*
  1700. X     * Free each row of Booleans
  1701. X     */
  1702. X    for (i = 0; i < mw->matrix.rows; i++)
  1703. X    XtFree((XtPointer) mw->matrix.selected_cells[i]);
  1704. X
  1705. X    /*
  1706. X     * Free the array of row pointers
  1707. X     */
  1708. X    XtFree((XtPointer) mw->matrix.selected_cells);
  1709. }
  1710. X
  1711. /*
  1712. X * Create a matrix of Pixels
  1713. X */
  1714. static void
  1715. CreateColors(mw)
  1716. XXbaeMatrixWidget mw;
  1717. {
  1718. X    int i;
  1719. X
  1720. X    /*
  1721. X     * Malloc an array of row pointers
  1722. X     */
  1723. X    mw->matrix.colors = (Pixel **) XtMalloc(mw->matrix.rows * sizeof(Pixel *));
  1724. X
  1725. X    /*
  1726. X     * Malloc an array of Pixels for each row pointer
  1727. X     */
  1728. X    for (i = 0; i < mw->matrix.rows; i++)
  1729. X    mw->matrix.colors[i] = (Pixel *) XtMalloc(mw->matrix.columns *
  1730. X                              sizeof(Pixel));
  1731. }
  1732. X
  1733. /*
  1734. X * Add rows/columns of cells when set_values changes our rows/columns
  1735. X */
  1736. static void
  1737. ResizeCells(current, new)
  1738. XXbaeMatrixWidget current;
  1739. XXbaeMatrixWidget new;
  1740. {
  1741. X    int i, j;
  1742. X    int safe_rows;
  1743. X
  1744. X    if (new->matrix.rows == current->matrix.rows)
  1745. X    safe_rows = new->matrix.rows;
  1746. X
  1747. X    /*
  1748. X     * Adding rows
  1749. X     */
  1750. X    if (new->matrix.rows > current->matrix.rows) {
  1751. X    /*
  1752. X     * Realloc a larger array of row pointers
  1753. X     */
  1754. X    new->matrix.cells =
  1755. X        (String **) XtRealloc((char *)new->matrix.cells,
  1756. X                   new->matrix.rows * sizeof(String *));
  1757. X
  1758. X    /*
  1759. X     * Malloc a new row array for each row. Initialize it with
  1760. X     * NULL Strings. Use the new column size.
  1761. X     */
  1762. X    for (i = current->matrix.rows; i < new->matrix.rows; i++) {
  1763. X        new->matrix.cells[i] =
  1764. X        (String *) XtMalloc(new->matrix.columns * sizeof(String));
  1765. X        for (j = 0; j < new->matrix.columns; j++)
  1766. X        new->matrix.cells[i][j] = XtNewString("");
  1767. X    }
  1768. X
  1769. X    safe_rows = current->matrix.rows;
  1770. X    }
  1771. X
  1772. X    /*
  1773. X     * Deleting rows
  1774. X     */
  1775. X    if (new->matrix.rows < current->matrix.rows) {
  1776. X    /*
  1777. X     * Free the cells in the rows being deleted and the rows themselves
  1778. X     */
  1779. X    for (i = new->matrix.rows; i < current->matrix.rows; i++) {
  1780. X        for (j = 0; j < current->matrix.columns; j++)
  1781. X        XtFree((XtPointer) new->matrix.cells[i][j]);
  1782. X        XtFree((XtPointer) new->matrix.cells[i]);
  1783. X    }
  1784. X
  1785. X    safe_rows = new->matrix.rows;
  1786. X    }
  1787. X
  1788. X    /*
  1789. X     * Adding columns
  1790. X     */
  1791. X    if (new->matrix.columns > current->matrix.columns) {
  1792. X    /*
  1793. X     * Realloc each row array. Do not touch any rows added/deleted above
  1794. X     * (use safe_rows)
  1795. X     */
  1796. X    for (i = 0; i < safe_rows; i++) {
  1797. X        new->matrix.cells[i] =
  1798. X        (String *) XtRealloc((char *)new->matrix.cells[i],
  1799. X                     new->matrix.columns * sizeof(String));
  1800. X        for (j = current->matrix.columns; j < new->matrix.columns; j++)
  1801. X        new->matrix.cells[i][j] = XtNewString("");
  1802. X    }
  1803. X    }
  1804. X
  1805. X    /*
  1806. X     * Deleting columns
  1807. X     */
  1808. X    if (new->matrix.columns < current->matrix.columns) {
  1809. X    /*
  1810. X     * Free all the cells in the deleted columns. Do not touch any
  1811. X     * rows added/deleted above (use safe_rows).
  1812. X     * We don't bother to realloc each row, just leave some wasted space.
  1813. X     * XXX is this a problem?
  1814. X     */
  1815. X    for (i = 0; i < safe_rows; i++)
  1816. X        for (j = new->matrix.columns; j < current->matrix.columns; j++)
  1817. X        XtFree((XtPointer) new->matrix.cells[i][j]);
  1818. X    }
  1819. }
  1820. X
  1821. /*
  1822. X * Add rows/columns of selected flags when set_values changes our rows/columns
  1823. X */
  1824. static void
  1825. ResizeSelectedCells(current, new)
  1826. XXbaeMatrixWidget current;
  1827. XXbaeMatrixWidget new;
  1828. {
  1829. X    int i;
  1830. X    int safe_rows;
  1831. X
  1832. X    if (new->matrix.rows == current->matrix.rows)
  1833. X    safe_rows = new->matrix.rows;
  1834. X
  1835. X    /*
  1836. X     * Adding rows
  1837. X     */
  1838. X    if (new->matrix.rows > current->matrix.rows) {
  1839. X    /*
  1840. X     * Realloc a larger array of row pointers
  1841. X     */
  1842. X    new->matrix.selected_cells =
  1843. X        (Boolean **) XtRealloc((char *)new->matrix.selected_cells,
  1844. X                   new->matrix.rows * sizeof(Boolean *));
  1845. X
  1846. X    /*
  1847. X     * Calloc a new row array for each row. Use the new column size.
  1848. X     */
  1849. X    for (i = current->matrix.rows; i < new->matrix.rows; i++)
  1850. X        new->matrix.selected_cells[i] =
  1851. X        (Boolean *) XtCalloc(new->matrix.columns, sizeof(Boolean));
  1852. X
  1853. X    safe_rows = current->matrix.rows;
  1854. X    }
  1855. X
  1856. X    /*
  1857. X     * Deleting rows
  1858. X     */
  1859. X    if (new->matrix.rows < current->matrix.rows) {
  1860. X    for (i = new->matrix.rows; i < current->matrix.rows; i++)
  1861. X        XtFree((XtPointer) new->matrix.selected_cells[i]);
  1862. X    safe_rows = new->matrix.rows;
  1863. X    }
  1864. X
  1865. X    /*
  1866. X     * Adding columns
  1867. X     */
  1868. X    if (new->matrix.columns > current->matrix.columns) {
  1869. X    /*
  1870. X     * Realloc each row array. Do not touch any rows added/deleted above
  1871. X     * (use safe_rows)
  1872. X     */
  1873. X    for (i = 0; i < safe_rows; i++) {
  1874. X        int j;
  1875. X
  1876. X        new->matrix.selected_cells[i] =
  1877. X        (Boolean *) XtRealloc((char *)new->matrix.selected_cells[i],
  1878. X                      new->matrix.columns * sizeof(Boolean));
  1879. X        for (j = current->matrix.columns; j < new->matrix.columns; j++)
  1880. X        new->matrix.selected_cells[i][j] = False;
  1881. X    }
  1882. X    }
  1883. X
  1884. X    /*
  1885. X     * Deleting columns
  1886. X     *   if (new->matrix.columns < current->matrix.columns)
  1887. X     * We don't bother to realloc, just leave some wasted space.
  1888. X     * XXX is this a problem?
  1889. X     */
  1890. }
  1891. X
  1892. /*
  1893. X * Add rows/columns of colors when set_values changes our rows/columns
  1894. X */
  1895. static void
  1896. ResizeColors(current, new)
  1897. XXbaeMatrixWidget current;
  1898. XXbaeMatrixWidget new;
  1899. {
  1900. X    int i, j;
  1901. X    int safe_rows;
  1902. X
  1903. X    if (new->matrix.rows == current->matrix.rows)
  1904. X    safe_rows = new->matrix.rows;
  1905. X
  1906. X    /*
  1907. X     * Adding rows
  1908. X     */
  1909. X    if (new->matrix.rows > current->matrix.rows) {
  1910. X    /*
  1911. X     * Realloc a larger array of row pointers
  1912. X     */
  1913. X    new->matrix.colors =
  1914. X        (Pixel **) XtRealloc((char *)new->matrix.colors,
  1915. X                 new->matrix.rows * sizeof(Pixel *));
  1916. SHAR_EOF
  1917. true || echo 'restore of Xbae/src/Matrix.c failed'
  1918. fi
  1919. echo 'End of Xbae part 7'
  1920. echo 'File Xbae/src/Matrix.c is continued in part 8'
  1921. echo 8 > _shar_seq_.tmp
  1922. exit 0
  1923. -- 
  1924. --
  1925. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1926. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1927. Sunnyvale, California 94086            at&t: 408/522-9236
  1928.