home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / Microline3.0 / XmL / Grid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  268.7 KB  |  10,563 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * The following source code is part of the Microline Widget Library.
  21.  * The Microline widget library is made available to Mozilla developers
  22.  * under the Netscape Public License (NPL) by Neuron Data.  To learn
  23.  * more about Neuron Data, please visit the Neuron Data Home Page at
  24.  * http://www.neurondata.com.
  25.  */
  26.  
  27. #include "GridP.h"
  28.  
  29. #include <Xm/ScrollBar.h>
  30. #include <Xm/Text.h>
  31. #include <Xm/DrawnB.h>
  32. #include <Xm/CutPaste.h>
  33. #include <X11/StringDefs.h>
  34. #include <X11/cursorfont.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37.  
  38. #ifdef SUNOS4
  39. int fprintf(FILE *, char *, ...);
  40. int fseek(FILE *, long, int);
  41. int fread(char *, int, int, FILE *);
  42. #endif
  43.  
  44. /* Create and Destroy */
  45. static void ClassInitialize(void);
  46. static void ClassPartInitialize(WidgetClass wc);
  47. static void Initialize(Widget req, Widget newW, ArgList args, Cardinal *nargs);
  48. static void Destroy(Widget w);
  49.  
  50. /* Geometry, Drawing, Entry and Picking */
  51. static void Realize(Widget w, XtValueMask *valueMask,
  52.     XSetWindowAttributes *attr);
  53. static void Redisplay(Widget w, XExposeEvent *event, Region region);
  54. static void DrawResizeLine(XmLGridWidget g, int xy, int erase);
  55. static void DrawXORRect(XmLGridWidget g, int xy, int size,
  56.     int isVert, int erase);
  57. static void DefineCursor(XmLGridWidget g, char defineCursor);
  58. static void DrawArea(XmLGridWidget g, int type, int row, int col);
  59. static void ExtendSelectRange(XmLGridWidget g, int *type,
  60.     int *fr, int *lr, int *fc, int *lc);
  61. static void ExtendSelect(XmLGridWidget g, XEvent *event, Boolean set,
  62.     int row, int col);
  63. static void SelectTypeArea(XmLGridWidget g, int type, XEvent *event,
  64.     int row, int col, Boolean select, Boolean notify);
  65. static int GetSelectedArea(XmLGridWidget g, int type, int *rowPos,
  66.     int *colPos, int count);
  67. static void ChangeManaged(Widget w);
  68. static void Resize(Widget w);
  69. static void PlaceScrollbars(XmLGridWidget w);
  70. static void VertLayout(XmLGridWidget g, int resizeIfNeeded);
  71. static void HorizLayout(XmLGridWidget g, int resizeIfNeeded);
  72. static void ApplyVisibleRows(XmLGridWidget g);
  73. static void ApplyVisibleCols(XmLGridWidget g);
  74. static void VisPosChanged(XmLGridWidget g, int isVert);
  75. static void RecalcVisPos(XmLGridWidget g, int isVert);
  76. static int PosToVisPos(XmLGridWidget g, int pos, int isVert);
  77. static int VisPosToPos(XmLGridWidget g, int visPos, int isVert);
  78. static unsigned char ColPosToType(XmLGridWidget g, int pos);
  79. static int ColPosToTypePos(XmLGridWidget g, unsigned char type, int pos);
  80. static unsigned char RowPosToType(XmLGridWidget g, int pos);
  81. static int RowPosToTypePos(XmLGridWidget g, unsigned char type, int pos);
  82. static int ColTypePosToPos(XmLGridWidget g, unsigned char type,
  83.     int pos, int allowNeg);
  84. static int RowTypePosToPos(XmLGridWidget g, unsigned char type,
  85.     int pos, int allowNeg);
  86. static int ScrollRowBottomPos(XmLGridWidget g, int row);
  87. static int ScrollColRightPos(XmLGridWidget g, int col);
  88. static int PosIsResize(XmLGridWidget g, int x, int y,
  89.     int *row, int *col, int *isVert);
  90. static int XYToRowCol(XmLGridWidget g, int x, int y, int *row, int *col);
  91. static int RowColToXY(XmLGridWidget g, int row, int col,
  92.     Boolean clipped, XRectangle *rect);
  93. static int RowColFirstSpan(XmLGridWidget g, int row, int col,
  94.     int *spanRow, int *spanCol, XRectangle *rect, Boolean lookLeft,
  95.     Boolean lookUp);
  96. static void RowColSpanRect(XmLGridWidget g, int row, int col, XRectangle *rect);
  97. static XmLGridCell GetCell(XmLGridWidget g, int row, int col);
  98. static int GetColWidth(XmLGridWidget g, int col);
  99. static int GetRowHeight(XmLGridWidget g, int row);
  100. static int ColIsVisible(XmLGridWidget g, int col);
  101. static int RowIsVisible(XmLGridWidget g, int row);
  102. static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request,
  103.     XtWidgetGeometry *);
  104. static void ScrollCB(Widget w, XtPointer, XtPointer);
  105. static int FindNextFocus(XmLGridWidget g, int row, int col,
  106.     int rowDir, int colDir, int *nextRow, int *nextCol);
  107. static int SetFocus(XmLGridWidget g, int row, int col, int rowDir, int colDir);
  108. static void ChangeFocus(XmLGridWidget g, int row, int col);
  109. static void MakeColVisible(XmLGridWidget g, int col);
  110. static void MakeRowVisible(XmLGridWidget g, int row);
  111. static void TextAction(XmLGridWidget g, int action);
  112.  
  113. /* Getting and Setting Values */
  114. static void GetSubValues(Widget w, ArgList args, Cardinal *nargs);
  115. static void SetSubValues(Widget w, ArgList args, Cardinal *nargs);
  116. static Boolean SetValues(Widget curW, Widget, Widget newW, 
  117.     ArgList args, Cardinal *nargs);
  118. static void CopyFontList(XmLGridWidget g);
  119. static Boolean CvtStringToSizePolicy(Display *dpy, XrmValuePtr args,
  120.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  121.     XtPointer *data);
  122. static Boolean CvtStringToSelectionPolicy(Display *dpy, XrmValuePtr args,
  123.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  124.     XtPointer *data);
  125. static Boolean CvtStringToRowColType(Display *dpy, XrmValuePtr args,
  126.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  127.     XtPointer *data);
  128. static Boolean CvtStringToCellAlignment(Display *dpy, XrmValuePtr args,
  129.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  130.     XtPointer *data);
  131. static Boolean CvtStringToCellType(Display *dpy, XrmValuePtr args,
  132.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  133.     XtPointer *data);
  134. static Boolean CvtStringToCellBorderType(Display *dpy, XrmValuePtr args,
  135.     Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal,
  136.     XtPointer *data);
  137. static void SetSimpleHeadings(XmLGridWidget g, char *data);
  138. static void SetSimpleWidths(XmLGridWidget g, char *data);
  139.  
  140. /* Getting and Setting Row Values */
  141. static void GetRowValueMask(XmLGridWidget g, char *s, long *mask);
  142. static void _GetRowValueMask(XmLGridWidget g, char *s, long *mask);
  143. static void GetRowValue(XmLGridWidget g, XmLGridRow row,
  144.     XtArgVal value, long mask);
  145. static void _GetRowValue(XmLGridWidget g, XmLGridRow row,
  146.     XtArgVal value, long mask);
  147. static int SetRowValues(XmLGridWidget g, XmLGridRow row, long mask);
  148. static int _SetRowValues(XmLGridWidget g, XmLGridRow row, long mask);
  149.  
  150. /* Getting and Setting Column Values */
  151. static void GetColumnValueMask(XmLGridWidget g, char *s, long *mask);
  152. static void _GetColumnValueMask(XmLGridWidget g, char *s, long *mask);
  153. static void GetColumnValue(XmLGridWidget g, XmLGridColumn col,
  154.     XtArgVal value, long mask);
  155. static void _GetColumnValue(XmLGridWidget g, XmLGridColumn col,
  156.     XtArgVal value, long mask);
  157. static int SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask);
  158. static int _SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask);
  159.  
  160. /* Getting and Setting Cell Values */
  161. static void CellValueGetMask(char *s, long *mask);
  162. static void GetCellValue(XmLGridCell cell, XtArgVal value, long mask);
  163. static XmLGridCellRefValues *CellRefValuesCreate(XmLGridWidget g,
  164.     XmLGridCellRefValues *copy);
  165. static void SetCellValuesPreprocess(XmLGridWidget g, long mask);
  166. static int SetCellHasRefValues(long mask);
  167. static int SetCellValuesResize(XmLGridWidget g, XmLGridRow row,
  168.     XmLGridColumn col, XmLGridCell cell, long mask);
  169. static int _SetCellValuesResize(XmLGridWidget g, XmLGridRow row,
  170.     XmLGridColumn col, XmLGridCell cell, long mask);
  171. static void SetCellValues(XmLGridWidget g, XmLGridCell cell, long mask);
  172. static void SetCellRefValues(XmLGridWidget g, XmLGridCellRefValues *values,
  173.     long mask);
  174. static int SetCellRefValuesCompare(void *, void **, void **);
  175. static void SetCellRefValuesPreprocess(XmLGridWidget g, int row, int col,
  176.     XmLGridCell cell, long mask);
  177.  
  178. /* Read, Write, Copy, Paste */
  179. static int Read(XmLGridWidget g, int format, char delimiter,
  180.     int row, int col, char *data);
  181. static void Write(XmLGridWidget g, FILE *file, int format, char delimiter,
  182.     Boolean skipHidden, int row, int col, int nrow, int ncol);
  183. static char *CopyDataCreate(XmLGridWidget g, int selected, int row, int col,
  184.     int nrow, int ncol);
  185. static Boolean Copy(XmLGridWidget g, Time time, int selected,
  186.     int row, int col, int nrow, int ncol);
  187. static Boolean Paste(XmLGridWidget g, int row, int col);
  188.  
  189. /* Utility */
  190. static void GetCoreBackground(Widget w, int, XrmValue *value);
  191. static void GetManagerForeground(Widget w, int, XrmValue *value);
  192. static void ClipRectToReg(XmLGridWidget g, XRectangle *rect, GridReg *reg);
  193. static char *FileToString(FILE *file);
  194. static char *CvtXmStringToStr(XmString str);
  195. static XmLGridWidget WidgetToGrid(Widget w, char *funcname);
  196.  
  197. /* Actions, Callbacks and Handlers */
  198. static void ButtonMotion(Widget w, XEvent *event, String *, Cardinal *);
  199. static void DragTimer(XtPointer, XtIntervalId *);
  200. static void CursorMotion(Widget w, XEvent *event, String *, Cardinal *);
  201. static void Edit(Widget w, XEvent *event, String *, Cardinal *);
  202. static void EditCancel(Widget w, XEvent *event, String *, Cardinal *);
  203. static void EditComplete(Widget w, XEvent *event, String *, Cardinal *);
  204. static void DragStart(Widget w, XEvent *event, String *, Cardinal *);
  205. static Boolean DragConvert(Widget w, Atom *selection, Atom *target,
  206.     Atom *type, XtPointer *value, unsigned long *length, int *format);
  207. static void DragFinish(Widget w, XtPointer clientData, XtPointer callData);
  208. static void DropRegister(XmLGridWidget g, Boolean set);
  209. static void DropStart(Widget w, XtPointer clientData, XtPointer callData);
  210. static void DropTransfer(Widget w, XtPointer clientData, Atom *selType,
  211.     Atom *type, XtPointer value, unsigned long *length, int *format);
  212. static void Select(Widget w, XEvent *event, String *, Cardinal *);
  213. static void TextActivate(Widget w, XtPointer clientData, XtPointer callData);
  214. static void TextFocus(Widget w, XtPointer clientData, XtPointer callData);
  215. static void TextMapped(Widget w, XtPointer closure, XEvent *event,
  216.     Boolean *ctd);
  217. static void TextModifyVerify(Widget w, XtPointer clientData,
  218.     XtPointer callData);
  219. static void Traverse(Widget w, XEvent *event, String *, Cardinal *);
  220.  
  221. /* XFE Additions */
  222. static void HideColumn(Widget w, XEvent *event, String *, Cardinal *);
  223. static void UnhideColumn(Widget w, XEvent *event, String *, Cardinal *);
  224. static void MenuArm(Widget w, XEvent *event, String *, Cardinal *);
  225. static void MenuDisarm(Widget w, XEvent *event, String *, Cardinal *);
  226.  
  227. /* XmLGridRow */
  228.  
  229. static XmLGridRow XmLGridRowNew(Widget grid);
  230. static void XmLGridRowFree(Widget grid, XmLGridRow row);
  231. static XmLGridRow _GridRowNew(Widget grid);
  232. static void _GridRowFree(XmLGridRow row);
  233. static XmLArray XmLGridRowCells(XmLGridRow row);
  234. static int XmLGridRowGetPos(XmLGridRow row);
  235. static int XmLGridRowGetVisPos(XmLGridRow row);
  236. static Boolean XmLGridRowIsHidden(XmLGridRow row);
  237. static Boolean XmLGridRowIsSelected(XmLGridRow row);
  238. static void XmLGridRowSetSelected(XmLGridRow row, Boolean selected);
  239. static void XmLGridRowSetVisPos(XmLGridRow row, int visPos);
  240. static int XmLGridRowHeightInPixels(XmLGridRow row);
  241. static void XmLGridRowHeightChanged(XmLGridRow row);
  242.  
  243. /* XmLGridColumn */
  244.  
  245. static XmLGridColumn XmLGridColumnNew(Widget grid);
  246. static void XmLGridColumnFree(Widget grid, XmLGridColumn column);
  247. static XmLGridColumn _GridColumnNew(Widget grid);
  248. static void _GridColumnFree(XmLGridColumn column);
  249. static int XmLGridColumnGetPos(XmLGridColumn column);
  250. static int XmLGridColumnGetVisPos(XmLGridColumn column);
  251. static Boolean XmLGridColumnIsHidden(XmLGridColumn column);
  252. static Boolean XmLGridColumnIsSelected(XmLGridColumn column);
  253. static void XmLGridColumnSetSelected(XmLGridColumn column, Boolean selected);
  254. static void XmLGridColumnSetVisPos(XmLGridColumn column, int visPos);
  255. static int XmLGridColumnWidthInPixels(XmLGridColumn column);
  256. static void XmLGridColumnWidthChanged(XmLGridColumn column);
  257.  
  258. /* XmLGridCell */
  259.  
  260. static XmLGridCell XmLGridCellNew();
  261. static void XmLGridCellFree(Widget grid, XmLGridCell cell);
  262. static int XmLGridCellAction(XmLGridCell cell, Widget w,
  263.     XmLGridCallbackStruct *cbs);
  264. static int _GridCellAction(XmLGridCell cell, Widget w,
  265.     XmLGridCallbackStruct *cbs);
  266. static XmLGridCellRefValues *XmLGridCellGetRefValues(XmLGridCell cell);
  267. static void XmLGridCellSetRefValues(XmLGridCell cell,
  268.     XmLGridCellRefValues *values);
  269. static void XmLGridCellDerefValues(XmLGridCellRefValues *values);
  270. static Boolean XmLGridCellInRowSpan(XmLGridCell cell);
  271. static Boolean XmLGridCellInColumnSpan(XmLGridCell cell);
  272. static Boolean XmLGridCellIsSelected(XmLGridCell cell);
  273. static Boolean XmLGridCellIsValueSet(XmLGridCell cell);
  274. static void XmLGridCellSetValueSet(XmLGridCell cell, Boolean set);
  275. static void XmLGridCellSetInRowSpan(XmLGridCell cell, Boolean set);
  276. static void XmLGridCellSetInColumnSpan(XmLGridCell cell, Boolean set);
  277. static void XmLGridCellSetSelected(XmLGridCell cell, Boolean selected);
  278. static void XmLGridCellAllocIcon(XmLGridCell cell);
  279. static void XmLGridCellAllocPixmap(XmLGridCell cell);
  280. static void XmLGridCellSetString(XmLGridCell cell, XmString string,
  281.     Boolean copy);
  282. static XmString XmLGridCellGetString(XmLGridCell cell);
  283. static void XmLGridCellSetToggle(XmLGridCell cell, Boolean state);
  284. static Boolean XmLGridCellGetToggle(XmLGridCell cell);
  285. static void XmLGridCellSetPixmap(XmLGridCell cell, Pixmap pixmap,
  286.     Dimension width, Dimension height);
  287. static void XmLGridCellSetPixmask(XmLGridCell cell, Pixmap pixmask);
  288. static XmLGridCellPixmap *XmLGridCellGetPixmap(XmLGridCell cell);
  289. /* static void XmLGridCellClearTextString(XmLGridCell cell, Widget w); */
  290. static int _XmLGridCellConfigureText(XmLGridCell cell, Widget w,
  291.     XRectangle *rect);
  292. static int _XmLGridCellBeginTextEdit(XmLGridCell cell, Widget w,
  293.     XRectangle *clipRect);
  294. static void _XmLGridCellCompleteTextEdit(XmLGridCell cell, Widget w);
  295. static void _XmLGridCellInsertText(XmLGridCell cell, Widget w);
  296. static int _XmLGridCellGetHeight(XmLGridCell cell, Widget w,XmLGridRow row);
  297. static int _XmLGridCellGetWidth(XmLGridCell cell, Widget w,XmLGridColumn col);
  298. static void _XmLGridCellFreeValue(XmLGridCell cell);
  299.  
  300. static XtActionsRec actions[] =
  301.     {
  302.     { "XmLGridEditComplete", EditComplete },
  303.     { "XmLGridButtonMotion", ButtonMotion },
  304.     { "XmLGridCursorMotion", CursorMotion },
  305.     { "XmLGridEditCancel",   EditCancel   },
  306.     { "XmLGridEdit",         Edit         },
  307.     { "XmLGridSelect",       Select       },
  308.     { "XmLGridDragStart",    DragStart    },
  309.     { "XmLGridTraverse",     Traverse     },
  310.     { "XmLGridHideColumn",   HideColumn   },
  311.     { "XmLGridUnhideColumn", UnhideColumn },
  312.     /* XFE Additions */
  313.     { "MenuArm", MenuArm },
  314.     { "MenuDisarm", MenuDisarm },
  315.     };
  316.  
  317. #define TEXT_HIDE           1
  318. #define TEXT_SHOW           2
  319. #define TEXT_EDIT           3
  320. #define TEXT_EDIT_CANCEL    4
  321. #define TEXT_EDIT_COMPLETE  5
  322. #define TEXT_EDIT_INSERT    6
  323.  
  324. /* future defines */
  325. #define XmTOGGLE_CELL  240
  326.  
  327. /* backwards compatibility defines */
  328. #define XmTEXT_CELL    250
  329. #define XmLABEL_CELL   251
  330.  
  331. /* Cursors */
  332.  
  333. #define horizp_width 19
  334. #define horizp_height 13
  335. static unsigned char horizp_bits[] = {
  336.  0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xff, 0x07, 0x00, 0x00, 0x06, 0x00,
  337.  0x00, 0x06, 0x00, 0x20, 0x46, 0x00, 0x30, 0xc6, 0x00, 0x38, 0xc6, 0x01,
  338.  0xfc, 0xff, 0x03, 0x38, 0xc6, 0x01, 0x30, 0xc6, 0x00, 0x20, 0x46, 0x00,
  339.  0x00, 0x06, 0x00 };
  340.  
  341. #define horizm_width 19
  342. #define horizm_height 13
  343. static unsigned char horizm_bits[] = {
  344.  0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00,
  345.  0x60, 0x6f, 0x00, 0x70, 0xef, 0x00, 0x78, 0xef, 0x01, 0xfc, 0xff, 0x03,
  346.  0xfe, 0xff, 0x07, 0xfc, 0xff, 0x03, 0x78, 0xef, 0x01, 0x70, 0xef, 0x00,
  347.  0x60, 0x6f, 0x00 };
  348.  
  349. #define vertp_width 13
  350. #define vertp_height 19
  351. static unsigned char vertp_bits[] = {
  352.    0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x03, 0xc6, 0x07, 0xe6, 0x0f,
  353.    0x06, 0x01, 0x06, 0x01, 0x06, 0x01, 0xfe, 0x1f, 0xfe, 0x1f, 0x00, 0x01,
  354.    0x00, 0x01, 0x00, 0x01, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 0x00, 0x01,
  355.    0x00, 0x00};
  356.  
  357. #define vertm_width 13
  358. #define vertm_height 19
  359. static unsigned char vertm_bits[] = {
  360.    0x0f, 0x00, 0x0f, 0x01, 0x8f, 0x03, 0xcf, 0x07, 0xef, 0x0f, 0xff, 0x1f,
  361.    0xff, 0x1f, 0x8f, 0x03, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f,
  362.    0x80, 0x03, 0xf0, 0x1f, 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03,
  363.    0x00, 0x01};
  364.  
  365. /* Grid Translations */
  366.  
  367. static char translations[] =
  368. "<Btn1Motion>:           XmLGridButtonMotion()\n\
  369. <MotionNotify>:          XmLGridCursorMotion()\n\
  370. ~Ctrl ~Shift <Btn1Down>: XmLGridSelect(BEGIN)\n\
  371. ~Ctrl Shift <Btn1Down>:  XmLGridSelect(EXTEND)\n\
  372. Ctrl ~Shift <Btn1Down>:  XmLGridSelect(TOGGLE)\n\
  373. <Btn1Up>:                XmLGridSelect(END)\n\
  374. <Btn2Down>:              XmLGridDragStart()\n\
  375. <EnterWindow>:           ManagerEnter()\n\
  376. <LeaveWindow>:           ManagerLeave()\n\
  377. <FocusOut>:              ManagerFocusOut()\n\
  378. <FocusIn>:               ManagerFocusIn()";
  379.  
  380. /* Text Translations */
  381.  
  382. static char traverseTranslations[] =
  383. "~Ctrl ~Shift <Key>osfUp:         XmLGridTraverse(UP)\n\
  384. ~Ctrl Shift <Key>osfUp:           XmLGridTraverse(EXTEND_UP)\n\
  385. Ctrl ~Shift <Key>osfUp:           XmLGridTraverse(PAGE_UP)\n\
  386. ~Ctrl ~Shift <Key>osfDown:        XmLGridTraverse(DOWN)\n\
  387. ~Ctrl Shift <Key>osfDown:         XmLGridTraverse(EXTEND_DOWN)\n\
  388. Ctrl ~Shift <Key>osfDown:         XmLGridTraverse(PAGE_DOWN)\n\
  389. ~Ctrl ~Shift <Key>osfLeft:        XmLGridTraverse(LEFT)\n\
  390. ~Ctrl Shift <Key>osfLeft:         XmLGridTraverse(EXTEND_LEFT)\n\
  391. Ctrl ~Shift <Key>osfLeft:         XmLGridTraverse(PAGE_LEFT)\n\
  392. ~Ctrl ~Shift <Key>osfRight:       XmLGridTraverse(RIGHT)\n\
  393. ~Ctrl Shift <Key>osfRight:        XmLGridTraverse(EXTEND_RIGHT)\n\
  394. Ctrl ~Shift <Key>osfRight:        XmLGridTraverse(PAGE_RIGHT)\n\
  395. ~Ctrl ~Shift <Key>osfPageUp:      XmLGridTraverse(PAGE_UP)\n\
  396. ~Ctrl Shift <Key>osfPageUp:       XmLGridTraverse(EXTEND_PAGE_UP)\n\
  397. Ctrl ~Shift <Key>osfPageUp:       XmLGridTraverse(PAGE_LEFT)\n\
  398. Ctrl Shift <Key>osfPageUp:        XmLGridTraverse(EXTEND_PAGE_LEFT)\n\
  399. ~Ctrl Shift <Key>osfPageDown:     XmLGridTraverse(EXTEND_PAGE_DOWN)\n\
  400. Ctrl ~Shift <Key>osfPageDown:     XmLGridTraverse(PAGE_RIGHT)\n\
  401. ~Ctrl ~Shift <Key>osfPageDown:    XmLGridTraverse(PAGE_DOWN)\n\
  402. Ctrl Shift <Key>osfPageDown:      XmLGridTraverse(EXTEND_PAGE_RIGHT)\n\
  403. ~Ctrl ~Shift <Key>Tab:            XmLGridTraverse(RIGHT)\n\
  404. ~Ctrl Shift <Key>Tab:             XmLGridTraverse(LEFT)\n\
  405. ~Ctrl ~Shift <Key>Home:           XmLGridTraverse(TO_TOP)\n\
  406. ~Ctrl ~Shift <Key>osfBeginLine:   XmLGridTraverse(TO_TOP)\n\
  407. Ctrl ~Shift <Key>Home:            XmLGridTraverse(TO_TOP_LEFT)\n\
  408. ~Ctrl ~Shift <Key>End:            XmLGridTraverse(TO_BOTTOM)\n\
  409. ~Ctrl ~Shift <Key>osfEndLine:     XmLGridTraverse(TO_BOTTOM)\n\
  410. Ctrl ~Shift <Key>End:             XmLGridTraverse(TO_BOTTOM_RIGHT)\n\
  411. <Key>osfInsert:                   XmLGridEdit()\n\
  412. <Key>F2:                          XmLGridEdit()\n\
  413. ~Ctrl ~Shift <KeyDown>space:      XmLGridSelect(BEGIN)\n\
  414. ~Ctrl Shift <KeyDown>space:       XmLGridSelect(EXTEND)\n\
  415. Ctrl ~Shift <KeyDown>space:       XmLGridSelect(TOGGLE)\n\
  416. <KeyUp>space:                     XmLGridSelect(END)";
  417.  
  418. /* You can't put multiple actions for any translation
  419.    where one translation changes the translation table
  420.    XmLGridComplete() and XmLGridCancel() do this and these
  421.    actions can't be combined with others */
  422. static char editTranslations[] =
  423. "~Ctrl ~Shift <Key>osfDown:     XmLGridEditComplete(DOWN)\n\
  424. ~Ctrl Shift <Key>Tab:            XmLGridEditComplete(LEFT)\n\
  425. ~Ctrl ~Shift <Key>Tab:            XmLGridEditComplete(RIGHT)\n\
  426. ~Ctrl ~Shift <Key>osfUp:        XmLGridEditComplete(UP)\n\
  427. <Key>osfCancel:                 XmLGridEditCancel()";
  428.  
  429. static XtResource resources[] =
  430.     {
  431.         /* Grid Resources */
  432.         {
  433.         XmNactivateCallback, XmCCallback,
  434.         XmRCallback, sizeof(XtCallbackList),
  435.         XtOffset(XmLGridWidget, grid.activateCallback),
  436.         XmRImmediate, (XtPointer)0,
  437.         },
  438.         {
  439.         XmNaddCallback, XmCCallback,
  440.         XmRCallback, sizeof(XtCallbackList),
  441.         XtOffset(XmLGridWidget, grid.addCallback),
  442.         XmRImmediate, (XtPointer)0,
  443.         },
  444.         {
  445.         XmNallowColumnHide, XmCAllowColumnHide,
  446.         XmRBoolean, sizeof(Boolean),
  447.         XtOffset(XmLGridWidget, grid.allowColHide),
  448.         XmRImmediate, (XtPointer)False,
  449.         },
  450.         {
  451.         XmNallowColumnResize, XmCAllowColumnResize,
  452.         XmRBoolean, sizeof(Boolean),
  453.         XtOffset(XmLGridWidget, grid.allowColResize),
  454.         XmRImmediate, (XtPointer)False,
  455.         },
  456.         {
  457.         XmNallowDragSelected, XmCAllowDragSelected,
  458.         XmRBoolean, sizeof(Boolean),
  459.         XtOffset(XmLGridWidget, grid.allowDrag),
  460.         XmRImmediate, (XtPointer)False,
  461.         },
  462.         {
  463.         XmNallowDrop, XmCAllowDrop,
  464.         XmRBoolean, sizeof(Boolean),
  465.         XtOffset(XmLGridWidget, grid.allowDrop),
  466.         XmRImmediate, (XtPointer)False,
  467.         },
  468.         {
  469.         XmNallowRowHide, XmCAllowRowHide,
  470.         XmRBoolean, sizeof(Boolean),
  471.         XtOffset(XmLGridWidget, grid.allowRowHide),
  472.         XmRImmediate, (XtPointer)False,
  473.         },
  474.         {
  475.         XmNallowRowResize, XmCAllowRowResize,
  476.         XmRBoolean, sizeof(Boolean),
  477.         XtOffset(XmLGridWidget, grid.allowRowResize),
  478.         XmRImmediate, (XtPointer)False,
  479.         },
  480.         {
  481.         XmNautoSelect, XmCAutoSelect,
  482.         XmRBoolean, sizeof(Boolean),
  483.         XtOffset(XmLGridWidget, grid.autoSelect),
  484.         XmRImmediate, (XtPointer)True,
  485.         },
  486.         {
  487.         XmNblankBackground, XmCBlankBackground,
  488.         XmRPixel, sizeof(Pixel),
  489.         XtOffset(XmLGridWidget, grid.blankBg),
  490.         XmRCallProc, (XtPointer)GetCoreBackground,
  491.         },
  492.         {
  493.         XmNbottomFixedCount, XmCBottomFixedCount,
  494.         XmRInt, sizeof(int),
  495.         XtOffset(XmLGridWidget, grid.bottomFixedCount),
  496.         XmRImmediate, (XtPointer)0,
  497.         },
  498.         {
  499.         XmNbottomFixedMargin, XmCBottomFixedMargin,
  500.         XmRDimension, sizeof(Dimension),
  501.         XtOffset(XmLGridWidget, grid.bottomFixedMargin),
  502.         XmRImmediate, (XtPointer)0,
  503.         },
  504.         {
  505.         XmNcellDefaults, XmCCellDefaults,
  506.         XmRBoolean, sizeof(Boolean),
  507.         XtOffset(XmLGridWidget, grid.cellDefaults),
  508.         XmRImmediate, (XtPointer)False,
  509.         },
  510.         {
  511.         XmNcellDrawCallback, XmCCallback,
  512.         XmRCallback, sizeof(XtCallbackList),
  513.         XtOffset(XmLGridWidget, grid.cellDrawCallback),
  514.         XmRImmediate, (XtPointer)0,
  515.         },
  516.         {
  517.         XmNcellDropCallback, XmCCallback,
  518.         XmRCallback, sizeof(XtCallbackList),
  519.         XtOffset(XmLGridWidget, grid.cellDropCallback),
  520.         XmRImmediate, (XtPointer)0,
  521.         },
  522.         {
  523.         XmNcellFocusCallback, XmCCallback,
  524.         XmRCallback, sizeof(XtCallbackList),
  525.         XtOffset(XmLGridWidget, grid.cellFocusCallback),
  526.         XmRImmediate, (XtPointer)0,
  527.         },
  528.         {
  529.         XmNcellPasteCallback, XmCCallback,
  530.         XmRCallback, sizeof(XtCallbackList),
  531.         XtOffset(XmLGridWidget, grid.cellPasteCallback),
  532.         XmRImmediate, (XtPointer)0,
  533.         },
  534.         {
  535.         XmNcolumns, XmCColumns,
  536.         XmRInt, sizeof(int),
  537.         XtOffset(XmLGridWidget, grid.colCount),
  538.         XmRImmediate, (XtPointer)0,
  539.         },
  540.         {
  541.         XmNdeleteCallback, XmCCallback,
  542.         XmRCallback, sizeof(XtCallbackList),
  543.         XtOffset(XmLGridWidget, grid.deleteCallback),
  544.         XmRImmediate, (XtPointer)0,
  545.         },
  546.         {
  547.         XmNdeselectCallback, XmCCallback,
  548.         XmRCallback, sizeof(XtCallbackList),
  549.         XtOffset(XmLGridWidget, grid.deselectCallback),
  550.         XmRImmediate, (XtPointer)0,
  551.         },
  552.         {
  553.         XmNdebugLevel, XmCDebugLevel,
  554.         XmRInt, sizeof(int),
  555.         XtOffset(XmLGridWidget, grid.debugLevel),
  556.         XmRImmediate, (XtPointer)0,
  557.         },
  558.         {
  559.         XmNeditCallback, XmCCallback,
  560.         XmRCallback, sizeof(XtCallbackList),
  561.         XtOffset(XmLGridWidget, grid.editCallback),
  562.         XmRImmediate, (XtPointer)0,
  563.         },
  564.         {
  565.         XmNeditTranslations, XmCTranslations,
  566.         XmRTranslationTable, sizeof(XtTranslations),
  567.         XtOffset(XmLGridWidget, grid.editTrans),
  568.         XmRString, (XtPointer)editTranslations,
  569.         },
  570.         {
  571.         XmNfontList, XmCFontList,
  572.         XmRFontList, sizeof(XmFontList),
  573.         XtOffset(XmLGridWidget, grid.fontList),
  574.         XmRImmediate, (XtPointer)0
  575.         },
  576.         {
  577.         XmNfooterColumns, XmCFooterColumns,
  578.         XmRInt, sizeof(int),
  579.         XtOffset(XmLGridWidget, grid.footerColCount),
  580.         XmRImmediate, (XtPointer)0,
  581.         },
  582.         {
  583.         XmNfooterRows, XmCFooterRows,
  584.         XmRInt, sizeof(int),
  585.         XtOffset(XmLGridWidget, grid.footerRowCount),
  586.         XmRImmediate, (XtPointer)0,
  587.         },
  588.         {
  589.         XmNglobalPixmapHeight, XmCGlobalPixmapHeight,
  590.         XmRDimension, sizeof(Dimension),
  591.         XtOffset(XmLGridWidget, grid.globalPixmapHeight),
  592.         XmRImmediate, (XtPointer)0,
  593.         },
  594.         {
  595.         XmNglobalPixmapWidth, XmCGlobalPixmapWidth,
  596.         XmRDimension, sizeof(Dimension),
  597.         XtOffset(XmLGridWidget, grid.globalPixmapWidth),
  598.         XmRImmediate, (XtPointer)0,
  599.         },
  600.         {
  601.         XmNheadingColumns, XmCHeadingColumns,
  602.         XmRInt, sizeof(int),
  603.         XtOffset(XmLGridWidget, grid.headingColCount),
  604.         XmRImmediate, (XtPointer)0,
  605.         },
  606.         {
  607.         XmNheadingRows, XmCHeadingRows,
  608.         XmRInt, sizeof(int),
  609.         XtOffset(XmLGridWidget, grid.headingRowCount),
  610.         XmRImmediate, (XtPointer)0,
  611.         },
  612.         {
  613.         XmNhiddenColumns, XmCHiddenColumns,
  614.         XmRInt, sizeof(int),
  615.         XtOffset(XmLGridWidget, grid.hiddenColCount),
  616.         XmRImmediate, (XtPointer)0,
  617.         },
  618.         {
  619.         XmNhiddenRows, XmCHiddenRows,
  620.         XmRInt, sizeof(int),
  621.         XtOffset(XmLGridWidget, grid.hiddenRowCount),
  622.         XmRImmediate, (XtPointer)0,
  623.         },
  624.         {
  625.         XmNhighlightRowMode, XmCHighlightRowMode,
  626.         XmRBoolean, sizeof(Boolean),
  627.         XtOffset(XmLGridWidget, grid.highlightRowMode),
  628.         XmRImmediate, (XtPointer)False,
  629.         },
  630.         {
  631.         XmNhighlightThickness, XmCHighlightThickness,
  632.         XmRDimension, sizeof(Dimension),
  633.         XtOffset(XmLGridWidget, grid.highlightThickness),
  634.         XmRImmediate, (XtPointer)2,
  635.         },
  636.         {
  637.         XmNhorizontalScrollBar, XmCHorizontalScrollBar,
  638.         XmRWidget, sizeof(Widget),
  639.         XtOffset(XmLGridWidget, grid.hsb),
  640.         XmRImmediate, (XtPointer)0,
  641.         },
  642.         {
  643.         XmNhorizontalSizePolicy, XmCHorizontalSizePolicy,
  644.         XmRGridSizePolicy, sizeof(unsigned char),
  645.         XtOffset(XmLGridWidget, grid.hsPolicy),
  646.         XmRImmediate, (XtPointer)XmCONSTANT,
  647.         },
  648.         {
  649.         XmNhsbDisplayPolicy, XmCHsbDisplayPolicy,
  650.         XmRScrollBarDisplayPolicy, sizeof(unsigned char),
  651.         XtOffset(XmLGridWidget, grid.hsbDisplayPolicy),
  652.         XmRImmediate, (XtPointer)XmAS_NEEDED,
  653.         },
  654.         {
  655.         XmNimmediateDraw, XmCImmediateDraw,
  656.         XmRBoolean, sizeof(Boolean),
  657.         XtOffset(XmLGridWidget, grid.immediateDraw),
  658.         XmRImmediate, (XtPointer)False,
  659.         },
  660.         {
  661.         XmNlayoutFrozen, XmCLayoutFrozen,
  662.         XmRBoolean, sizeof(Boolean),
  663.         XtOffset(XmLGridWidget, grid.layoutFrozen),
  664.         XmRImmediate, (XtPointer)False,
  665.         },
  666.         {
  667.         XmNleftFixedCount, XmCLeftFixedCount,
  668.         XmRInt, sizeof(int),
  669.         XtOffset(XmLGridWidget, grid.leftFixedCount),
  670.         XmRImmediate, (XtPointer)0,
  671.         },
  672.         {
  673.         XmNleftFixedMargin, XmCLeftFixedMargin,
  674.         XmRDimension, sizeof(Dimension),
  675.         XtOffset(XmLGridWidget, grid.leftFixedMargin),
  676.         XmRImmediate, (XtPointer)0,
  677.         },
  678.         {
  679.         XmNrightFixedCount, XmCRightFixedCount,
  680.         XmRInt, sizeof(int),
  681.         XtOffset(XmLGridWidget, grid.rightFixedCount),
  682.         XmRImmediate, (XtPointer)0,
  683.         },
  684.         {
  685.         XmNrightFixedMargin, XmCRightFixedMargin,
  686.         XmRDimension, sizeof(Dimension),
  687.         XtOffset(XmLGridWidget, grid.rightFixedMargin),
  688.         XmRImmediate, (XtPointer)0,
  689.         },
  690.         {
  691.         XmNresizeCallback, XmCCallback,
  692.         XmRCallback, sizeof(XtCallbackList),
  693.         XtOffset(XmLGridWidget, grid.resizeCallback),
  694.         XmRImmediate, (XtPointer)0,
  695.         },
  696.         {
  697.         XmNrows, XmCRows,
  698.         XmRInt, sizeof(int),
  699.         XtOffset(XmLGridWidget, grid.rowCount),
  700.         XmRImmediate, (XtPointer)0,
  701.         },
  702.         {
  703.         XmNscrollBarMargin, XmCScrollBarMargin,
  704.         XmRDimension, sizeof(Dimension),
  705.         XtOffset(XmLGridWidget, grid.scrollBarMargin),
  706.         XmRImmediate, (XtPointer)2,
  707.         },
  708.         {
  709.         XmNscrollCallback, XmCCallback,
  710.         XmRCallback, sizeof(XtCallbackList),
  711.         XtOffset(XmLGridWidget, grid.scrollCallback),
  712.         XmRImmediate, (XtPointer)0,
  713.         },
  714.         {
  715.         XmNscrollColumn, XmCScrollColumn,
  716.         XmRInt, sizeof(int),
  717.         XtOffset(XmLGridWidget, grid.cScrollCol),
  718.         XmRImmediate, (XtPointer)0,
  719.         },
  720.         {
  721.         XmNscrollRow, XmCScrollRow,
  722.         XmRInt, sizeof(int),
  723.         XtOffset(XmLGridWidget, grid.cScrollRow),
  724.         XmRImmediate, (XtPointer)0,
  725.         },
  726.         {
  727.         XmNselectCallback, XmCCallback,
  728.         XmRCallback, sizeof(XtCallbackList),
  729.         XtOffset(XmLGridWidget, grid.selectCallback),
  730.         XmRImmediate, (XtPointer)0,
  731.         },
  732.         {
  733.         XmNselectionPolicy, XmCGridSelectionPolicy,
  734.         XmRGridSelectionPolicy, sizeof(unsigned char),
  735.         XtOffset(XmLGridWidget, grid.selectionPolicy),
  736.         XmRImmediate, (XtPointer)XmSELECT_BROWSE_ROW,
  737.         },
  738.         {
  739.         XmNselectBackground, XmCSelectBackground,
  740.         XmRPixel, sizeof(Pixel),
  741.         XtOffset(XmLGridWidget, grid.selectBg),
  742.         XmRCallProc, (XtPointer)GetManagerForeground,
  743.         },
  744.         {
  745.         XmNselectForeground, XmCSelectForeground,
  746.         XmRPixel, sizeof(Pixel),
  747.         XtOffset(XmLGridWidget, grid.selectFg),
  748.         XmRCallProc, (XtPointer)GetCoreBackground,
  749.         },
  750.         {
  751.         XmNshadowRegions, XmCShadowRegions,
  752.         XmRInt, sizeof(int),
  753.         XtOffset(XmLGridWidget, grid.shadowRegions),
  754.         XmRImmediate, (XtPointer)511,
  755.         },
  756.         {
  757.         XmNshadowType, XmCShadowType,
  758.         XmRShadowType, sizeof(unsigned char),
  759.         XtOffset(XmLGridWidget, grid.shadowType),
  760.         XmRImmediate, (XtPointer)XmSHADOW_IN,
  761.         },
  762.         {
  763.         XmNsimpleHeadings, XmCSimpleHeadings,
  764.         XmRString, sizeof(char *),
  765.         XtOffset(XmLGridWidget, grid.simpleHeadings),
  766.         XmRImmediate, (XtPointer)0,
  767.         },
  768.         {
  769.         XmNsimpleWidths, XmCSimpleWidths,
  770.         XmRString, sizeof(char *),
  771.         XtOffset(XmLGridWidget, grid.simpleWidths),
  772.         XmRImmediate, (XtPointer)0,
  773.         },
  774.         {
  775.         XmNtextWidget, XmCTextWidget,
  776.         XmRWidget, sizeof(Widget),
  777.         XtOffset(XmLGridWidget, grid.text),
  778.         XmRImmediate, (XtPointer)0,
  779.         },
  780.         {
  781.         XmNtoggleBottomColor, XmCToggleBottomColor,
  782.         XmRPixel, sizeof(Pixel),
  783.         XtOffset(XmLGridWidget, grid.toggleBotColor),
  784.         XmRCallProc, (XtPointer)GetManagerForeground,
  785.         },
  786.         {
  787.         XmNtoggleTopColor, XmCToggleTopColor,
  788.         XmRPixel, sizeof(Pixel),
  789.         XtOffset(XmLGridWidget, grid.toggleTopColor),
  790.         XmRCallProc, (XtPointer)GetManagerForeground,
  791.         },
  792.         {
  793.         XmNtoggleSize, XmCToggleSize,
  794.         XmRDimension, sizeof(Dimension),
  795.         XtOffset(XmLGridWidget, grid.toggleSize),
  796.         XmRImmediate, (XtPointer)16,
  797.         },
  798.         {
  799.         XmNtraverseTranslations, XmCTranslations,
  800.         XmRTranslationTable, sizeof(XtTranslations),
  801.         XtOffset(XmLGridWidget, grid.traverseTrans),
  802.         XmRString, (XtPointer)traverseTranslations,
  803.         },
  804.         {
  805.         XmNtopFixedCount, XmCTopFixedCount,
  806.         XmRInt, sizeof(int),
  807.         XtOffset(XmLGridWidget, grid.topFixedCount),
  808.         XmRImmediate, (XtPointer)0,
  809.         },
  810.         {
  811.         XmNtopFixedMargin, XmCTopFixedMargin,
  812.         XmRDimension, sizeof(Dimension),
  813.         XtOffset(XmLGridWidget, grid.topFixedMargin),
  814.         XmRImmediate, (XtPointer)0,
  815.         },
  816.         {
  817.         XmNuseAverageFontWidth, XmCUseAverageFontWidth,
  818.         XmRBoolean, sizeof(Boolean),
  819.         XtOffset(XmLGridWidget, grid.useAvgWidth),
  820.         XmRImmediate, (XtPointer)True,
  821.         },
  822.         {
  823.         XmNverticalScrollBar, XmCVerticalScrollBar,
  824.         XmRWidget, sizeof(Widget),
  825.         XtOffset(XmLGridWidget, grid.vsb),
  826.         XmRImmediate, (XtPointer)0,
  827.         },
  828.         {
  829.         XmNverticalSizePolicy, XmCVerticalSizePolicy,
  830.         XmRGridSizePolicy, sizeof(unsigned char),
  831.         XtOffset(XmLGridWidget, grid.vsPolicy),
  832.         XmRImmediate, (XtPointer)XmCONSTANT,
  833.         },
  834.         {
  835.         XmNvisibleColumns, XmCVisibleColumns,
  836.         XmRInt, sizeof(int),
  837.         XtOffset(XmLGridWidget, grid.visibleCols),
  838.         XmRImmediate, (XtPointer)0,
  839.         },
  840.         {
  841.         XmNvisibleRows, XmCVisibleRows,
  842.         XmRInt, sizeof(int),
  843.         XtOffset(XmLGridWidget, grid.visibleRows),
  844.         XmRImmediate, (XtPointer)0,
  845.         },
  846.         {
  847.         XmNvsbDisplayPolicy, XmCVsbDisplayPolicy,
  848.         XmRScrollBarDisplayPolicy, sizeof(unsigned char),
  849.         XtOffset(XmLGridWidget, grid.vsbDisplayPolicy),
  850.         XmRImmediate, (XtPointer)XmAS_NEEDED,
  851.         },
  852.         /* Row Resources */
  853.         {
  854.         XmNrow, XmCGridRow,
  855.         XmRInt, sizeof(int),
  856.         XtOffset(XmLGridWidget, grid.cellRow),
  857.         XmRImmediate, (XtPointer)-1,
  858.         },
  859.         {
  860.         XmNrowUserData, XmCUserData,
  861.         XmRPointer, sizeof(XtPointer),
  862.         XtOffset(XmLGridWidget, grid.rowUserData),
  863.         XmRImmediate, (XtPointer)0,
  864.         },
  865.         {
  866.         XmNrowHeight, XmCRowHeight,
  867.         XmRDimension, sizeof(Dimension),
  868.         XtOffset(XmLGridWidget, grid.rowHeight),
  869.         XmRImmediate, (XtPointer)0,
  870.         },
  871.         {
  872.         XmNrowRangeEnd, XmCRowRangeEnd,
  873.         XmRInt, sizeof(int),
  874.         XtOffset(XmLGridWidget, grid.cellRowRangeEnd),
  875.         XmRImmediate, (XtPointer)-1,
  876.         },
  877.         {
  878.         XmNrowRangeStart, XmCRowRangeStart,
  879.         XmRInt, sizeof(int),
  880.         XtOffset(XmLGridWidget, grid.cellRowRangeStart),
  881.         XmRImmediate, (XtPointer)-1,
  882.         },
  883.         {
  884.         XmNrowSizePolicy, XmCRowSizePolicy,
  885.         XmRGridSizePolicy, sizeof(unsigned char),
  886.         XtOffset(XmLGridWidget, grid.rowSizePolicy),
  887.         XmRImmediate, (XtPointer)0,
  888.         },
  889.         {
  890.         XmNrowStep, XmCRowStep,
  891.         XmRInt, sizeof(int),
  892.         XtOffset(XmLGridWidget, grid.rowStep),
  893.         XmRImmediate, (XtPointer)1,
  894.         },
  895.         {
  896.         XmNrowType, XmCRowType,
  897.         XmRRowType, sizeof(unsigned char),
  898.         XtOffset(XmLGridWidget, grid.rowType),
  899.         XmRImmediate, (XtPointer)XmINVALID_TYPE,
  900.         },
  901.         /* Column Resources */
  902.         {
  903.         XmNcolumn, XmCGridColumn,
  904.         XmRInt, sizeof(int),
  905.         XtOffset(XmLGridWidget, grid.cellCol),
  906.         XmRImmediate, (XtPointer)-1,
  907.         },
  908.         {
  909.         XmNcolumnUserData, XmCUserData,
  910.         XmRPointer, sizeof(XtPointer),
  911.         XtOffset(XmLGridWidget, grid.colUserData),
  912.         XmRImmediate, (XtPointer)0,
  913.         },
  914.         {
  915.         XmNcolumnResizable, XmCColumnResizable,
  916.         XmRBoolean, sizeof(Boolean),
  917.         XtOffset(XmLGridWidget, grid.colResizable),
  918.         XmRImmediate, (XtPointer)TRUE,
  919.         },
  920.         {
  921.         XmNcolumnWidth, XmCColumnWidth,
  922.         XmRDimension, sizeof(Dimension),
  923.         XtOffset(XmLGridWidget, grid.colWidth),
  924.         XmRImmediate, (XtPointer)0,
  925.         },
  926.         {
  927.         XmNcolumnRangeEnd, XmCColumnRangeEnd,
  928.         XmRInt, sizeof(int),
  929.         XtOffset(XmLGridWidget, grid.cellColRangeEnd),
  930.         XmRImmediate, (XtPointer)-1,
  931.         },
  932.         {
  933.         XmNcolumnRangeStart, XmCColumnRangeStart,
  934.         XmRInt, sizeof(int),
  935.         XtOffset(XmLGridWidget, grid.cellColRangeStart),
  936.         XmRImmediate, (XtPointer)-1,
  937.         },
  938.         {
  939.         XmNcolumnSizePolicy, XmCColumnSizePolicy,
  940.         XmRGridSizePolicy, sizeof(unsigned char),
  941.         XtOffset(XmLGridWidget, grid.colSizePolicy),
  942.         XmRImmediate, (XtPointer)0,
  943.         },
  944.         {
  945.         XmNcolumnStep, XmCColumnStep,
  946.         XmRInt, sizeof(int),
  947.         XtOffset(XmLGridWidget, grid.colStep),
  948.         XmRImmediate, (XtPointer)1,
  949.         },
  950.         {
  951.         XmNcolumnType, XmCColumnType,
  952.         XmRColumnType, sizeof(unsigned char),
  953.         XtOffset(XmLGridWidget, grid.colType),
  954.         XmRImmediate, (XtPointer)XmINVALID_TYPE,
  955.         },
  956.         /* Cell Resources */
  957.         {
  958.         XmNcellAlignment, XmCCellAlignment,
  959.         XmRCellAlignment, sizeof(unsigned char),
  960.         XtOffset(XmLGridWidget, grid.cellValues.alignment),
  961.         XmRImmediate, (XtPointer)0,
  962.         },
  963.         {
  964.         XmNcellBackground, XmCCellBackground,
  965.         XmRPixel, sizeof(Pixel),
  966.         XtOffset(XmLGridWidget, grid.cellValues.background),
  967.         XmRImmediate, (XtPointer)0,
  968.         },
  969.         {
  970.         XmNcellBottomBorderColor, XmCCellBottomBorderColor,
  971.         XmRPixel, sizeof(Pixel),
  972.         XtOffset(XmLGridWidget, grid.cellValues.bottomBorderColor),
  973.         XmRImmediate, (XtPointer)0,
  974.         },
  975.         {
  976.         XmNcellBottomBorderType, XmCCellBottomBorderType,
  977.         XmRCellBorderType, sizeof(unsigned char),
  978.         XtOffset(XmLGridWidget, grid.cellValues.bottomBorderType),
  979.         XmRImmediate, (XtPointer)0,
  980.         },
  981.         {
  982.         XmNcellColumnSpan, XmCCellColumnSpan,
  983.         XmRInt, sizeof(int),
  984.         XtOffset(XmLGridWidget, grid.cellValues.columnSpan),
  985.         XmRImmediate, (XtPointer)0,
  986.         },
  987.         {
  988.         XmNcellEditable, XmCCellEditable,
  989.         XmRBoolean, sizeof(Boolean),
  990.         XtOffset(XmLGridWidget, grid.cellValues.editable),
  991.         XmRImmediate, (XtPointer)False,
  992.         },
  993.         {
  994.         XmNcellFontList, XmCCellFontList,
  995.         XmRFontList, sizeof(XmFontList),
  996.         XtOffset(XmLGridWidget, grid.cellValues.fontList),
  997.         XmRImmediate, (XtPointer)0,
  998.         },
  999.         {
  1000.         XmNcellForeground, XmCCellForeground,
  1001.         XmRPixel, sizeof(Pixel),
  1002.         XtOffset(XmLGridWidget, grid.cellValues.foreground),
  1003.         XmRImmediate, (XtPointer)0,
  1004.         },
  1005.         {
  1006.         XmNcellLeftBorderColor, XmCCellLeftBorderColor,
  1007.         XmRPixel, sizeof(Pixel),
  1008.         XtOffset(XmLGridWidget, grid.cellValues.leftBorderColor),
  1009.         XmRImmediate, (XtPointer)0,
  1010.         },
  1011.         {
  1012.         XmNcellLeftBorderType, XmCCellLeftBorderType,
  1013.         XmRCellBorderType, sizeof(unsigned char),
  1014.         XtOffset(XmLGridWidget, grid.cellValues.leftBorderType),
  1015.         XmRImmediate, (XtPointer)0,
  1016.         },
  1017.         {
  1018.         XmNcellMarginBottom, XmCCellMarginBottom,
  1019.         XmRDimension, sizeof(Dimension),
  1020.         XtOffset(XmLGridWidget, grid.cellValues.bottomMargin),
  1021.         XmRImmediate, (XtPointer)0,
  1022.         },
  1023.         {
  1024.         XmNcellMarginLeft, XmCCellMarginLeft,
  1025.         XmRDimension, sizeof(Dimension),
  1026.         XtOffset(XmLGridWidget, grid.cellValues.leftMargin),
  1027.         XmRImmediate, (XtPointer)0,
  1028.         },
  1029.         {
  1030.         XmNcellMarginRight, XmCCellMarginRight,
  1031.         XmRDimension, sizeof(Dimension),
  1032.         XtOffset(XmLGridWidget, grid.cellValues.rightMargin),
  1033.         XmRImmediate, (XtPointer)0,
  1034.         },
  1035.         {
  1036.         XmNcellMarginTop, XmCCellMarginTop,
  1037.         XmRDimension, sizeof(Dimension),
  1038.         XtOffset(XmLGridWidget, grid.cellValues.topMargin),
  1039.         XmRImmediate, (XtPointer)0,
  1040.         },
  1041.         {
  1042.         XmNcellPixmap, XmCCellPixmap,
  1043.         XmRManForegroundPixmap, sizeof(Pixmap),
  1044.         XtOffset(XmLGridWidget, grid.cellPixmap),
  1045.         XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
  1046.         },
  1047.         {
  1048.         XmNcellPixmapMask, XmCCellPixmapMask,
  1049.         XtRBitmap, sizeof(Pixmap),
  1050.         XtOffset(XmLGridWidget, grid.cellPixmapMask),
  1051.         XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP,
  1052.         },
  1053.         {
  1054.         XmNcellRightBorderColor, XmCCellRightBorderColor,
  1055.         XmRPixel, sizeof(Pixel),
  1056.         XtOffset(XmLGridWidget, grid.cellValues.rightBorderColor),
  1057.         XmRImmediate, (XtPointer)0,
  1058.         },
  1059.         {
  1060.         XmNcellRightBorderType, XmCCellRightBorderType,
  1061.         XmRCellBorderType, sizeof(unsigned char),
  1062.         XtOffset(XmLGridWidget, grid.cellValues.rightBorderType),
  1063.         XmRImmediate, (XtPointer)0,
  1064.         },
  1065.         {
  1066.         XmNcellRowSpan, XmCCellRowSpan,
  1067.         XmRInt, sizeof(int),
  1068.         XtOffset(XmLGridWidget, grid.cellValues.rowSpan),
  1069.         XmRImmediate, (XtPointer)0,
  1070.         },
  1071.         {
  1072.         XmNcellString, XmCXmString,
  1073.         XmRXmString, sizeof(XmString),
  1074.         XtOffset(XmLGridWidget, grid.cellString),
  1075.         XmRImmediate, (XtPointer)0,
  1076.         },
  1077.         {
  1078.         XmNcellToggleSet, XmCCellToggleSet,
  1079.         XmRBoolean, sizeof(Boolean),
  1080.         XtOffset(XmLGridWidget, grid.cellToggleSet),
  1081.         XmRImmediate, (XtPointer)False,
  1082.         },
  1083.         {
  1084.         XmNcellTopBorderColor, XmCCellTopBorderColor,
  1085.         XmRPixel, sizeof(Pixel),
  1086.         XtOffset(XmLGridWidget, grid.cellValues.topBorderColor),
  1087.         XmRImmediate, (XtPointer)0,
  1088.         },
  1089.         {
  1090.         XmNcellTopBorderType, XmCCellTopBorderType,
  1091.         XmRCellBorderType, sizeof(unsigned char),
  1092.         XtOffset(XmLGridWidget, grid.cellValues.topBorderType),
  1093.         XmRImmediate, (XtPointer)0,
  1094.         },
  1095.         {
  1096.         XmNcellType, XmCCellType,
  1097.         XmRCellType, sizeof(unsigned char),
  1098.         XtOffset(XmLGridWidget, grid.cellValues.type),
  1099.         XmRImmediate, (XtPointer)0,
  1100.         },
  1101.         {
  1102.         XmNcellUserData, XmCUserData,
  1103.         XmRPointer, sizeof(XtPointer),
  1104.         XtOffset(XmLGridWidget, grid.cellValues.userData),
  1105.         XmRImmediate, (XtPointer)0,
  1106.         },
  1107.         /* Overridden inherited resources */
  1108.         {
  1109.         XmNshadowThickness, XmCShadowThickness,
  1110.         XmRHorizontalDimension, sizeof(Dimension),
  1111.         XtOffset(XmLGridWidget, manager.shadow_thickness),
  1112.         XmRImmediate, (XtPointer)2,
  1113.         },
  1114.  
  1115.         {
  1116.         XmNshowHideButton, XmCShowHideButton,
  1117.         XmRBoolean, sizeof(Boolean),
  1118.         XtOffset(XmLGridWidget, grid.showHideButton),
  1119.         XmRImmediate, (XtPointer)False,
  1120.         },
  1121.         {
  1122.         XmNuseTextWidget, XmCUseTextWidget,
  1123.         XmRBoolean, sizeof(Boolean),
  1124.         XtOffset(XmLGridWidget, grid.useTextWidget),
  1125.         XmRImmediate, (XtPointer)True,
  1126.         },
  1127.         {
  1128.           XmNiconSpacing, XmCIconSpacing,
  1129.           XmRHorizontalDimension, sizeof(Dimension),
  1130.           XtOffset(XmLGridWidget, grid.iconSpacing),
  1131.           XmRImmediate, (XtPointer) 4,
  1132.         },
  1133.     };
  1134.  
  1135. XmLGridClassRec xmlGridClassRec =
  1136.     {
  1137.         { /* core_class */
  1138.         (WidgetClass)&xmManagerClassRec,          /* superclass         */
  1139.         "XmLGrid",                                /* class_name         */
  1140.         sizeof(XmLGridRec),                       /* widget_size        */
  1141.         ClassInitialize,                          /* class_init         */
  1142.         ClassPartInitialize,                      /* class_part_init    */
  1143.         FALSE,                                    /* class_inited       */
  1144.         (XtInitProc)Initialize,                   /* initialize         */
  1145.         0,                                        /* initialize_hook    */
  1146.         (XtRealizeProc)Realize,                   /* realize            */
  1147.         (XtActionList)actions,                    /* actions            */
  1148.         (Cardinal)XtNumber(actions),              /* num_actions        */
  1149.         resources,                                /* resources          */
  1150.         XtNumber(resources),                      /* num_resources      */
  1151.         NULLQUARK,                                /* xrm_class          */
  1152.         TRUE,                                     /* compress_motion    */
  1153.         XtExposeCompressMaximal,                  /* compress_exposure  */
  1154.         TRUE,                                     /* compress_enterleav */
  1155.         TRUE,                                     /* visible_interest   */
  1156.         (XtWidgetProc)Destroy,                    /* destroy            */
  1157.         (XtWidgetProc)Resize,                     /* resize             */
  1158.         (XtExposeProc)Redisplay,                  /* expose             */
  1159.         (XtSetValuesFunc)SetValues,               /* set_values         */
  1160.         0,                                        /* set_values_hook    */
  1161.         XtInheritSetValuesAlmost,                 /* set_values_almost  */
  1162.         (XtArgsProc)GetSubValues,                 /* get_values_hook    */
  1163.         0,                                        /* accept_focus       */
  1164.         XtVersion,                                /* version            */
  1165.         0,                                        /* callback_private   */
  1166.         translations,                             /* tm_table           */
  1167.         0,                                        /* query_geometry     */
  1168.         0,                                        /* display_accelerato */
  1169.         0,                                        /* extension          */
  1170.         },
  1171.         { /* composite_class */
  1172.         (XtGeometryHandler)GeometryManager,       /* geometry_manager   */
  1173.         (XtWidgetProc)ChangeManaged,              /* change_managed     */
  1174.         XtInheritInsertChild,                     /* insert_child       */
  1175.         XtInheritDeleteChild,                     /* delete_child       */
  1176.         0,                                        /* extension          */
  1177.         },
  1178.         { /* constraint_class */
  1179.         0,                                        /* subresources       */
  1180.         0,                                        /* subresource_count  */
  1181.         sizeof(XmLGridConstraintRec),             /* constraint_size    */
  1182.         0,                                        /* initialize         */
  1183.         0,                                        /* destroy            */
  1184.         0,                                        /* set_values         */
  1185.         0,                                        /* extension          */
  1186.         },
  1187.         { /* manager_class */
  1188.         XtInheritTranslations,                    /* translations       */
  1189.         0,                                        /* syn resources      */
  1190.         0,                                        /* num syn_resources  */
  1191.         0,                                        /* get_cont_resources */
  1192.         0,                                        /* num_get_cont_res   */
  1193.         XmInheritParentProcess,                   /* parent_process     */
  1194.         0,                                        /* extension          */
  1195.         },
  1196.         { /* grid_class */
  1197.         0,                                        /* initial rows       */
  1198.         0,                                        /* initial columns    */
  1199.         XmInheritGridPreLayout,                   /* pre layout         */
  1200.         sizeof(struct _XmLGridRowRec),            /* row rec size       */
  1201.         _GridRowNew,                              /* row new            */
  1202.         _GridRowFree,                             /* row free           */
  1203.         _GetRowValueMask,                         /* get row value mask */
  1204.         _GetRowValue,                             /* get row value      */
  1205.         _SetRowValues,                            /* set row values     */
  1206.         sizeof(struct _XmLGridColumnRec),         /* column rec size    */
  1207.         _GridColumnNew,                           /* column new         */
  1208.         _GridColumnFree,                          /* column free        */
  1209.         _GetColumnValueMask,                      /* get col value mask */
  1210.         _GetColumnValue,                          /* get column value   */
  1211.         _SetColumnValues,                         /* set column values  */
  1212.         _SetCellValuesResize,                     /* set cell vl resize */
  1213.         _GridCellAction,                          /* cell action        */
  1214.         }
  1215.     };
  1216.  
  1217. WidgetClass xmlGridWidgetClass = (WidgetClass)&xmlGridClassRec;
  1218.  
  1219. /*
  1220.    Create and Destroy
  1221. */
  1222.  
  1223. static void 
  1224. ClassInitialize(void)
  1225.     {
  1226.     int off1, off2;
  1227.  
  1228.     XmLInitialize();
  1229.  
  1230.     XtSetTypeConverter(XmRString, XmRGridSizePolicy,
  1231.         CvtStringToSizePolicy, 0, 0, XtCacheNone, 0);
  1232.     XtSetTypeConverter(XmRString, XmRColumnType,
  1233.         CvtStringToRowColType, 0, 0, XtCacheNone, 0);
  1234.     XtSetTypeConverter(XmRString, XmRRowType,
  1235.         CvtStringToRowColType, 0, 0, XtCacheNone, 0);
  1236.     XtSetTypeConverter(XmRString, XmRGridSelectionPolicy,
  1237.         CvtStringToSelectionPolicy, 0, 0, XtCacheNone, 0);
  1238.     XtSetTypeConverter(XmRString, XmRCellAlignment,
  1239.         CvtStringToCellAlignment, 0, 0, XtCacheNone, 0);
  1240.     XtSetTypeConverter(XmRString, XmRCellType,
  1241.         CvtStringToCellType, 0, 0, XtCacheNone, 0);
  1242.     XtSetTypeConverter(XmRString, XmRCellBorderType,
  1243.         CvtStringToCellBorderType, 0, 0, XtCacheNone, 0);
  1244.     /* long must be > 2 bytes for cell mask to work */
  1245.     if (sizeof(long) < 3)
  1246.         fprintf(stderr, "xmlGridClass: fatal error: long < 3 bytes\n");
  1247.     /* compiler sanity check - make sure array pos lines up */
  1248.     off1 = XtOffset(XmLArrayItem *, pos);
  1249.     off2 = XtOffset(XmLGridColumn, grid.pos);
  1250.     if (off1 != off2)
  1251.         fprintf(stderr, "xmlGridClass: fatal error: column pos offset bad\n");
  1252.     off2 = XtOffset(XmLGridRow, grid.pos);
  1253.     if (off1 != off2)
  1254.         fprintf(stderr, "xmlGridClass: fatal error: row pos offset bad\n");
  1255.     }
  1256.  
  1257. static void 
  1258. ClassPartInitialize(WidgetClass wc)
  1259.     {
  1260.     XmLGridWidgetClass c, sc;
  1261.  
  1262.     c = (XmLGridWidgetClass)wc;
  1263.     sc = (XmLGridWidgetClass)c->core_class.superclass;
  1264.  
  1265. #define INHERIT_PROC(proc, inherit) \
  1266.     if (c->grid_class.proc == inherit) \
  1267.         c->grid_class.proc = sc->grid_class.proc;
  1268.  
  1269.     INHERIT_PROC(rowNewProc, XmInheritGridRowNew)
  1270.     INHERIT_PROC(rowFreeProc, XmInheritGridRowFree)
  1271.     INHERIT_PROC(getRowValueMaskProc, XmInheritGridGetRowValueMask)
  1272.     INHERIT_PROC(getRowValueProc, XmInheritGridGetRowValue)
  1273.     INHERIT_PROC(setRowValuesProc, XmInheritGridSetRowValues)
  1274.  
  1275.     INHERIT_PROC(columnNewProc, XmInheritGridColumnNew)
  1276.     INHERIT_PROC(columnFreeProc, XmInheritGridColumnFree)
  1277.     INHERIT_PROC(getColumnValueMaskProc, XmInheritGridGetColumnValueMask)
  1278.     INHERIT_PROC(getColumnValueProc, XmInheritGridGetColumnValue)
  1279.     INHERIT_PROC(setColumnValuesProc, XmInheritGridSetColumnValues)
  1280.  
  1281.     INHERIT_PROC(setCellValuesResizeProc, XmInheritGridSetCellValuesResize)
  1282.     INHERIT_PROC(cellActionProc, XmInheritGridCellAction)
  1283.  
  1284. #undef INHERIT_PROC
  1285.     }
  1286.  
  1287. static void 
  1288. Initialize(Widget reqW,
  1289.        Widget newW,
  1290.        ArgList args,
  1291.        Cardinal *narg)
  1292.     {
  1293.     XmLGridWidget g, request;
  1294.     Display *dpy;
  1295.     Pixmap pix, pixMask;
  1296.     Pixel white, black;
  1297.     XColor fg, bg;
  1298.     GridReg *reg;
  1299.     int i, valid, hc, c, fc, hr, r, fr;
  1300.     Boolean layoutFrozen;
  1301. #ifdef POINTER_FOCUS_CHECK
  1302.     unsigned char kfp;
  1303.     Widget shell;
  1304. #endif
  1305.  
  1306.     g = (XmLGridWidget)newW;
  1307.     dpy = XtDisplay((Widget)g);
  1308.     request = (XmLGridWidget)reqW;
  1309.  
  1310. #ifdef POINTER_FOCUS_CHECK
  1311.     shell = XmLShellOfWidget(newW);
  1312.     if (shell && XmIsVendorShell(shell)) 
  1313.         {
  1314.         XtVaGetValues(shell,
  1315.             XmNkeyboardFocusPolicy, &kfp,
  1316.             NULL);
  1317.         if (kfp == XmPOINTER)
  1318.             XmLWarning(newW, "keyboardFocusPolicy of XmPOINTER not supported");
  1319.         }
  1320. #endif
  1321.  
  1322.     black = BlackPixelOfScreen(XtScreen((Widget)g));
  1323.     white = WhitePixelOfScreen(XtScreen((Widget)g));
  1324.  
  1325.     g->grid.rowArray = XmLArrayNew(1, 1);
  1326.     g->grid.colArray = XmLArrayNew(1, 1);
  1327.  
  1328.     if (g->core.width <= 0) 
  1329.         g->core.width = 100;
  1330.     if (g->core.height <= 0) 
  1331.         g->core.height = 100;
  1332.  
  1333.     CopyFontList(g);
  1334.  
  1335.     if (g->grid.useTextWidget) {
  1336.       g->grid.text = XtVaCreateManagedWidget("text", xmTextWidgetClass, (Widget)g,
  1337.                          XmNmarginHeight, 0,
  1338.                          XmNmarginWidth, 3,
  1339.                          XmNshadowThickness, 0,
  1340.                          XmNhighlightThickness, 0,
  1341.                          XmNx, 0,
  1342.                          XmNy, 0,
  1343.                          XmNwidth, 40,
  1344.                          XmNheight, 40,
  1345.                          XmNbackground, g->core.background_pixel,
  1346.                          XmNforeground, g->manager.foreground,
  1347.                          NULL);
  1348.       XtOverrideTranslations(g->grid.text, g->grid.traverseTrans);
  1349.       XtAddEventHandler(g->grid.text, StructureNotifyMask,
  1350.                 True, (XtEventHandler)TextMapped, (XtPointer)0);
  1351.       XtAddCallback(g->grid.text, XmNactivateCallback, TextActivate, 0);
  1352.       XtAddCallback(g->grid.text, XmNfocusCallback, TextFocus, 0);
  1353.       XtAddCallback(g->grid.text, XmNlosingFocusCallback, TextFocus, 0);
  1354.       XtAddCallback(g->grid.text, XmNmodifyVerifyCallback, TextModifyVerify, 0);
  1355.     }
  1356.  
  1357.     g->grid.hsb = XtVaCreateWidget(
  1358.         "hsb", xmScrollBarWidgetClass, (Widget)g,
  1359.         XmNincrement, 1,
  1360.         XmNorientation, XmHORIZONTAL,
  1361.         XmNtraversalOn, False,
  1362.         XmNbackground, g->core.background_pixel,
  1363. /* Don't force foreground on IRIX - it screws up the thumb color in sgiMode */
  1364. #ifndef IRIX
  1365.         XmNforeground, g->manager.foreground,
  1366. #endif
  1367.         XmNtopShadowColor, g->manager.top_shadow_color,
  1368.         XmNbottomShadowColor, g->manager.bottom_shadow_color,
  1369.         NULL);
  1370.     XtAddCallback(g->grid.hsb, XmNdragCallback, ScrollCB, 0);
  1371.     XtAddCallback(g->grid.hsb, XmNvalueChangedCallback, ScrollCB, 0);
  1372.     g->grid.vsb = XtVaCreateWidget(
  1373.         "vsb", xmScrollBarWidgetClass, (Widget)g,
  1374.         XmNorientation, XmVERTICAL,
  1375.         XmNincrement, 1,
  1376.         XmNtraversalOn, False,
  1377.         XmNbackground, g->core.background_pixel,
  1378. /* Don't force foreground on IRIX - it screws up the thumb color in sgiMode */
  1379. #ifndef IRIX
  1380.         XmNforeground, g->manager.foreground,
  1381. #endif
  1382.         XmNtopShadowColor, g->manager.top_shadow_color,
  1383.         XmNbottomShadowColor, g->manager.bottom_shadow_color,
  1384.         NULL);
  1385.     XtAddCallback(g->grid.vsb, XmNdragCallback, ScrollCB, 0);
  1386.     XtAddCallback(g->grid.vsb, XmNvalueChangedCallback, ScrollCB, 0);
  1387.  
  1388.     if (g->grid.showHideButton)
  1389.         {
  1390.         g->grid.hideButton = XtVaCreateWidget(
  1391.             "hide", xmDrawnButtonWidgetClass,
  1392.                (Widget)g, XmNhighlightThickness, 0,
  1393.             XmNshadowThickness, 1,
  1394.                XmNtraversalOn, False,
  1395.               XmNbackground, g->core.background_pixel,
  1396.             XmNforeground, g->manager.foreground,
  1397.             XmNtopShadowColor, g->manager.top_shadow_color,
  1398.             XmNbottomShadowColor, g->manager.bottom_shadow_color,
  1399.             NULL);
  1400.  
  1401.         XmLDrawnButtonSetType(g->grid.hideButton,
  1402.                       XmDRAWNB_DOUBLEARROW,
  1403.                       XmDRAWNB_RIGHT);
  1404.         }
  1405.     else 
  1406.         {
  1407.         g->grid.hideButton = 0;
  1408.         }
  1409.  
  1410.     g->grid.realColCount = -1;
  1411.  
  1412.     g->grid.inResize = False;
  1413.  
  1414.     /* Cursors */
  1415.     fg.red = ~0;
  1416.     fg.green = ~0;
  1417.     fg.blue = ~0;
  1418.     fg.pixel = white;
  1419.     fg.flags = DoRed | DoGreen | DoBlue;
  1420.     bg.red = 0;
  1421.     bg.green = 0;
  1422.     bg.blue = 0;
  1423.     bg.pixel = black;
  1424.     bg.flags = DoRed | DoGreen | DoBlue;
  1425.     pix = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy),
  1426.         (char *)horizp_bits, horizp_width, horizp_height, 0, 1, 1);
  1427.     pixMask = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy),
  1428.         (char *)horizm_bits, horizm_width, horizm_height, 1, 0, 1);
  1429.     g->grid.hResizeCursor = XCreatePixmapCursor(dpy, pix, pixMask,
  1430.         &fg, &bg, 9, 9);
  1431.     XFreePixmap(dpy, pix);
  1432.     XFreePixmap(dpy, pixMask);
  1433.     pix = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy),
  1434.         (char *)vertp_bits, vertp_width, vertp_height, 0, 1, 1);
  1435.     pixMask = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy),
  1436.         (char *)vertm_bits, vertm_width, vertm_height, 1, 0, 1);
  1437.     g->grid.vResizeCursor = XCreatePixmapCursor(dpy, pix, pixMask,
  1438.         &fg, &bg, 9, 9);
  1439.     XFreePixmap(dpy, pix);
  1440.     XFreePixmap(dpy, pixMask);
  1441.  
  1442.     g->grid.cursorDefined = CursorNormal;
  1443.     g->grid.focusIn = 0;
  1444.     g->grid.focusRow = -1;
  1445.     g->grid.focusCol = -1;
  1446.     g->grid.mayHaveRowSpans = 0;
  1447.     g->grid.scrollCol = 0;
  1448.     g->grid.scrollRow = 0;
  1449.     g->grid.textHidden = 1;
  1450.     g->grid.inMode = InNormal;
  1451.     g->grid.inEdit = 0;
  1452.     g->grid.singleColScrollMode = 0;
  1453.     g->grid.layoutStack = 0;
  1454.     g->grid.needsHorizLayout = 0;
  1455.     g->grid.needsVertLayout = 0;
  1456.     g->grid.recalcHorizVisPos = 0;
  1457.     g->grid.recalcVertVisPos = 0;
  1458.     g->grid.vertVisChangedHint = 0;
  1459.     g->grid.defCellValues = CellRefValuesCreate(g, 0);
  1460.     g->grid.defCellValues->refCount = 1;
  1461.     g->grid.ignoreModifyVerify = 0;
  1462.     g->grid.extendRow = -1;
  1463.     g->grid.extendCol = -1;
  1464.     g->grid.extendToRow = -1;
  1465.     g->grid.extendToCol = -1;
  1466.     g->grid.extendSelect = True;
  1467.     g->grid.lastSelectRow = -1;
  1468.     g->grid.lastSelectCol = -1;
  1469.     g->grid.lastSelectTime = 0;
  1470.     g->grid.dragTimerSet = 0;
  1471.     g->grid.gc = 0;
  1472.     reg = g->grid.reg;
  1473.     for (i = 0; i < 9; i++)
  1474.             {
  1475.             reg[i].x = 0;
  1476.             reg[i].y = 0;
  1477.             reg[i].width = 0;
  1478.             reg[i].height = 0;
  1479.             reg[i].row = 0;
  1480.             reg[i].col = 0;
  1481.             reg[i].nrow = 0;
  1482.             reg[i].ncol = 0;
  1483.             }
  1484.  
  1485.     layoutFrozen = g->grid.layoutFrozen;
  1486.     g->grid.layoutFrozen = True;
  1487.  
  1488.     if (g->grid.hiddenColCount || g->grid.hiddenRowCount)
  1489.         {
  1490.         XmLWarning(newW, "Initialize() - can't set hidden rows or columns");
  1491.         g->grid.hiddenColCount = 0;
  1492.         g->grid.hiddenRowCount = 0;
  1493.         }
  1494.     hc = g->grid.headingColCount;
  1495.     c = XmLGridClassPartOfWidget(g).initialCols;
  1496.     if (c < g->grid.colCount)
  1497.         c = g->grid.colCount;
  1498.     fc = g->grid.footerColCount;
  1499.     hr = g->grid.headingRowCount;
  1500.     r = XmLGridClassPartOfWidget(g).initialRows;
  1501.     if (r < g->grid.rowCount)
  1502.         r = g->grid.rowCount ;
  1503.     fr = g->grid.footerRowCount;
  1504.     g->grid.headingColCount = 0;
  1505.     g->grid.colCount = 0;
  1506.     g->grid.footerColCount = 0;
  1507.     g->grid.headingRowCount = 0;
  1508.     g->grid.rowCount = 0;
  1509.     g->grid.footerRowCount = 0;
  1510.     XmLGridAddColumns(newW, XmHEADING, -1, hc);
  1511.     XmLGridAddColumns(newW, XmCONTENT, -1, c);
  1512.     XmLGridAddColumns(newW, XmFOOTER, -1, fc);
  1513.     XmLGridAddRows(newW, XmHEADING, -1, hr);
  1514.     XmLGridAddRows(newW, XmCONTENT, -1, r);
  1515.     XmLGridAddRows(newW, XmFOOTER, -1, fr);
  1516.     if (g->grid.simpleHeadings)
  1517.         {
  1518.         g->grid.simpleHeadings = (char *)strdup(g->grid.simpleHeadings);
  1519.         SetSimpleHeadings(g, g->grid.simpleHeadings);
  1520.         }
  1521.     if (g->grid.simpleWidths)
  1522.         {
  1523.         g->grid.simpleWidths = (char *)strdup(g->grid.simpleWidths);
  1524.         SetSimpleWidths(g, g->grid.simpleWidths);
  1525.         }
  1526.     if (g->grid.visibleRows)
  1527.         ApplyVisibleRows(g);
  1528.     if (g->grid.visibleCols)
  1529.         ApplyVisibleCols(g);
  1530.  
  1531.     g->grid.layoutFrozen = layoutFrozen;
  1532.     VertLayout(g, 1);
  1533.     HorizLayout(g, 1);
  1534.     PlaceScrollbars(g);
  1535.  
  1536.     valid = 1;
  1537.     for (i = 0; i < *narg; i++)
  1538.         {
  1539.         if (!args[i].name)
  1540.             continue;
  1541.         if (!strcmp(args[i].name, XmNrows) ||
  1542.             !strcmp(args[i].name, XmNcolumns))
  1543.             continue;
  1544.         if (!strncmp(args[i].name, "row", 3) ||
  1545.             !strncmp(args[i].name, "column", 6) ||
  1546.             !strncmp(args[i].name, "cell", 4))
  1547.             valid = 0;
  1548.         }
  1549.     if (!valid)
  1550.         XmLWarning(newW,
  1551.             "Initialize() - can't set row,column or cell values in init");
  1552.  
  1553.     DropRegister(g, g->grid.allowDrop);
  1554.     }
  1555.  
  1556. static void
  1557. Destroy(Widget w)
  1558.     {
  1559.     XmLGridWidget g;
  1560.     Display *dpy;
  1561.     int i, count;
  1562.  
  1563.     g = (XmLGridWidget)w;
  1564.     dpy = XtDisplay(w);
  1565.     if (g->grid.dragTimerSet)
  1566.         XtRemoveTimeOut(g->grid.dragTimerId);
  1567.     DefineCursor(g, CursorNormal);
  1568.     XFreeCursor(dpy, g->grid.hResizeCursor);
  1569.     XFreeCursor(dpy, g->grid.vResizeCursor);
  1570.     if (g->grid.gc)
  1571.         {
  1572.         XFreeGC(dpy, g->grid.gc);
  1573.         XFreeFont(dpy, g->grid.fallbackFont);
  1574.         }
  1575.     XmFontListFree(g->grid.fontList);
  1576.     XmLGridCellDerefValues(g->grid.defCellValues);
  1577.     ExtendSelect(g, (XEvent *)0, False, -1, -1);
  1578.     count = XmLArrayGetCount(g->grid.rowArray);
  1579.     for (i = 0; i < count; i++)
  1580.         XmLGridRowFree(w, (XmLGridRow)XmLArrayGet(g->grid.rowArray, i));
  1581.     XmLArrayFree(g->grid.rowArray);
  1582.     count = XmLArrayGetCount(g->grid.colArray);
  1583.     for (i = 0; i < count; i++)
  1584.         XmLGridColumnFree(w, (XmLGridColumn)XmLArrayGet(g->grid.colArray, i));
  1585.     XmLArrayFree(g->grid.colArray);
  1586.     if (g->grid.simpleHeadings)
  1587.         free((char *)g->grid.simpleHeadings);
  1588.     if (g->grid.simpleWidths)
  1589.         free((char *)g->grid.simpleWidths);
  1590.     }
  1591.  
  1592. /*
  1593.    Geometry, Drawing, Entry and Picking
  1594. */
  1595.  
  1596. static void 
  1597. Realize(Widget w,
  1598.     XtValueMask *valueMask,
  1599.     XSetWindowAttributes *attr)
  1600.     {
  1601.     XmLGridWidget g;
  1602.     Display *dpy;
  1603.     WidgetClass superClass;
  1604.     XtRealizeProc realize;
  1605.     XGCValues values;
  1606.     XtGCMask mask;
  1607.     static char dashes[2] = { 1, 1 };
  1608.  
  1609.     g = (XmLGridWidget)w;
  1610.     dpy = XtDisplay(g);
  1611.     superClass = xmlGridWidgetClass->core_class.superclass;
  1612.     realize = superClass->core_class.realize;
  1613.     (*realize)(w, valueMask, attr);
  1614.  
  1615.     if (!g->grid.gc)
  1616.         {
  1617.         g->grid.fallbackFont = XLoadQueryFont(dpy, "fixed");
  1618.         values.foreground = g->manager.foreground;
  1619.         values.font = g->grid.fallbackFont->fid;
  1620.         mask = GCForeground | GCFont;
  1621.         g->grid.gc = XCreateGC(dpy, XtWindow(g), mask, &values);
  1622.         XSetDashes(dpy, g->grid.gc, 0, dashes, 2);
  1623.         if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW &&
  1624.             g->grid.autoSelect == True &&
  1625.             g->grid.rowCount)
  1626.             XmLGridSelectRow(w, 0, False);
  1627.         }
  1628.     }
  1629.  
  1630. static void
  1631. Redisplay(Widget w,
  1632.       XExposeEvent *event,
  1633.       Region region)
  1634.     {
  1635.     XmLGridWidget g;
  1636.     Display *dpy;
  1637.     Window win;
  1638.     XmLGridCell cell;
  1639.     XmLGridRow row;
  1640.     XmLGridColumn col;
  1641.     XmLGridCellRefValues *cellValues;
  1642.     XmLGridDrawStruct ds;
  1643.     XmLGridCallbackStruct cbs;
  1644.     GridReg *reg;
  1645.     XRectangle eRect, rRect, clipRect, rect[6];
  1646.     int i, n, st, c, r, sc, sr, width, height, rowHeight;
  1647.     int lastVisPos, visPos, hasDrawCB;
  1648.     Boolean spanUp, spanLeft;
  1649.  
  1650.     g = (XmLGridWidget)w;
  1651.     if (!XtIsRealized((Widget)g))
  1652.         return;
  1653.     if (!g->core.visible)
  1654.         return;
  1655.     if (g->grid.layoutFrozen == True)
  1656.         XmLWarning(w, "Redisplay() - layout frozen is True during redraw");
  1657.     dpy = XtDisplay(g);
  1658.     win = XtWindow(g);
  1659.     st = g->manager.shadow_thickness;
  1660.     reg = g->grid.reg;
  1661.     if (event)
  1662.         {
  1663.         eRect.x = event->x;
  1664.         eRect.y = event->y;
  1665.         eRect.width = event->width;
  1666.         eRect.height = event->height;
  1667.         if (g->grid.debugLevel > 1)
  1668.             fprintf(stderr, "XmLGrid: Redisplay x %d y %d w %d h %d\n",
  1669.                 event->x, event->y, event->width, event->height);
  1670.         }
  1671.     else
  1672.         {
  1673.         eRect.x = 0;
  1674.         eRect.y = 0;
  1675.         eRect.width = g->core.width;
  1676.         eRect.height = g->core.height;
  1677.         }
  1678.     if (!eRect.width || !eRect.height)
  1679.         return;
  1680.     /* Hide any XORed graphics */
  1681.     DrawResizeLine(g, 0, 1);
  1682.     hasDrawCB = 0;
  1683.     if (XtHasCallbacks(w, XmNcellDrawCallback) == XtCallbackHasSome)
  1684.             hasDrawCB = 1;
  1685.     for (i = 0; i < 9; i++)
  1686.         {
  1687.         if (g->grid.debugLevel > 1)
  1688.             fprintf(stderr, "XmLGrid: Redisplay region %d phase 0\n", i);
  1689.         if (!reg[i].width || !reg[i].height)
  1690.             continue;
  1691.         rRect.x = reg[i].x;
  1692.         rRect.y = reg[i].y;
  1693.         rRect.width = reg[i].width;
  1694.         rRect.height = reg[i].height;
  1695.         if (XmLRectIntersect(&eRect, &rRect) == XmLRectOutside)
  1696.             continue;
  1697.         if (g->grid.debugLevel > 1)
  1698.             fprintf(stderr, "XmLGrid: Redisplay region %d phase 1\n", i);
  1699.         rRect.x += st;
  1700.         rRect.width -= st * 2;
  1701.         rRect.y += st;
  1702.         rRect.height -= st * 2;
  1703.         if (XmLRectIntersect(&eRect, &rRect) != XmLRectInside &&
  1704.             g->manager.shadow_thickness)
  1705.             {
  1706.             if (g->grid.shadowRegions & (1 << i))
  1707. #ifdef MOTIF11
  1708.                 _XmDrawShadow(dpy, win,
  1709.                     g->manager.bottom_shadow_GC,
  1710.                     g->manager.top_shadow_GC,
  1711.                     g->manager.shadow_thickness,
  1712.                     reg[i].x, reg[i].y,
  1713.                     reg[i].width, reg[i].height);
  1714. #else
  1715.                 _XmDrawShadows(dpy, win,
  1716.                     g->manager.top_shadow_GC,
  1717.                     g->manager.bottom_shadow_GC,
  1718.                     reg[i].x, reg[i].y,
  1719.                     reg[i].width, reg[i].height,
  1720.                     g->manager.shadow_thickness,
  1721.                     g->grid.shadowType);
  1722. #endif
  1723.             else
  1724. #ifdef MOTIF11
  1725.                 _XmEraseShadow(dpy, win,
  1726.                     g->manager.shadow_thickness,
  1727.                     reg[i].x, reg[i].y,
  1728.                     reg[i].width, reg[i].height);
  1729. #else
  1730.                 _XmClearBorder(dpy, win,
  1731.                     reg[i].x, reg[i].y,
  1732.                     reg[i].width, reg[i].height,
  1733.                     g->manager.shadow_thickness);
  1734. #endif
  1735.             }
  1736.         rRect.x += st;
  1737.         height = 0;
  1738.         if (g->grid.debugLevel > 1)
  1739.             fprintf(stderr, "XmLGrid: Redisplay region %d phase 2\n", i);
  1740.         for (r = reg[i].row; r < reg[i].row + reg[i].nrow; r++)
  1741.             {
  1742.             rowHeight = GetRowHeight(g, r);
  1743.             if (!rowHeight && !g->grid.mayHaveRowSpans)
  1744.                 continue;
  1745.             width = 0;
  1746.             for (c = reg[i].col; c < reg[i].col + reg[i].ncol; c++)
  1747.                 {
  1748.                 rRect.x = reg[i].x + st + width;
  1749.                 rRect.y = reg[i].y + st + height;
  1750.                 if (g->grid.singleColScrollMode)
  1751.                     rRect.x -= g->grid.singleColScrollPos;
  1752.                 rRect.width = GetColWidth(g, c);
  1753.                 rRect.height = rowHeight;
  1754.                 width += rRect.width;
  1755.                 cell = GetCell(g, r, c);
  1756.                 if (!cell)
  1757.                     continue;
  1758.                 cellValues = XmLGridCellGetRefValues(cell);
  1759.  
  1760.                 spanUp = False;
  1761.                 spanLeft = False;
  1762.                 if (XmLGridCellInRowSpan(cell))
  1763.                     {
  1764.                     if (r == reg[i].row)
  1765.                         {
  1766.                         spanUp = True;
  1767.                         if (c == reg[i].col)
  1768.                             spanLeft = True;
  1769.                         }
  1770.                     else
  1771.                         continue;
  1772.                     }
  1773.                 if (XmLGridCellInColumnSpan(cell))
  1774.                     {
  1775.                     if (c == reg[i].col)
  1776.                         spanLeft = True;
  1777.                     else
  1778.                         continue;
  1779.                     }
  1780.                 sr = r;
  1781.                 sc = c;
  1782.                 if (spanUp == True || spanLeft == True ||
  1783.                     cellValues->rowSpan || cellValues->columnSpan)
  1784.                     {
  1785.                     if (RowColFirstSpan(g, r, c, &sr, &sc, &rRect,
  1786.                         spanLeft, spanUp) == -1)
  1787.                         continue;
  1788.                     RowColSpanRect(g, sr, sc, &rRect);
  1789.                     }
  1790.                 if (!rRect.width || !rRect.height)
  1791.                     continue;
  1792.                 clipRect = rRect;
  1793.                 ClipRectToReg(g, &clipRect, ®[i]);
  1794.                 if (!clipRect.width || !clipRect.height)
  1795.                     continue;
  1796.                 if (event && XRectInRegion(region, clipRect.x, clipRect.y,
  1797.                         clipRect.width, clipRect.height) == RectangleOut)
  1798.                     continue;
  1799.                 cell = GetCell(g, sr, sc);
  1800.                 if (!cell)
  1801.                     continue;
  1802.                 cellValues = XmLGridCellGetRefValues(cell);
  1803.                 cbs.reason = XmCR_CELL_DRAW;
  1804.                 cbs.event = (XEvent *)event;
  1805.                 cbs.rowType = RowPosToType(g, sr);
  1806.                 cbs.row = RowPosToTypePos(g, cbs.rowType, sr);
  1807.                 cbs.columnType = ColPosToType(g, sc);
  1808.                 cbs.column = ColPosToTypePos(g, cbs.columnType, sc);
  1809.                 cbs.clipRect = &clipRect;
  1810.                 cbs.drawInfo = &ds;
  1811.                 ds.gc = g->grid.gc;
  1812.                 ds.cellRect = &rRect;
  1813.                 ds.topMargin = cellValues->topMargin;
  1814.                 ds.bottomMargin = cellValues->bottomMargin;
  1815.                 ds.leftMargin = cellValues->leftMargin;
  1816.                 ds.rightMargin = cellValues->rightMargin;
  1817.                 ds.background = cellValues->background;
  1818.                 ds.foreground = cellValues->foreground;
  1819.                 ds.fontList = cellValues->fontList;
  1820.                 ds.alignment = cellValues->alignment;
  1821.                 ds.selectBackground = g->grid.selectBg;
  1822.                 ds.selectForeground = g->grid.selectFg;
  1823.                 row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, sr);
  1824.                 col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, sc);
  1825.                 ds.drawFocusType = XmDRAW_FOCUS_NONE;
  1826.                 if (g->grid.focusRow == sr &&
  1827.                     g->grid.highlightRowMode == True &&
  1828.                     g->grid.focusIn)
  1829.                     {
  1830.                     RecalcVisPos(g, 0);
  1831.                     visPos = XmLGridColumnGetVisPos(col);
  1832.                     lastVisPos = XmLArrayGetCount(g->grid.colArray) -
  1833.                         g->grid.hiddenColCount - 1;
  1834.                     if (visPos == 0 && visPos == lastVisPos)
  1835.                         ds.drawFocusType = XmDRAW_FOCUS_CELL;
  1836.                     else if (visPos == 0)
  1837.                         ds.drawFocusType = XmDRAW_FOCUS_LEFT;
  1838.                     else if (visPos == lastVisPos)
  1839.                         ds.drawFocusType = XmDRAW_FOCUS_RIGHT;
  1840.                     else
  1841.                         ds.drawFocusType = XmDRAW_FOCUS_MID;
  1842.                     }
  1843.                 if (g->grid.focusRow == sr &&
  1844.                     g->grid.focusCol == sc &&
  1845.                     g->grid.highlightRowMode == False &&
  1846.                     g->grid.focusIn)
  1847.                     ds.drawFocusType = XmDRAW_FOCUS_CELL;
  1848.                 if (XmLGridRowIsSelected(row) == True ||
  1849.                     XmLGridColumnIsSelected(col) == True ||
  1850.                     XmLGridCellIsSelected(cell) == True)
  1851.                     ds.drawSelected = True;
  1852.                 else
  1853.                     ds.drawSelected = False;
  1854.                 if (g->grid.selectionPolicy == XmSELECT_CELL &&
  1855.                     g->grid.focusIn && g->grid.focusRow == sr &&
  1856.                     g->grid.focusCol == sc)
  1857.                     ds.drawSelected = False;
  1858.                 ds.stringDirection = g->manager.string_direction;
  1859.                 XmLGridCellAction(cell, (Widget)g, &cbs);
  1860.                 if (hasDrawCB)
  1861.                     XtCallCallbackList(w, g->grid.cellDrawCallback,
  1862.                         (XtPointer)&cbs);
  1863.                 }
  1864.             height += rowHeight;
  1865.             }
  1866.         }
  1867.     if (g->grid.debugLevel > 1)
  1868.         fprintf(stderr, "XmLGrid: Redisplay non-cell areas\n");
  1869.     n = 0;
  1870.     if (reg[0].width && g->grid.leftFixedMargin)
  1871.         {
  1872.         rect[n].x = reg[0].width;
  1873.         rect[n].y = 0;
  1874.         rect[n].width = g->grid.leftFixedMargin;
  1875.         rect[n].height = g->core.height;
  1876.         n++;
  1877.         }
  1878.     if (reg[2].width && g->grid.rightFixedMargin)
  1879.         {
  1880.         width = 0;
  1881.         if (reg[0].ncol)
  1882.             width += reg[0].width + g->grid.leftFixedMargin;
  1883.         if (reg[1].ncol)
  1884.             width += reg[1].width;
  1885.         rect[n].x = width;
  1886.         rect[n].y = 0;
  1887.         rect[n].width = g->grid.rightFixedMargin;
  1888.         rect[n].height = g->core.height;
  1889.         n++;
  1890.         }
  1891.     if (reg[0].height && g->grid.topFixedMargin)
  1892.         {
  1893.         rect[n].x = 0;
  1894.         rect[n].y = reg[0].height;
  1895.         rect[n].width = g->core.width;
  1896.         rect[n].height = g->grid.topFixedMargin;
  1897.         n++;
  1898.         }
  1899.     if (reg[6].height && g->grid.bottomFixedMargin)
  1900.         {
  1901.         rect[n].x = 0;
  1902.         height = 0;
  1903.         if (reg[0].nrow)
  1904.             height += reg[0].height + g->grid.topFixedMargin;
  1905.         if (reg[3].nrow)
  1906.             height += reg[3].height;
  1907.         rect[n].y = height;
  1908.         rect[n].width = g->core.width;
  1909.         rect[n].height = g->grid.bottomFixedMargin;
  1910.         n++;
  1911.         }
  1912.     width = reg[1].width;
  1913.     if (reg[0].ncol)
  1914.         width += reg[0].width + g->grid.leftFixedMargin;
  1915.     if (reg[2].ncol)
  1916.         width += g->grid.rightFixedMargin + reg[2].width;
  1917.     if (width < (int)g->core.width)
  1918.         {
  1919.         rect[n].x = width;
  1920.         rect[n].y = 0;
  1921.         rect[n].width = g->core.width - width;
  1922.         rect[n].height = g->core.height;
  1923.         n++;
  1924.         }
  1925.     height = reg[3].height;
  1926.     if (reg[0].nrow)
  1927.         height += reg[0].height + g->grid.topFixedMargin;
  1928.     if (reg[6].nrow)
  1929.         height += g->grid.bottomFixedMargin + reg[6].height;
  1930.     if (height < (int)g->core.height)
  1931.         {
  1932.         rect[n].x = 0;
  1933.         rect[n].y = height;
  1934.         rect[n].width = g->core.width;
  1935.         rect[n].height = g->core.height - height;
  1936.         n++;
  1937.         }
  1938.     for (i = 0; i < n; i++)
  1939.         {
  1940.         if (XmLRectIntersect(&eRect, &rect[i]) == XmLRectOutside)
  1941.             continue;
  1942.         XClearArea(dpy, win, rect[i].x, rect[i].y, rect[i].width,
  1943.             rect[i].height, False);
  1944.         }
  1945.     n = 0;
  1946.     if (reg[1].width)
  1947.         {
  1948.         width = 0;
  1949.         for (c = reg[1].col; c < reg[1].col + reg[1].ncol; c++)
  1950.             width += GetColWidth(g, c);
  1951.         for (i = 1; i < 9; i += 3)
  1952.             if (reg[i].height && width < reg[i].width - st * 2)
  1953.                 {
  1954.                 rect[n].x = reg[i].x + st + width;
  1955.                 rect[n].y = reg[i].y + st;
  1956.                 rect[n].width = reg[i].x + reg[i].width -
  1957.                     rect[n].x - st;
  1958.                 rect[n].height = reg[i].height - st * 2;
  1959.                 n++;
  1960.                 }
  1961.         }
  1962.     if (reg[3].height)
  1963.         {
  1964.         height = 0;
  1965.         for (r = reg[3].row; r < reg[3].row + reg[3].nrow; r++)
  1966.             height += GetRowHeight(g, r);
  1967.         for (i = 3; i < 6; i++)
  1968.             if (reg[i].width && height < reg[i].height - st * 2)
  1969.                 {
  1970.                 rect[n].x = reg[i].x + st;
  1971.                 rect[n].y = reg[i].y + st + height;
  1972.                 rect[n].width = reg[i].width - st * 2;
  1973.                 rect[n].height = reg[i].y + reg[i].height -
  1974.                     rect[n].y - st;
  1975.                 n++;
  1976.                 }
  1977.         }
  1978.     XSetForeground(dpy, g->grid.gc, g->grid.blankBg);
  1979.     for (i = 0; i < n; i++)
  1980.         {
  1981.         if (XmLRectIntersect(&eRect, &rect[i]) == XmLRectOutside)
  1982.             continue;
  1983.         XFillRectangle(dpy, win, g->grid.gc, rect[i].x, rect[i].y,
  1984.             rect[i].width, rect[i].height);
  1985.         }
  1986.     /* Show any XORed graphics */
  1987.     DrawResizeLine(g, 0, 1);
  1988.     }
  1989.  
  1990. static void
  1991. DrawResizeLine(XmLGridWidget g,
  1992.            int xy,
  1993.            int erase)
  1994.     {
  1995.     if (g->grid.inMode != InResize)
  1996.         return;
  1997.     DrawXORRect(g, xy, 2, g->grid.resizeIsVert, erase);
  1998.     }
  1999.  
  2000. static void
  2001. DrawXORRect(XmLGridWidget g,
  2002.         int xy,
  2003.         int size,
  2004.         int isVert,
  2005.         int erase)
  2006.     {
  2007.     Display *dpy;
  2008.     Window win;
  2009.     GC gc;
  2010.     Pixel black, white;
  2011.     int oldXY, maxX, maxY;
  2012.  
  2013.     if (!XtIsRealized((Widget)g))
  2014.         return;
  2015.     /* erase is (0 == none) (1 == hide/show) (2 == permenent erase) */
  2016.     dpy = XtDisplay(g);
  2017.     win = XtWindow(g);
  2018.     gc = g->grid.gc;
  2019.     XSetFunction(dpy, gc, GXinvert);
  2020.     black = BlackPixelOfScreen(XtScreen((Widget)g));
  2021.     white = WhitePixelOfScreen(XtScreen((Widget)g));
  2022.     XSetForeground(dpy, gc, black ^ white);
  2023.     maxX = g->core.width;
  2024.     if (XtIsManaged(g->grid.vsb))
  2025.         maxX -= g->grid.vsb->core.width + g->grid.scrollBarMargin;
  2026.     maxY = g->core.height;
  2027.     if (XtIsManaged(g->grid.hsb))
  2028.         maxY -= g->grid.hsb->core.height + g->grid.scrollBarMargin;
  2029.     oldXY = g->grid.resizeLineXY;
  2030.     if (isVert)
  2031.         {
  2032.         if (oldXY != -1)
  2033.             XFillRectangle(dpy, win, gc, 0, oldXY, maxX, size);
  2034.         }
  2035.     else
  2036.         {
  2037.         if (oldXY != -1)
  2038.             XFillRectangle(dpy, win, gc, oldXY, 0, size, maxY);
  2039.         }
  2040.     if (!erase)
  2041.         {
  2042.         if (isVert)
  2043.             {
  2044.             if (xy > maxY)
  2045.                 xy = maxY - 2;
  2046.             if (xy < 0)
  2047.                 xy = 0;
  2048.             XFillRectangle(dpy, win, gc, 0, xy, maxX, size);
  2049.             }
  2050.         else
  2051.             {
  2052.             if (xy > maxX)
  2053.                 xy = maxX - 2;
  2054.             if (xy < 0)
  2055.                 xy = 0;
  2056.             XFillRectangle(dpy, win, gc, xy, 0, size, maxY);
  2057.             }
  2058.         g->grid.resizeLineXY = xy;
  2059.         }
  2060.     else if (erase == 2)
  2061.         g->grid.resizeLineXY = -1;
  2062.     XSetFunction(dpy, gc, GXcopy);
  2063.     }
  2064.  
  2065. static void 
  2066. DefineCursor(XmLGridWidget g,
  2067.          char defineCursor)
  2068.     {
  2069.     Display *dpy;
  2070.     Window win;
  2071.  
  2072.     if (!XtIsRealized((Widget)g))
  2073.         return;
  2074.     dpy = XtDisplay(g);
  2075.     win = XtWindow(g);
  2076.     if (defineCursor != g->grid.cursorDefined)
  2077.         XUndefineCursor(dpy, win);
  2078.     if (defineCursor == CursorVResize)
  2079.         XDefineCursor(dpy, win, g->grid.vResizeCursor);
  2080.     else if (defineCursor == CursorHResize)
  2081.         XDefineCursor(dpy, win, g->grid.hResizeCursor);
  2082.     g->grid.cursorDefined = defineCursor;
  2083.     }
  2084.  
  2085. static void
  2086. DrawArea(XmLGridWidget g,
  2087.      int type,
  2088.      int row,
  2089.      int col)
  2090.     {
  2091.     GridReg *reg;
  2092.     Display *dpy;
  2093.     Window win;
  2094.     XExposeEvent event;
  2095.     XRectangle rect[3];
  2096.     Region region;
  2097.     int i, j, n;
  2098.     Dimension width, height, st;
  2099.  
  2100.     if (g->grid.layoutFrozen == True)
  2101.         return;
  2102.     if (!XtIsRealized((Widget)g))
  2103.         return;
  2104.     if (!g->core.visible)
  2105.         return;
  2106.     dpy = XtDisplay(g);
  2107.     win = XtWindow(g);
  2108.     reg = g->grid.reg;
  2109.     st = g->manager.shadow_thickness;
  2110.     if (g->grid.debugLevel > 1)
  2111.         fprintf(stderr, "XmLGrid: DrawArea %d %d %d\n", type, row, col);
  2112.  
  2113.     n = 0;
  2114.     switch (type)
  2115.     {
  2116.     case DrawAll:
  2117.         {
  2118.         rect[n].x = 0;
  2119.         rect[n].y = 0;
  2120.         rect[n].width = g->core.width;
  2121.         rect[n].height = g->core.height;
  2122.         n++;
  2123.         break;
  2124.         }
  2125.     case DrawHScroll:
  2126.         {
  2127.         for (i = 1; i < 9; i += 3)
  2128.             {
  2129.             if (!reg[i].width || !reg[i].height)
  2130.                 continue;
  2131.             rect[n].x = reg[i].x + st;
  2132.             rect[n].y = reg[i].y + st;
  2133.             rect[n].width = reg[i].width - st * 2;
  2134.             rect[n].height = reg[i].height - st * 2;
  2135.             n++;
  2136.             }
  2137.         break;
  2138.         }
  2139.     case DrawVScroll:
  2140.         {
  2141.         for (i = 3; i < 6; i++)
  2142.             {
  2143.             if (!reg[i].width || !reg[i].height)
  2144.                 continue;
  2145.             rect[n].x = reg[i].x + st;
  2146.             rect[n].y = reg[i].y + st;
  2147.             rect[n].width = reg[i].width - st * 2;
  2148.             rect[n].height = reg[i].height - st * 2;
  2149.             n++;
  2150.             }
  2151.         break;
  2152.         }
  2153.     case DrawRow:
  2154.         {
  2155.         for (i = 0; i < 9; i++)
  2156.             {
  2157.             if (!reg[i].width || !reg[i].height)
  2158.                 continue;
  2159.             if (!(row >= reg[i].row &&
  2160.                 row < reg[i].row + reg[i].nrow))
  2161.                 continue;
  2162.             height = 0;
  2163.             for (j = reg[i].row; j < row; j++)
  2164.                 height += GetRowHeight(g, j);
  2165.             rect[n].x = reg[i].x + st;
  2166.             rect[n].y = reg[i].y + st + height;
  2167.             rect[n].width = reg[i].width - st * 2;
  2168.             rect[n].height = GetRowHeight(g, row);
  2169.             ClipRectToReg(g, &rect[n], ®[i]);
  2170.             n++;
  2171.             }
  2172.         break;
  2173.         }
  2174.     case DrawCol:
  2175.         {
  2176.         for (i = 0; i < 9; i++)
  2177.             {
  2178.             if (!reg[i].width || !reg[i].height)
  2179.                 continue;
  2180.             if (!(col >= reg[i].col &&
  2181.                 col < reg[i].col + reg[i].ncol))
  2182.                 continue;
  2183.             width = 0;
  2184.             for (j = reg[i].col; j < col; j++)
  2185.                 width += GetColWidth(g, j);
  2186.             rect[n].x = reg[i].x + st + width;
  2187.             rect[n].y = reg[i].y + st;
  2188.             rect[n].width = GetColWidth(g, col);
  2189.             rect[n].height = reg[i].height - st * 2;
  2190.             ClipRectToReg(g, &rect[n], ®[i]);
  2191.             n++;
  2192.             }
  2193.         break;
  2194.         }
  2195.     case DrawCell:
  2196.         {
  2197.         if (!RowColToXY(g, row, col, True, &rect[n]))
  2198.             n++;
  2199.         break;
  2200.         }
  2201.     }
  2202.     for (i = 0; i < n; i++)
  2203.         {
  2204.         if (!rect[i].width || !rect[i].height)
  2205.             continue;
  2206.         event.type = Expose;
  2207.         event.window = win;
  2208.         event.display = dpy;
  2209.         event.x = rect[i].x;
  2210.         event.y = rect[i].y;
  2211.         event.width = rect[i].width;
  2212.         event.height = rect[i].height;
  2213.         event.send_event = True;
  2214.         event.count = 0;
  2215.         if (g->grid.immediateDraw)
  2216.             {
  2217.             region = XCreateRegion();
  2218.             XUnionRectWithRegion(&rect[i], region, region);
  2219.             Redisplay((Widget)g, &event, region);
  2220.             XDestroyRegion(region);
  2221.             }
  2222.         else
  2223.             XSendEvent(dpy, win, False, ExposureMask, (XEvent *)&event);
  2224.         if (g->grid.debugLevel > 1)
  2225.             fprintf(stderr, "XmLGrid: DrawArea expose x %d y %d w %d h %d\n",
  2226.                 event.x, event.y, event.width, event.height);
  2227.         }
  2228.     }
  2229.  
  2230. static void
  2231. ExtendSelectRange(XmLGridWidget g,
  2232.           int *type,
  2233.           int *fr,
  2234.           int *lr,
  2235.           int *fc,
  2236.           int *lc)
  2237.     {
  2238.     int r, c;
  2239.  
  2240.     if ((g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW) ||
  2241.         (ColPosToType(g, g->grid.extendCol) != XmCONTENT))
  2242.         *type = SelectRow;
  2243.     else if (RowPosToType(g, g->grid.extendRow) != XmCONTENT)
  2244.         *type = SelectCol;
  2245.     else
  2246.         *type = SelectCell;
  2247.  
  2248.     r = g->grid.extendToRow;
  2249.     if (r < g->grid.headingRowCount)
  2250.         r = g->grid.headingRowCount;
  2251.     if (r >= g->grid.headingRowCount + g->grid.rowCount)
  2252.         r = g->grid.headingRowCount + g->grid.rowCount - 1;
  2253.     if (*type == SelectCol)
  2254.         {
  2255.         *fr = 0;
  2256.         *lr = 1;
  2257.         }
  2258.     else if (g->grid.extendRow < r)
  2259.         {
  2260.         *fr = g->grid.extendRow;
  2261.         *lr = r;
  2262.         }
  2263.     else
  2264.         {
  2265.         *fr = r;
  2266.         *lr = g->grid.extendRow;
  2267.         }
  2268.     c = g->grid.extendToCol;
  2269.     if (c < g->grid.headingColCount)
  2270.         c = g->grid.headingColCount;
  2271.     if (c >= g->grid.headingColCount + g->grid.colCount)
  2272.         c = g->grid.headingColCount + g->grid.colCount - 1;
  2273.     if (*type == SelectRow)
  2274.         {
  2275.         *fc = 0;
  2276.         *lc = 1;
  2277.         }
  2278.     else if (g->grid.extendCol < c)
  2279.         {
  2280.         *fc = g->grid.extendCol;
  2281.         *lc = c;
  2282.         }
  2283.     else
  2284.         {
  2285.         *fc = c;
  2286.         *lc = g->grid.extendCol;
  2287.         }
  2288.     }
  2289.  
  2290. static void 
  2291. ExtendSelect(XmLGridWidget g,
  2292.          XEvent *event,
  2293.          Boolean set,
  2294.          int row,
  2295.          int col)
  2296.     {
  2297.     int type;
  2298.     int r, fr, lr;
  2299.     int c, fc, lc;
  2300.  
  2301.     if (row == -1 || col == -1)
  2302.         {
  2303.         g->grid.extendRow = -1;
  2304.         g->grid.extendCol = -1;
  2305.         g->grid.extendToRow = -1;
  2306.         g->grid.extendToCol = -1;
  2307.         g->grid.extendSelect = True;
  2308.         return;
  2309.         }
  2310.     if (RowPosToType(g, row) == XmFOOTER || ColPosToType(g, col) == XmFOOTER)
  2311.         return;
  2312.     if ((g->grid.extendToRow == row && g->grid.extendToCol == col) ||
  2313.         (g->grid.extendRow == -1 && row == g->grid.focusRow &&
  2314.         g->grid.extendCol == -1 && col == g->grid.focusCol))
  2315.         return;
  2316.     if (g->grid.extendRow != -1 && g->grid.extendCol != -1)
  2317.         {
  2318.         /* clear previous extend */
  2319.         ExtendSelectRange(g, &type, &fr, &lr, &fc, &lc);
  2320.         for (r = fr; r <= lr; r += 1)
  2321.             for (c = fc; c <= lc; c += 1)
  2322.                 SelectTypeArea(g, type, event,
  2323.                     RowPosToTypePos(g, XmCONTENT, r),
  2324.                     ColPosToTypePos(g, XmCONTENT, c), False, True);
  2325.         }
  2326.     else
  2327.         {
  2328.         g->grid.extendRow = g->grid.focusRow;
  2329.         g->grid.extendCol = g->grid.focusCol;
  2330.         }
  2331.     if (set == True)
  2332.         {
  2333.         g->grid.extendRow = row;
  2334.         g->grid.extendCol = col;
  2335.         }
  2336.     if (g->grid.extendRow < 0 || g->grid.extendCol < 0)
  2337.         return;
  2338.     g->grid.extendToRow = row;
  2339.     g->grid.extendToCol = col;
  2340.  
  2341.     /* set new extend */
  2342.     ExtendSelectRange(g, &type, &fr, &lr, &fc, &lc);
  2343.     for (r = fr; r <= lr; r += 1)
  2344.         for (c = fc; c <= lc; c += 1)
  2345.             SelectTypeArea(g, type, event,
  2346.                 RowPosToTypePos(g, XmCONTENT, r),
  2347.                 ColPosToTypePos(g, XmCONTENT, c),
  2348.                 g->grid.extendSelect, True);
  2349.     }
  2350.  
  2351. static void 
  2352. SelectTypeArea(XmLGridWidget g,
  2353.            int type,
  2354.            XEvent *event,
  2355.            int row,
  2356.            int col,
  2357.            Boolean select,
  2358.            Boolean notify)
  2359.     {
  2360.     Widget w;
  2361.     XmLGridRow rowp;
  2362.     XmLGridColumn colp;
  2363.     XmLGridCell cellp;
  2364.     int r, fr, lr, hrc;
  2365.     int c, fc, lc, hcc;
  2366.     int badPos, hasCB;
  2367.     XmLGridCallbackStruct cbs;
  2368.  
  2369.     w = (Widget)g;
  2370.     hrc = g->grid.headingRowCount;
  2371.     hcc = g->grid.headingColCount;
  2372.     cbs.event = event;
  2373.     cbs.rowType = XmCONTENT;
  2374.     cbs.columnType = XmCONTENT;
  2375.     hasCB = 0;
  2376.     if (select == True)
  2377.         {
  2378.         if (type == SelectRow)
  2379.             cbs.reason = XmCR_SELECT_ROW;
  2380.         else if (type == SelectCol)
  2381.             cbs.reason = XmCR_SELECT_COLUMN;
  2382.         else if (type == SelectCell)
  2383.             cbs.reason = XmCR_SELECT_CELL;
  2384.         if (XtHasCallbacks(w, XmNselectCallback) == XtCallbackHasSome)
  2385.             hasCB = 1;
  2386.         }
  2387.     else
  2388.         {
  2389.         if (type == SelectRow)
  2390.             cbs.reason = XmCR_DESELECT_ROW;
  2391.         else if (type == SelectCol)
  2392.             cbs.reason = XmCR_DESELECT_COLUMN;
  2393.         else if (type == SelectCell)
  2394.             cbs.reason = XmCR_DESELECT_CELL;
  2395.         if (XtHasCallbacks(w, XmNdeselectCallback) == XtCallbackHasSome)
  2396.             hasCB = 1;
  2397.         }
  2398.     if (row != -1)
  2399.         {
  2400.         fr = hrc + row;
  2401.         lr = fr + 1;
  2402.         }
  2403.     else
  2404.         {
  2405.         fr = hrc;
  2406.         lr = XmLArrayGetCount(g->grid.rowArray) - g->grid.footerRowCount;
  2407.         }
  2408.     if (col != -1)
  2409.         {
  2410.         fc = hcc + col;
  2411.         lc = fc + 1;
  2412.         }
  2413.     else
  2414.         {
  2415.         fc = hcc;
  2416.         lc = XmLArrayGetCount(g->grid.colArray) - g->grid.footerColCount;
  2417.         }
  2418.     badPos = 0;
  2419.     for (r = fr; r < lr; r++)
  2420.         for (c = fc; c < lc; c++)
  2421.             {
  2422.             if (type == SelectRow)
  2423.                 {
  2424.                 rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  2425.                 if (!rowp)
  2426.                     {
  2427.                     badPos = 1;
  2428.                     continue;
  2429.                     }
  2430.                 if (XmLGridRowIsSelected(rowp) == select)
  2431.                     continue;
  2432.                 if (select == True &&
  2433.                     (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW ||
  2434.                     g->grid.selectionPolicy == XmSELECT_SINGLE_ROW))
  2435.                     SelectTypeArea(g, SelectRow, event, -1, 0, False, notify);
  2436.                 XmLGridRowSetSelected(rowp, select);
  2437.                 if (RowIsVisible(g, r))
  2438.                     DrawArea(g, DrawRow, r, 0);
  2439.                 if (notify && hasCB)
  2440.                     {
  2441.                     cbs.row = r - hrc;
  2442.                     if (select == True)
  2443.                         XtCallCallbackList(w, g->grid.selectCallback,
  2444.                             (XtPointer)&cbs);
  2445.                     else
  2446.                         XtCallCallbackList(w, g->grid.deselectCallback,
  2447.                             (XtPointer)&cbs);
  2448.                     }
  2449.                 }
  2450.             else if (type == SelectCol)
  2451.                 {
  2452.                 colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  2453.                 if (!colp)
  2454.                     {
  2455.                     badPos = 1;
  2456.                     continue;
  2457.                     }
  2458.                 if (XmLGridColumnIsSelected(colp) == select)
  2459.                     continue;
  2460.                 XmLGridColumnSetSelected(colp, select);
  2461.                 if (ColIsVisible(g, c))
  2462.                     DrawArea(g, DrawCol, 0, c);
  2463.                 if (notify && hasCB)
  2464.                     {
  2465.                     cbs.column = c - hcc;
  2466.                     if (select == True)
  2467.                         XtCallCallbackList(w, g->grid.selectCallback,
  2468.                             (XtPointer)&cbs);
  2469.                     else
  2470.                         XtCallCallbackList(w, g->grid.deselectCallback,
  2471.                             (XtPointer)&cbs);
  2472.                     }
  2473.                 }
  2474.             else if (type == SelectCell)
  2475.                 {
  2476.                 cellp = GetCell(g, r, c);
  2477.                 if (!cellp)
  2478.                     {
  2479.                     badPos = 1;
  2480.                     continue;
  2481.                     }
  2482.                 if (XmLGridCellIsSelected(cellp) == select)
  2483.                     continue;
  2484.                 XmLGridCellSetSelected(cellp, select);
  2485.                 DrawArea(g, DrawCell, r, c);
  2486.                 if (notify && hasCB)
  2487.                     {
  2488.                     cbs.column = c - hcc;
  2489.                     cbs.row = r - hrc;
  2490.                     if (select == True)
  2491.                         XtCallCallbackList(w, g->grid.selectCallback,
  2492.                             (XtPointer)&cbs);
  2493.                     else
  2494.                         XtCallCallbackList(w, g->grid.deselectCallback,
  2495.                             (XtPointer)&cbs);
  2496.                     }
  2497.                 }
  2498.             }
  2499.     if (badPos)
  2500.         XmLWarning((Widget)g, "SelectTypeArea() - bad position");
  2501.     }
  2502.  
  2503. static int 
  2504. GetSelectedArea(XmLGridWidget g,
  2505.         int type,
  2506.         int *rowPos,
  2507.         int *colPos,
  2508.         int count)
  2509.     {
  2510.     XmLGridRow row;
  2511.     XmLGridColumn col;
  2512.     XmLGridCell cell;
  2513.     int r, fr, lr;
  2514.     int c, fc, lc;
  2515.     int n;
  2516.  
  2517.     if (type == SelectCol)
  2518.         {
  2519.         fr = 0;
  2520.         lr = 1;
  2521.         }
  2522.     else
  2523.         {
  2524.         fr = g->grid.headingRowCount;
  2525.         lr = XmLArrayGetCount(g->grid.rowArray) - g->grid.footerRowCount;
  2526.         }
  2527.     if (type == SelectRow)
  2528.         {
  2529.         fc = 0;
  2530.         lc = 1;
  2531.         }
  2532.     else
  2533.         {
  2534.         fc = g->grid.headingColCount;
  2535.         lc = XmLArrayGetCount(g->grid.colArray) - g->grid.footerColCount;
  2536.         }
  2537.     n = 0;
  2538.     for (r = fr; r < lr; r++)
  2539.         for (c = fc; c < lc; c++)
  2540.             {
  2541.             if (type == SelectRow)
  2542.                 {
  2543.                 row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  2544.                 if (row && XmLGridRowIsSelected(row) == True)
  2545.                     {
  2546.                     if (rowPos && n < count)
  2547.                         rowPos[n] = r - fr;
  2548.                     n++;
  2549.                     }
  2550.                 }
  2551.             else if (type == SelectCol)
  2552.                 {
  2553.                 col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  2554.                 if (col && XmLGridColumnIsSelected(col) == True)
  2555.                     {
  2556.                     if (colPos && n < count)
  2557.                         colPos[n] = c - fc;
  2558.                     n++;
  2559.                     }
  2560.                 }
  2561.             else if (type == SelectCell)
  2562.                 {
  2563.                 cell = GetCell(g, r, c);
  2564.                 if (cell && XmLGridCellIsSelected(cell) == True)
  2565.                     {
  2566.                     if (rowPos && colPos && n < count)
  2567.                         {
  2568.                         rowPos[n] = r - fr;
  2569.                         colPos[n] = c - fc;
  2570.                         }
  2571.                     n++;
  2572.                     }
  2573.                 }
  2574.             }
  2575.     return n;
  2576.     }
  2577.  
  2578. static void
  2579. ChangeManaged(Widget w)
  2580.     {
  2581.     _XmNavigChangeManaged(w);
  2582.     }
  2583.  
  2584. static void
  2585. Resize(Widget w)
  2586.     {
  2587.     XmLGridWidget g;
  2588.     XmLGridCallbackStruct cbs;
  2589.  
  2590.     g = (XmLGridWidget)w;
  2591.  
  2592.     if (!g->grid.inResize)
  2593.       {
  2594.         cbs.reason = XmCR_RESIZE_GRID;
  2595.  
  2596.         g->grid.inResize = True;
  2597.         XtCallCallbackList((Widget)g, g->grid.resizeCallback,
  2598.                    (XtPointer)&cbs);
  2599.         g->grid.inResize = False;
  2600.       }
  2601.  
  2602.     VertLayout(g, 0);
  2603.     HorizLayout(g, 0);
  2604.     PlaceScrollbars(g);
  2605.     DrawArea(g, DrawAll, 0, 0);
  2606.     }
  2607.  
  2608. static void
  2609. PlaceScrollbars(XmLGridWidget g)
  2610.     {
  2611.     int x, y;
  2612.     int width, height;
  2613.     Widget vsb, hsb;
  2614.     Dimension headingRowHeight = 0;
  2615.  
  2616.     vsb = g->grid.vsb;
  2617.     hsb = g->grid.hsb;
  2618.     width = g->core.width;
  2619.     if (XtIsManaged(vsb))
  2620.         width -= vsb->core.width;
  2621.     if (width <= 0)
  2622.         width = 1;
  2623.     y = g->core.height - hsb->core.height;
  2624.     XtConfigureWidget(hsb, 0, y, width, hsb->core.height, 0);
  2625.  
  2626.     height = g->core.height;
  2627.     if (XtIsManaged(hsb))
  2628.         height -= hsb->core.height;
  2629.  
  2630.     y = 0;
  2631.     
  2632.     if (g->grid.headingRowCount > 0)
  2633.       {
  2634.         XmLGridRow rowp;
  2635.  
  2636.         rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, 0);
  2637.         
  2638.         headingRowHeight = XmLGridRowHeightInPixels(rowp) + g->manager.shadow_thickness;
  2639.       }
  2640.  
  2641.         if (g->grid.showHideButton && g->grid.hideButton)
  2642.         {
  2643.           if (headingRowHeight == 0)
  2644.         headingRowHeight = 20;
  2645.  
  2646.           /* if there is at least heading row, we make the
  2647.            height of the button the height of the first
  2648.            heading row.
  2649.  
  2650.            This is pretty braindead... */
  2651.  
  2652.         XtConfigureWidget(g->grid.hideButton, 
  2653.                   g->core.width - vsb->core.width,
  2654.                   y + g->manager.shadow_thickness,
  2655.                   vsb->core.width,
  2656.                   headingRowHeight, 0);
  2657.  
  2658.         /* once we've positioned it, make sure it's managed.
  2659.            Doing it in this order (position, then manage) reduces
  2660.            screen flickering -- the button doesn't flash on in the
  2661.            upper left corner for an instant. */
  2662.         if (!XtIsManaged(g->grid.hideButton)) 
  2663.             XtManageChild(g->grid.hideButton);
  2664.         }
  2665.  
  2666.     if (height <= 0)
  2667.         width = 1;
  2668.     x = g->core.width - vsb->core.width;
  2669.     XtConfigureWidget(vsb, 
  2670.               x, y + headingRowHeight + g->manager.shadow_thickness * 2, 
  2671.               vsb->core.width, height - headingRowHeight - g->manager.shadow_thickness * 2, 
  2672.               0);
  2673.     }
  2674.  
  2675. void 
  2676. _XmLGridLayout(XmLGridWidget g)
  2677.     {
  2678.     VertLayout(g, 1);
  2679.     HorizLayout(g, 1);
  2680.     }
  2681.  
  2682. static void
  2683. VertLayout(XmLGridWidget g,
  2684.        int resizeIfNeeded)
  2685.     {
  2686.     GridReg *reg;
  2687.     int i, j, st2, height, rowCount;
  2688.     int topNRow, topHeight;
  2689.     int midRow, midY, midNRow, midHeight;
  2690.     int botRow, botY, botNRow, botHeight;
  2691.     int scrollChanged, needsSB, needsResize, cRow;
  2692.     int maxRow, maxPos, maxHeight, newHeight, sliderSize;
  2693.     int horizSizeChanged;
  2694.     XtWidgetGeometry req;
  2695.     XmLGridCallbackStruct cbs;
  2696.     XmLGridPreLayoutProc preLayoutProc;
  2697.  
  2698.     if (g->grid.layoutFrozen == True)
  2699.         {
  2700.         g->grid.needsVertLayout = 1;
  2701.         return;
  2702.         }
  2703.  
  2704.     maxRow = maxPos = maxHeight = newHeight = horizSizeChanged = 0;
  2705.     preLayoutProc = XmLGridClassPartOfWidget(g).preLayoutProc;
  2706.     if (g->grid.layoutStack < 2 && preLayoutProc != XmInheritGridPreLayout)
  2707.         horizSizeChanged = preLayoutProc(g, 1);
  2708.  
  2709.     scrollChanged = 0;
  2710.     needsResize = 0;
  2711.     needsSB = 0;
  2712.     rowCount = XmLArrayGetCount(g->grid.rowArray);
  2713.     reg = g->grid.reg;
  2714.     st2 = g->manager.shadow_thickness * 2;
  2715.     TextAction(g, TEXT_HIDE);
  2716.  
  2717.     topHeight = 0;
  2718.     topNRow = g->grid.topFixedCount;
  2719.     if (topNRow > g->grid.rowCount + g->grid.headingRowCount)
  2720.         topNRow = g->grid.rowCount + g->grid.headingRowCount;
  2721.     if (topNRow)
  2722.         {
  2723.         topHeight += st2;
  2724.         for (i = 0; i < topNRow; i++)
  2725.             topHeight += GetRowHeight(g, i);
  2726.         }
  2727.     botHeight = 0;
  2728.     botNRow = g->grid.bottomFixedCount;
  2729.     if (topNRow + botNRow > rowCount)
  2730.         botNRow = rowCount - topNRow;
  2731.     botRow = rowCount - botNRow;
  2732.     if (botNRow)
  2733.         {
  2734.         botHeight += st2;
  2735.         for (i = botRow; i < rowCount; i++)
  2736.             botHeight += GetRowHeight(g, i);
  2737.         }
  2738.     height = 0;
  2739.     if (topNRow)
  2740.         height += topHeight + g->grid.topFixedMargin;
  2741.     midY = height;
  2742.     if (botNRow)
  2743.         height += botHeight + g->grid.bottomFixedMargin;
  2744.     if (XtIsManaged(g->grid.hsb))
  2745.         {
  2746.         height += g->grid.hsb->core.height; 
  2747.         height += g->grid.scrollBarMargin;
  2748.         }
  2749.     maxHeight = g->core.height - height;
  2750.     if (g->grid.vsPolicy != XmCONSTANT)
  2751.         {
  2752.         if (rowCount == topNRow + botNRow)
  2753.             midHeight = 0;
  2754.         else
  2755.             midHeight = st2;
  2756.         for (i = topNRow; i < rowCount - botNRow; i++)
  2757.             midHeight += GetRowHeight(g, i);
  2758.         midRow = topNRow;
  2759.         midNRow = rowCount - topNRow - botNRow;
  2760.         needsResize = 1;
  2761.         newHeight = midHeight + height;
  2762.         if (g->grid.debugLevel)
  2763.             fprintf(stderr, "XmLGrid: VertLayout VARIABLE height\n");
  2764.         }
  2765.     else
  2766.         {
  2767.         if (maxHeight < st2)
  2768.             maxHeight = 0;
  2769.         height = st2;
  2770.         j = rowCount - botNRow - 1;
  2771.         for (i = j; i >= topNRow; i--)
  2772.             {
  2773.             height += GetRowHeight(g, i);
  2774.             if (height > maxHeight)
  2775.                 break;
  2776.             }
  2777.         i++;
  2778.         if (i > j)
  2779.             i = j;
  2780.         maxRow = i;
  2781.         if (maxRow < topNRow)
  2782.             maxRow = topNRow;
  2783.         if (g->grid.debugLevel)
  2784.             fprintf(stderr, "XmLGrid: VertLayout max scroll row %d\n", i);
  2785.         if (maxRow == topNRow)
  2786.             {
  2787.             if (g->grid.scrollRow != topNRow)
  2788.                 {
  2789.                 scrollChanged = 1;
  2790.                 g->grid.scrollRow = topNRow;
  2791.                 }
  2792.             midRow = topNRow;
  2793.             midHeight = maxHeight;
  2794.             midNRow = rowCount - topNRow - botNRow;
  2795.             if (g->grid.debugLevel)
  2796.                 fprintf(stderr, "XmLGrid: VertLayout everything fits\n");
  2797.             }
  2798.         else
  2799.             {
  2800.             if (g->grid.scrollRow < topNRow)
  2801.                 {
  2802.                 scrollChanged = 1;
  2803.                 g->grid.scrollRow = topNRow;
  2804.                 if (g->grid.debugLevel)
  2805.                     fprintf(stderr, "XmLGrid: VertLayout scrolled < topRow\n");
  2806.                 }
  2807.             if (g->grid.scrollRow > maxRow)
  2808.                 {
  2809.                 if (g->grid.debugLevel)
  2810.                     fprintf(stderr, "XmLGrid: VertLayout scrolled > maxRow\n");
  2811.                 scrollChanged = 1;
  2812.                 g->grid.scrollRow = maxRow;
  2813.                 }
  2814.             height = st2;
  2815.             midNRow = 0;
  2816.             for (i = g->grid.scrollRow; i < rowCount - botNRow; i++)
  2817.                 {
  2818.                 midNRow++;
  2819.                 height += GetRowHeight(g, i);
  2820.                 if (height >= maxHeight)
  2821.                     break;
  2822.                 }
  2823.             needsSB = 1;
  2824.             midRow = g->grid.scrollRow;
  2825.             midHeight = maxHeight;
  2826.             }
  2827.         }
  2828.     botY = midY + midHeight;
  2829.     if (botNRow)
  2830.         botY += g->grid.bottomFixedMargin;
  2831.     for (i = 0; i < 3; i++)
  2832.         {
  2833.         reg[i].y = 0;
  2834.         reg[i].height = topHeight;
  2835.         reg[i].row = 0;
  2836.         reg[i].nrow = topNRow;
  2837.         }
  2838.     for (i = 3; i < 6; i++)
  2839.         {
  2840.         reg[i].y = midY;
  2841.         reg[i].height = midHeight;
  2842.         reg[i].row = midRow;
  2843.         reg[i].nrow = midNRow;
  2844.         }
  2845.     for (i = 6; i < 9; i++)
  2846.         {
  2847.         reg[i].y = botY;
  2848.         reg[i].height = botHeight;
  2849.         reg[i].row = botRow;
  2850.         reg[i].nrow = botNRow;
  2851.         }
  2852.     if (g->grid.debugLevel)
  2853.             {
  2854.             fprintf(stderr, "XmLGrid: VertLayout T y %d h %d r %d nr %d\n",
  2855.                 reg[0].y, reg[0].height, reg[0].row, reg[0].nrow);
  2856.             fprintf(stderr, "XmLGrid: VertLayout M y %d h %d r %d nr %d\n",
  2857.                 reg[3].y, reg[3].height, reg[3].row, reg[3].nrow);
  2858.             fprintf(stderr, "XmLGrid: VertLayout B y %d h %d r %d nr %d\n",
  2859.                 reg[6].y, reg[6].height, reg[6].row, reg[6].nrow);
  2860.             }
  2861.     if (needsSB)
  2862.         {
  2863.         if (!XtIsManaged(g->grid.vsb))
  2864.             {
  2865.             XtManageChild(g->grid.vsb);
  2866.             horizSizeChanged = 1;
  2867.             }
  2868.         if (g->grid.debugLevel)
  2869.             fprintf(stderr, "XmLGrid: VertLayout set sb values\n");
  2870.         maxPos = PosToVisPos(g, maxRow, 1);
  2871.         sliderSize = PosToVisPos(g, rowCount - botNRow - 1, 1) - maxPos + 1;
  2872.         XtVaSetValues(g->grid.vsb,
  2873.             XmNminimum, PosToVisPos(g, topNRow, 1),
  2874.             XmNmaximum, maxPos + sliderSize,
  2875.             XmNsliderSize, sliderSize,
  2876.             XmNpageIncrement, sliderSize,
  2877.             XmNvalue, PosToVisPos(g, g->grid.scrollRow, 1),
  2878.             NULL);
  2879.         }
  2880.     else if (g->grid.vsPolicy == XmCONSTANT &&
  2881.         g->grid.vsbDisplayPolicy == XmSTATIC)
  2882.         {
  2883.         if (!XtIsManaged(g->grid.vsb))
  2884.             {
  2885.             XtManageChild(g->grid.vsb);
  2886.             horizSizeChanged = 1;
  2887.             }
  2888.         if (g->grid.debugLevel)
  2889.             fprintf(stderr, "XmLGrid: VertLayout vsb not needed but static\n");
  2890.         XtVaSetValues(g->grid.vsb,
  2891.             XmNminimum, 0,
  2892.             XmNmaximum, 1,
  2893.             XmNsliderSize, 1,
  2894.             XmNpageIncrement, 1,
  2895.             XmNvalue, 0,
  2896.             NULL);
  2897.         }
  2898.     else
  2899.         {
  2900.         if (XtIsManaged(g->grid.vsb))
  2901.             {
  2902.             XtUnmanageChild(g->grid.vsb);
  2903.             horizSizeChanged = 1;
  2904.             }
  2905.         }
  2906.     if (needsResize && resizeIfNeeded)
  2907.         {
  2908.         if (newHeight < 1)
  2909.             newHeight = 1;
  2910.         req.request_mode = CWHeight;
  2911.         req.height = newHeight;
  2912.         if (g->grid.debugLevel)
  2913.             fprintf(stderr, "XmLGrid: VertLayout Req h %d\n", (int)newHeight);
  2914.         XtMakeGeometryRequest((Widget)g, &req, NULL);
  2915.         PlaceScrollbars(g);
  2916.         }
  2917.     if (scrollChanged)
  2918.         DrawArea(g, DrawVScroll, 0, 0);
  2919.     TextAction(g, TEXT_SHOW);
  2920.     cRow = g->grid.scrollRow - g->grid.headingRowCount;
  2921.     if (cRow != g->grid.cScrollRow)
  2922.         {
  2923.         g->grid.cScrollRow = cRow;
  2924.         cbs.reason = XmCR_SCROLL_ROW;
  2925.         cbs.rowType = XmCONTENT;
  2926.         cbs.row = cRow;
  2927.         XtCallCallbackList((Widget)g, g->grid.scrollCallback, (XtPointer)&cbs);
  2928.         }
  2929.     if (horizSizeChanged)
  2930.         {
  2931.         if (g->grid.layoutStack > 2)
  2932.             XmLWarning((Widget)g, "VertLayout() - recursion error");
  2933.         else
  2934.             {
  2935.             g->grid.layoutStack++;
  2936.             HorizLayout(g, resizeIfNeeded);
  2937.             g->grid.layoutStack--;
  2938.             }
  2939.         PlaceScrollbars(g);
  2940.         }
  2941.     }
  2942.  
  2943. static void
  2944. HorizLayout(XmLGridWidget g,
  2945.         int resizeIfNeeded)
  2946.     {
  2947.     GridReg *reg;
  2948.     int i, j, st2, width, colCount;
  2949.     int leftNCol, leftWidth;
  2950.     int midCol, midX, midNCol, midWidth;
  2951.     int rightCol, rightX, rightNCol, rightWidth;
  2952.     int scrollChanged, needsSB, needsResize, cCol;
  2953.     int maxCol, maxPos, maxWidth, newWidth, sliderSize;
  2954.     int vertSizeChanged;
  2955.     XtWidgetGeometry req;
  2956.     XmLGridCallbackStruct cbs;
  2957.     XmLGridPreLayoutProc preLayoutProc;
  2958.  
  2959.     if (g->grid.layoutFrozen == True)
  2960.         {
  2961.         g->grid.needsHorizLayout = 1;
  2962.         return;
  2963.         }
  2964.  
  2965.     maxCol = maxPos = newWidth = vertSizeChanged = 0;
  2966.     preLayoutProc = XmLGridClassPartOfWidget(g).preLayoutProc;
  2967.     if (g->grid.layoutStack < 2 && preLayoutProc != XmInheritGridPreLayout)
  2968.         vertSizeChanged = preLayoutProc(g, 0);
  2969.  
  2970.     scrollChanged = 0;
  2971.     needsResize = 0;
  2972.     needsSB = 0;
  2973. #if 0
  2974.     /* we can't use this one if we're going to allow for hidden columns,
  2975.        as we're changing what g->grid.colCount is. 
  2976.  
  2977.        the calculation we're replacing it with works the same, and results
  2978.        in less code being munged.
  2979.        */
  2980.     colCount = XmLArrayGetCount(g->grid.colArray);
  2981. #else
  2982.     colCount = g->grid.colCount + g->grid.headingColCount + g->grid.footerColCount;
  2983. #endif
  2984.     reg = g->grid.reg;
  2985.     st2 = g->manager.shadow_thickness * 2;
  2986.     TextAction(g, TEXT_HIDE);
  2987.  
  2988.     leftWidth = 0;
  2989.     leftNCol = g->grid.leftFixedCount;
  2990.     if (leftNCol > g->grid.colCount + g->grid.headingColCount)
  2991.         leftNCol = g->grid.colCount + g->grid.headingColCount;
  2992.     if (leftNCol)
  2993.         {
  2994.         leftWidth += st2;
  2995.         for (i = 0; i < leftNCol; i++)
  2996.             leftWidth += GetColWidth(g, i);
  2997.         }
  2998.     rightWidth = 0;
  2999.     rightNCol = g->grid.rightFixedCount;
  3000.     if (rightNCol + leftNCol > colCount)
  3001.         rightNCol = colCount - leftNCol;
  3002.     rightCol = colCount - rightNCol;
  3003.     if (rightNCol)
  3004.         {
  3005.         rightWidth += st2;
  3006.         for (i = rightCol; i < colCount; i++)
  3007.             rightWidth += GetColWidth(g, i);
  3008.         }
  3009.     width = 0;
  3010.     if (leftNCol)
  3011.         width += leftWidth + g->grid.leftFixedMargin;
  3012.     midX = width;
  3013.     if (rightNCol)
  3014.         width += rightWidth + g->grid.rightFixedMargin;
  3015.     if (XtIsManaged(g->grid.vsb))
  3016.         {
  3017.         width += g->grid.vsb->core.width; 
  3018.         width += g->grid.scrollBarMargin;
  3019.         }
  3020.     maxWidth = g->core.width - width;
  3021.     if (g->grid.hsPolicy != XmCONSTANT)
  3022.         {
  3023.         if (colCount == leftNCol + rightNCol)
  3024.             midWidth = 0;
  3025.         else
  3026.             midWidth = st2;
  3027.         for (i = leftNCol; i < colCount - rightNCol; i++)
  3028.             midWidth += GetColWidth(g, i);
  3029.         midCol = leftNCol;
  3030.         midNCol = colCount - leftNCol - rightNCol;
  3031.         needsResize = 1;
  3032.         newWidth = midWidth + width;
  3033.         if (g->grid.debugLevel)
  3034.             fprintf(stderr, "XmLGrid: HorizLayout VARIABLE width\n");
  3035.         }
  3036.     else
  3037.         {
  3038.         if (maxWidth < st2)
  3039.             maxWidth = 0;
  3040.         width = st2;
  3041.         j = colCount - rightNCol - 1;
  3042.         for (i = j; i >= leftNCol; i--)
  3043.             {
  3044.             width += GetColWidth(g, i);
  3045.             if (width > maxWidth)
  3046.                 break;
  3047.             }
  3048.         i++;
  3049.         if (i > j)
  3050.             i = j;
  3051.         maxCol = i;
  3052.         if (maxCol < leftNCol)
  3053.             maxCol = leftNCol;
  3054.         if (g->grid.debugLevel)
  3055.             fprintf(stderr, "XmLGrid: HorizLayout max scroll col %d\n", i);
  3056.         if (maxCol == leftNCol)
  3057.             {
  3058.             if (g->grid.scrollCol != leftNCol)
  3059.                 {
  3060.                 scrollChanged = 1;
  3061.                 g->grid.scrollCol = leftNCol;
  3062.                 }
  3063.             midCol = leftNCol;
  3064.             midWidth = maxWidth;
  3065.             midNCol = colCount - leftNCol - rightNCol;
  3066.             if (g->grid.debugLevel)
  3067.                 fprintf(stderr, "XmLGrid: HorizLayout everything fits\n");
  3068.             }
  3069.         else
  3070.             {
  3071.             if (g->grid.scrollCol < leftNCol)
  3072.                 {
  3073.                 scrollChanged = 1;
  3074.                 g->grid.scrollCol = leftNCol;
  3075.                 if (g->grid.debugLevel)
  3076.                     fprintf(stderr, "XmLGrid: HorizLayout scroll < leftCol\n");
  3077.                 }
  3078.             if (g->grid.scrollCol > maxCol)
  3079.                 {
  3080.                 if (g->grid.debugLevel)
  3081.                     fprintf(stderr, "XmLGrid: HorizLayout scroll > maxCol\n");
  3082.                 scrollChanged = 1;
  3083.                 g->grid.scrollCol = maxCol;
  3084.                 }
  3085.             width = st2;
  3086.             midNCol = 0;
  3087.             for (i = g->grid.scrollCol; i < colCount - rightNCol; i++)
  3088.                 {
  3089.                 midNCol++;
  3090.                 width += GetColWidth(g, i);
  3091.                 if (width >= maxWidth)
  3092.                     break;
  3093.                 }
  3094.             needsSB = 1;
  3095.             midCol = g->grid.scrollCol;
  3096.             midWidth = maxWidth;
  3097.             }
  3098.         }
  3099.     rightX = midX + midWidth;
  3100.     if (rightNCol)
  3101.         rightX += g->grid.rightFixedMargin;
  3102.     for (i = 0; i < 9; i += 3)
  3103.         {
  3104.         reg[i].x = 0;
  3105.         reg[i].width = leftWidth;
  3106.         reg[i].col = 0;
  3107.         reg[i].ncol = leftNCol;
  3108.         }
  3109.     for (i = 1; i < 9; i += 3)
  3110.         {
  3111.         reg[i].x = midX;
  3112.         reg[i].width = midWidth;
  3113.         reg[i].col = midCol;
  3114.         reg[i].ncol = midNCol;
  3115.         }
  3116.     for (i = 2; i < 9; i += 3)
  3117.         {
  3118.         reg[i].x = rightX;
  3119.         reg[i].width = rightWidth;
  3120.         reg[i].col = rightCol;
  3121.         reg[i].ncol = rightNCol;
  3122.         }
  3123.     if (g->grid.debugLevel)
  3124.         {
  3125.         fprintf(stderr, "XmLGrid: HorizLayout TOP x %d w %d c %d nc %d\n",
  3126.             reg[0].x, reg[0].width, reg[0].col, reg[0].ncol);
  3127.         fprintf(stderr, "XmLGrid: HorizLayout MID x %d w %d c %d nc %d\n",
  3128.             reg[1].x, reg[1].width, reg[1].col, reg[1].ncol);
  3129.         fprintf(stderr, "XmLGrid: HorizLayout BOT x %d w %d c %d nc %d\n",
  3130.             reg[2].x, reg[2].width, reg[2].col, reg[2].ncol);
  3131.         }
  3132.     if (g->grid.hsPolicy == XmCONSTANT && colCount == 1 &&
  3133.         g->grid.colCount == 1 && width > maxWidth)
  3134.         {
  3135.         /* Single Column Pixel Scroll Mode */
  3136.         if (g->grid.singleColScrollMode)
  3137.             {
  3138.             i = g->grid.singleColScrollPos;
  3139.             if (i < 0)
  3140.                 i = 0;
  3141.             else if (i > width - maxWidth)
  3142.                 i = width - maxWidth;
  3143.             }
  3144.         else
  3145.             i = 0;
  3146.         XtVaSetValues(g->grid.hsb,
  3147.             XmNminimum, 0,
  3148.             XmNmaximum, width - maxWidth + 1,
  3149.             XmNsliderSize, 1,
  3150.             XmNpageIncrement, ((width - maxWidth) / 4) + 1,
  3151.             XmNvalue, i,
  3152.             NULL);
  3153.         if (!XtIsManaged(g->grid.hsb))
  3154.             {
  3155.             XtManageChild(g->grid.hsb);
  3156.             vertSizeChanged = 1;
  3157.             }
  3158.         g->grid.singleColScrollMode = 1;
  3159.         g->grid.singleColScrollPos = i;
  3160.         }
  3161.     else
  3162.         g->grid.singleColScrollMode = 0;
  3163.     if (g->grid.singleColScrollMode)
  3164.         ;
  3165.     else if (needsSB)
  3166.         {
  3167.         if (g->grid.debugLevel)
  3168.             fprintf(stderr, "XmLGrid: HorizLayout set sb values\n");
  3169.         if (!XtIsManaged(g->grid.hsb))
  3170.             {
  3171.             XtManageChild(g->grid.hsb);
  3172.             vertSizeChanged = 1;
  3173.             }
  3174.         maxPos = PosToVisPos(g, maxCol, 0);
  3175.         sliderSize = PosToVisPos(g, colCount - rightNCol - 1, 0) - maxPos + 1;
  3176.         XtVaSetValues(g->grid.hsb,
  3177.             XmNminimum, PosToVisPos(g, leftNCol, 0),
  3178.             XmNmaximum, maxPos + sliderSize,
  3179.             XmNsliderSize, sliderSize,
  3180.             XmNpageIncrement, sliderSize,
  3181.             XmNvalue, PosToVisPos(g, g->grid.scrollCol, 0),
  3182.             NULL);
  3183.         }
  3184.     else if (g->grid.hsPolicy == XmCONSTANT &&
  3185.         g->grid.hsbDisplayPolicy == XmSTATIC)
  3186.         {
  3187.         if (!XtIsManaged(g->grid.hsb))
  3188.             {
  3189.             XtManageChild(g->grid.hsb);
  3190.             vertSizeChanged = 1;
  3191.             }
  3192.         if (g->grid.debugLevel)
  3193.             fprintf(stderr, "XmLGrid: HorizLayout hsb not needed - static\n");
  3194.         XtVaSetValues(g->grid.hsb,
  3195.             XmNminimum, 0,
  3196.             XmNmaximum, 1,
  3197.             XmNsliderSize, 1,
  3198.             XmNpageIncrement, 1,
  3199.             XmNvalue, 0,
  3200.             NULL);
  3201.         }
  3202.     else
  3203.         {
  3204.         if (XtIsManaged(g->grid.hsb))
  3205.             {
  3206.             XtUnmanageChild(g->grid.hsb);
  3207.             vertSizeChanged = 1;
  3208.             }
  3209.         }
  3210.     if (needsResize && resizeIfNeeded)
  3211.         {
  3212.         if (newWidth < 1)
  3213.             newWidth = 1;
  3214.         req.request_mode = CWWidth;
  3215.         req.width = newWidth;
  3216.         if (g->grid.debugLevel)
  3217.             fprintf(stderr, "XmLGrid: HorizLayout Req w %d\n", (int)newWidth);
  3218.         XtMakeGeometryRequest((Widget)g, &req, NULL);
  3219.         PlaceScrollbars(g);
  3220.         }
  3221.     if (scrollChanged)
  3222.         DrawArea(g, DrawHScroll, 0, 0);
  3223.     TextAction(g, TEXT_SHOW);
  3224.     cCol = g->grid.scrollCol - g->grid.headingColCount;
  3225.     if (cCol != g->grid.cScrollCol)
  3226.         {
  3227.         g->grid.cScrollCol = cCol;
  3228.         cbs.reason = XmCR_SCROLL_COLUMN;
  3229.         cbs.columnType = XmCONTENT;
  3230.         cbs.column = cCol;
  3231.         XtCallCallbackList((Widget)g, g->grid.scrollCallback, (XtPointer)&cbs);
  3232.         }
  3233.     if (vertSizeChanged)
  3234.         {
  3235.         if (g->grid.layoutStack > 2)
  3236.             XmLWarning((Widget)g, "HorizLayout() - recursion error");
  3237.         else
  3238.             {
  3239.             g->grid.layoutStack++;
  3240.             VertLayout(g, resizeIfNeeded);
  3241.             g->grid.layoutStack--;
  3242.             }
  3243.         PlaceScrollbars(g);
  3244.         }
  3245.     }
  3246.  
  3247. static void
  3248. ApplyVisibleRows(XmLGridWidget g)
  3249.     {
  3250.     XtWidgetGeometry req;
  3251.     XmLGridCellRefValues *cellValues;
  3252.  
  3253.     if (g->grid.vsPolicy != XmCONSTANT)
  3254.         {
  3255.         XmLWarning((Widget)g,
  3256.             "verticalSizePolicy must be XmCONSTANT to set visibleRows");
  3257.         return;
  3258.         }
  3259.     cellValues = g->grid.defCellValues;
  3260.     req.request_mode = CWHeight;
  3261.     req.height = g->manager.shadow_thickness * 2 + g->grid.visibleRows *
  3262.         (4 + cellValues->fontHeight + cellValues->topMargin +
  3263.         cellValues->bottomMargin);
  3264.     if (g->grid.hsPolicy == XmCONSTANT &&
  3265.         g->grid.hsbDisplayPolicy == XmSTATIC)
  3266.         req.height += g->grid.scrollBarMargin + XtHeight(g->grid.hsb);
  3267.     XtMakeGeometryRequest((Widget)g, &req, NULL);
  3268.     }
  3269.  
  3270. static void
  3271. ApplyVisibleCols(XmLGridWidget g)
  3272.     {
  3273.     XtWidgetGeometry req;
  3274.     XmLGridCellRefValues *cellValues;
  3275.  
  3276.     if (g->grid.vsPolicy != XmCONSTANT)
  3277.         {
  3278.         XmLWarning((Widget)g,
  3279.             "horizontalSizePolicy must be XmCONSTANT to set visibleColumns");
  3280.         return;
  3281.         }
  3282.     cellValues = g->grid.defCellValues;
  3283.     req.request_mode = CWWidth;
  3284.     req.width = g->manager.shadow_thickness * 2 + g->grid.visibleCols *
  3285.         (4 + 8 * cellValues->fontWidth + cellValues->leftMargin +
  3286.         cellValues->rightMargin);
  3287.     if (g->grid.vsPolicy == XmCONSTANT &&
  3288.         g->grid.vsbDisplayPolicy == XmSTATIC)
  3289.         req.width += g->grid.scrollBarMargin + XtWidth(g->grid.vsb);
  3290.     XtMakeGeometryRequest((Widget)g, &req, NULL);
  3291.     }
  3292.  
  3293. static void
  3294. VisPosChanged(XmLGridWidget g,
  3295.           int isVert)
  3296.     {
  3297.     if (isVert)
  3298.         {
  3299.         g->grid.recalcVertVisPos = 1;
  3300.         g->grid.vertVisChangedHint = 1;
  3301.         }
  3302.     else
  3303.         g->grid.recalcHorizVisPos = 1;
  3304.     }
  3305.  
  3306. static void 
  3307. RecalcVisPos(XmLGridWidget g,
  3308.          int isVert)
  3309.     {
  3310.     XmLGridRow row;
  3311.     XmLGridColumn col;
  3312.     int i, count, visPos;
  3313.  
  3314.     if (g->grid.layoutFrozen == True)
  3315.             XmLWarning((Widget)g, "RecalcVisPos() - layout is frozen");
  3316.     visPos = 0;
  3317.     if (isVert)
  3318.         {
  3319.         if (!g->grid.recalcVertVisPos)
  3320.             return;
  3321.         count = XmLArrayGetCount(g->grid.rowArray);
  3322.         for (i = 0; i < count; i++)
  3323.             {
  3324.             row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i);
  3325.             XmLGridRowSetVisPos(row, visPos);
  3326.             if (!XmLGridRowIsHidden(row))
  3327.                 visPos++;
  3328.             }
  3329.         g->grid.recalcVertVisPos = 0;
  3330.         }
  3331.     else
  3332.         {
  3333.         if (!g->grid.recalcHorizVisPos)
  3334.             return;
  3335.         count = XmLArrayGetCount(g->grid.colArray);
  3336.         for (i = 0; i < count; i++)
  3337.             {
  3338.             col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  3339.             XmLGridColumnSetVisPos(col, visPos);
  3340.             if (!XmLGridColumnIsHidden(col))
  3341.                 visPos++;
  3342.             }
  3343.         g->grid.recalcHorizVisPos = 0;
  3344.         }
  3345.     }
  3346.  
  3347. static int 
  3348. PosToVisPos(XmLGridWidget g,
  3349.         int pos,
  3350.         int isVert)
  3351.     {
  3352.     int visPos;
  3353.     XmLGridRow row;
  3354.     XmLGridColumn col;
  3355.  
  3356.     if (isVert)
  3357.         {
  3358.         if (!g->grid.hiddenRowCount)
  3359.             visPos = pos;
  3360.         else
  3361.             {
  3362.             RecalcVisPos(g, isVert);
  3363.             row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, pos);
  3364.             if (row)
  3365.                 visPos = XmLGridRowGetVisPos(row);
  3366.             else
  3367.                 visPos = -1;
  3368.             }
  3369.         }
  3370.     else
  3371.         {
  3372.         if (!g->grid.hiddenColCount)
  3373.             visPos = pos;
  3374.         else
  3375.             {
  3376.             RecalcVisPos(g, isVert);
  3377.             col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, pos);
  3378.             if (col)
  3379.                 visPos = XmLGridColumnGetVisPos(col);
  3380.             else
  3381.                 visPos = -1;
  3382.             }
  3383.         }
  3384.     if (visPos == -1)
  3385.         XmLWarning((Widget)g, "PosToVisPos() - invalid pos");
  3386.     return visPos;
  3387.     }
  3388.  
  3389. static int
  3390. VisPosToPos(XmLGridWidget g,
  3391.         int visPos,
  3392.         int isVert)
  3393.     {
  3394.     XmLGridRow row;
  3395.     XmLGridColumn col;
  3396.     int i1, i2, vp1, vp2, ic, mid, val, count;
  3397.  
  3398.     if (isVert)
  3399.         {
  3400.         if (!g->grid.hiddenRowCount)
  3401.             return visPos;
  3402.         count = XmLArrayGetCount(g->grid.rowArray);
  3403.         if (!count)
  3404.             {
  3405.             XmLWarning((Widget)g, "VisPosToPos() - called when no rows exist");
  3406.             return -1;
  3407.             }
  3408.         RecalcVisPos(g, isVert);
  3409.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, 0);
  3410.         vp1 = XmLGridRowGetVisPos(row);
  3411.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, count - 1);
  3412.         vp2 = XmLGridRowGetVisPos(row);
  3413.         if (visPos < vp1 || visPos > vp2)
  3414.             {
  3415.             XmLWarning((Widget)g, "VisPosToPos() - invalid Vert visPos");
  3416.             return -1;
  3417.             }
  3418.         }
  3419.     else
  3420.         {
  3421.         if (!g->grid.hiddenColCount)
  3422.             return visPos;
  3423.         count = XmLArrayGetCount(g->grid.colArray);
  3424.         if (!count)
  3425.             {
  3426.             XmLWarning((Widget)g, "VisPosToPos() - called when no cols exist");
  3427.             return -1;
  3428.             }
  3429.         RecalcVisPos(g, isVert);
  3430.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, 0);
  3431.         vp1 = XmLGridColumnGetVisPos(col);
  3432.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, count - 1);
  3433.         vp2 = XmLGridColumnGetVisPos(col);
  3434.         if (visPos < vp1 || visPos > vp2)
  3435.             {
  3436.             XmLWarning((Widget)g, "VisPosToPos() - invalid Horiz visPos");
  3437.             return -1;
  3438.             }
  3439.         }
  3440.     i1 = 0;
  3441.     i2 = count;
  3442.     ic = 0;
  3443.     while (1)
  3444.         {
  3445.         mid = i1 + (i2 - i1) / 2;
  3446.         if (isVert)
  3447.             {
  3448.             row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, mid);
  3449.             val = XmLGridRowGetVisPos(row);
  3450.             }
  3451.         else
  3452.             {
  3453.             col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, mid);
  3454.             val = XmLGridColumnGetVisPos(col);
  3455.             }
  3456.         if (visPos > val)
  3457.             i1 = mid;
  3458.         else if (visPos < val)
  3459.             i2 = mid;
  3460.         else
  3461.             break;
  3462.         if (++ic > 1000)
  3463.                 return -1; /* inf loop */
  3464.         }
  3465.     return mid;
  3466.     }
  3467.  
  3468. static unsigned char
  3469. ColPosToType(XmLGridWidget g,
  3470.          int pos)
  3471.     {
  3472.     unsigned char type;
  3473.  
  3474.     if (pos < g->grid.headingColCount)
  3475.         type = XmHEADING;
  3476.     else if (pos < g->grid.headingColCount + g->grid.colCount)
  3477.         type = XmCONTENT;
  3478.     else
  3479.         type = XmFOOTER;
  3480.     return type;
  3481.     }
  3482.  
  3483. static int 
  3484. ColPosToTypePos(XmLGridWidget g,
  3485.         unsigned char type,
  3486.         int pos)
  3487. {
  3488.     int c;
  3489.  
  3490.     if (type == XmHEADING)
  3491.         c = pos;
  3492.     else if (type == XmCONTENT)
  3493.         c = pos - g->grid.headingColCount;
  3494.     else
  3495.         c = pos - g->grid.headingColCount - g->grid.colCount;
  3496.     return c;
  3497.     }
  3498.  
  3499. static unsigned char 
  3500. RowPosToType(XmLGridWidget g,
  3501.          int pos)
  3502.     {
  3503.     unsigned char type;
  3504.  
  3505.     if (pos < g->grid.headingRowCount)
  3506.         type = XmHEADING;
  3507.     else if (pos < g->grid.headingRowCount + g->grid.rowCount)
  3508.         type = XmCONTENT;
  3509.     else
  3510.         type = XmFOOTER;
  3511.     return type;
  3512.     }
  3513.  
  3514. static int
  3515. RowPosToTypePos(XmLGridWidget g,
  3516.         unsigned char type,
  3517.         int pos)
  3518.     {
  3519.     int r;
  3520.  
  3521.     if (type == XmHEADING)
  3522.         r = pos;
  3523.     else if (type == XmCONTENT)
  3524.         r = pos - g->grid.headingRowCount;
  3525.     else
  3526.         r = pos - g->grid.headingRowCount - g->grid.rowCount;
  3527.     return r;
  3528.     }
  3529.  
  3530. static int 
  3531. ColTypePosToPos(XmLGridWidget g,
  3532.         unsigned char type,
  3533.         int pos,
  3534.         int allowNeg)
  3535.     {
  3536.     if (pos < 0)
  3537.         {
  3538.         if (!allowNeg)
  3539.             return -1;
  3540.         if (type == XmHEADING)
  3541.             pos = g->grid.headingColCount;
  3542.         else if (type == XmFOOTER || type == XmALL_TYPES)
  3543.             pos = g->grid.headingColCount + g->grid.colCount +
  3544.                 g->grid.footerColCount;
  3545.         else /* XmCONTENT */
  3546.             pos = g->grid.headingColCount + g->grid.colCount;
  3547.         }
  3548.     else
  3549.         {
  3550.         if (type == XmALL_TYPES)
  3551.             ;
  3552.         else if (type == XmHEADING)
  3553.             {
  3554.             if (pos >= g->grid.headingColCount)
  3555.                 return -1;
  3556.             }
  3557.         else if (type == XmFOOTER)
  3558.             {
  3559.             if (pos >= g->grid.footerColCount)
  3560.                 return -1;
  3561.             pos += g->grid.headingColCount + g->grid.colCount;
  3562.             }
  3563.         else /* XmCONTENT */
  3564.             {
  3565.             if (pos >= g->grid.colCount)
  3566.                 return -1;
  3567.             pos += g->grid.headingColCount;
  3568.             }
  3569.         }
  3570.     return pos;
  3571.     }
  3572.  
  3573. static int
  3574. RowTypePosToPos(XmLGridWidget g,
  3575.         unsigned char type,
  3576.         int pos,
  3577.         int allowNeg)
  3578.     {
  3579.     if (pos < 0)
  3580.         {
  3581.         if (!allowNeg)
  3582.             return -1;
  3583.         if (type == XmHEADING)
  3584.             pos = g->grid.headingRowCount;
  3585.         else if (type == XmFOOTER || type == XmALL_TYPES)
  3586.             pos = g->grid.headingRowCount + g->grid.rowCount +
  3587.                     g->grid.footerRowCount;
  3588.         else /* XmCONTENT */
  3589.             pos = g->grid.headingRowCount + g->grid.rowCount;
  3590.         }
  3591.     else
  3592.         {
  3593.         if (type == XmALL_TYPES)
  3594.             ;
  3595.         else if (type == XmHEADING)
  3596.             {
  3597.             if (pos >= g->grid.headingRowCount)
  3598.                 return -1;
  3599.             }
  3600.         else if (type == XmFOOTER)
  3601.             {
  3602.             if (pos >= g->grid.footerRowCount)
  3603.                 return -1;
  3604.             pos += g->grid.headingRowCount + g->grid.rowCount;
  3605.             }
  3606.         else /* XmCONTENT */
  3607.             {
  3608.             if (pos >= g->grid.rowCount)
  3609.                 return -1;
  3610.             pos += g->grid.headingRowCount;
  3611.             }
  3612.         }
  3613.     return pos;
  3614.     }
  3615.  
  3616. static int
  3617. ScrollRowBottomPos(XmLGridWidget g,
  3618.            int row)
  3619.     {
  3620.     int r, h, height;
  3621.  
  3622.     if (g->grid.vsPolicy == XmVARIABLE)
  3623.         return -1;
  3624.     height = g->grid.reg[4].height;
  3625.     h = 0;
  3626.     r = row;
  3627.     while (r >= 0)
  3628.         {
  3629.         h += GetRowHeight(g, r);
  3630.         if (h > height)
  3631.             break;
  3632.         r--;
  3633.         }
  3634.     if (r != row)
  3635.         r++;
  3636.     return r;
  3637.     }
  3638.  
  3639. static int
  3640. ScrollColRightPos(XmLGridWidget g,
  3641.           int col)
  3642.     {
  3643.     int c, w, width;
  3644.  
  3645.     if (g->grid.hsPolicy == XmVARIABLE)
  3646.         return -1;
  3647.     width = g->grid.reg[4].width;
  3648.     w = 0;
  3649.     c = col;
  3650.     while (c >= 0)
  3651.         {
  3652.         w += GetColWidth(g, c);
  3653.         if (w >= width)
  3654.             break;
  3655.         c--;
  3656.         }
  3657.     if (c != col)
  3658.         c++;
  3659.     return c;
  3660.     }
  3661.  
  3662. static int
  3663. PosIsResize(XmLGridWidget g,
  3664.             int x,
  3665.             int y,
  3666.             int *row,
  3667.             int *col,
  3668.             int *isVert)
  3669. {
  3670.     XRectangle rect;
  3671.     int i, nx, ny, margin;
  3672.     
  3673.     /* check for bottom resize */
  3674.     if (g->grid.allowRowResize == True)
  3675.         for (i = 0; i < 2; i++)
  3676.             {
  3677.                 nx = x;
  3678.                 ny = y;
  3679.                 if (i)
  3680.                     ny = y - 4;
  3681.                 if (XYToRowCol(g, nx, ny, row, col) == -1)
  3682.                     continue;
  3683.                 if (RowColToXY(g, *row, *col, False, &rect) == -1)
  3684.                     continue;
  3685.                 if (ColPosToType(g, *col) != XmHEADING)
  3686.                     continue;
  3687.                 margin = ny - (rect.y + rect.height);
  3688.                 if (margin > -5 && margin < 5)
  3689.                     {
  3690.                         *isVert = 1;
  3691.                         return 1;
  3692.                     }
  3693.             }
  3694.     /* check for right resize */
  3695.     if (g->grid.allowColResize == True)
  3696.         for (i = 0; i < 2; i++)
  3697.             {
  3698.                 XmLGridColumn colp;
  3699.                 int c;
  3700.  
  3701.                 nx = x;
  3702.                 ny = y;
  3703.                 if (i)
  3704.                     nx = x - 4;
  3705.                 if (XYToRowCol(g, nx, ny, row, col) == -1)
  3706.                     continue;
  3707.                 if (RowColToXY(g, *row, *col, False, &rect) == -1)
  3708.                     continue;
  3709.                 if (RowPosToType(g, *row) != XmHEADING)
  3710.                     continue;
  3711.                 
  3712.                 /* if it's the last column, don't allow resize. */
  3713.                 if (*col == XmLArrayGetCount(g->grid.colArray) - 1)
  3714.                     continue;
  3715.                 
  3716.                 colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, *col);
  3717.                 
  3718.                 if (!colp->grid.resizable)
  3719.                     continue;
  3720.                 
  3721.                 for (c = *col + 1 + i; c < XmLArrayGetCount(g->grid.colArray); c ++)
  3722.                     {
  3723.                         colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  3724.                         
  3725.                         if (colp->grid.resizable)
  3726.                             break;
  3727.  
  3728.                         return 0;
  3729.                     }
  3730.  
  3731.                 margin = nx - (rect.x + rect.width);
  3732.                 if (margin > -5 && margin < 5)
  3733.                     {
  3734.                         *isVert = 0;
  3735.                         return 1;
  3736.                     }
  3737.             }
  3738.     return 0;
  3739. }
  3740.  
  3741. int 
  3742. XmLGridPosIsResize(Widget g,
  3743.            int x,
  3744.            int y)
  3745. {
  3746.   int row, col;
  3747.   int isVert;
  3748.   return PosIsResize((XmLGridWidget) g, x, y, &row, &col, &isVert);
  3749. }
  3750.  
  3751. static int
  3752. XYToRowCol(XmLGridWidget g,
  3753.        int x,
  3754.        int y,
  3755.        int *row,
  3756.        int *col)
  3757.     {
  3758.     XRectangle xyRect, rect;
  3759.     GridReg *reg;
  3760.     int i, r, c;
  3761.     int width, height;
  3762.     int st;
  3763.  
  3764.     reg = g->grid.reg;
  3765.     st = g->manager.shadow_thickness;
  3766.     xyRect.x = x;
  3767.     xyRect.y = y;
  3768.     xyRect.width = 1;
  3769.     xyRect.height = 1;
  3770.     for (i = 0; i < 9; i++)
  3771.         {
  3772.         if (!reg[i].width || !reg[i].height)
  3773.             continue;
  3774.         rect.x = reg[i].x + st;
  3775.         rect.y = reg[i].y + st;
  3776.         rect.width = reg[i].width - st * 2;
  3777.         rect.height = reg[i].height - st * 2;
  3778.         if (XmLRectIntersect(&xyRect, &rect) == XmLRectOutside)
  3779.             continue;
  3780.         height = 0;
  3781.         for (r = reg[i].row; r < reg[i].row + reg[i].nrow; r++)
  3782.             {
  3783.             width = 0;
  3784.             for (c = reg[i].col; c < reg[i].col + reg[i].ncol; c++)
  3785.                 {
  3786.                 rect.x = reg[i].x + st + width;
  3787.                 rect.y = reg[i].y + st + height;
  3788.                 rect.width = GetColWidth(g, c);
  3789.                 rect.height = GetRowHeight(g, r);
  3790.                 if (g->grid.singleColScrollMode)
  3791.                     rect.x -= g->grid.singleColScrollPos;
  3792.                 ClipRectToReg(g, &rect, ®[i]);
  3793.                 if (XmLRectIntersect(&xyRect, &rect) != XmLRectOutside)
  3794.                     {
  3795.                     if (!RowColFirstSpan(g, r, c, row, col, 0, True, True))
  3796.                         return 0; /* SUCCESS */
  3797.                     else
  3798.                         return -1;
  3799.                     }
  3800.                 width += GetColWidth(g, c);
  3801.                 }
  3802.             height += GetRowHeight(g, r);
  3803.             }
  3804.         }
  3805.     return -1;
  3806.     }
  3807.  
  3808. static int
  3809. RowColToXY(XmLGridWidget g,
  3810.        int row,
  3811.        int col,
  3812.        Boolean clipped,
  3813.        XRectangle *rect)
  3814.     {
  3815.     XmLGridCell cell;
  3816.     XmLGridCellRefValues *cellValues;
  3817.     GridReg *reg;
  3818.     Dimension st;
  3819.     int i, r, c, off;
  3820.  
  3821.     reg = g->grid.reg;
  3822.     st = g->manager.shadow_thickness;
  3823.     cell = GetCell(g, row, col);
  3824.     if (!cell)
  3825.         return -1;
  3826.     cellValues = XmLGridCellGetRefValues(cell);
  3827.  
  3828.     if (!cellValues) return -1;
  3829.  
  3830.     for (i = 0; i < 9; i++)
  3831.         {
  3832.         if (!reg[i].width || !reg[i].height)
  3833.             continue;
  3834.         if (!(col >= reg[i].col &&
  3835.             col < reg[i].col + reg[i].ncol &&
  3836.             row >= reg[i].row &&
  3837.             row < reg[i].row + reg[i].nrow))
  3838.             continue;
  3839.         off = 0;
  3840.         for (r = reg[i].row; r < row; r++)
  3841.             off += GetRowHeight(g, r);
  3842.         rect->y = reg[i].y + st + off;
  3843.         rect->height = GetRowHeight(g, row);
  3844.         if (cellValues->rowSpan)
  3845.             for (r = row + 1; r <= row + cellValues->rowSpan; r++)
  3846.                 rect->height += GetRowHeight(g, r);
  3847.         off = 0;
  3848.         for (c = reg[i].col; c < col; c++)
  3849.             off += GetColWidth(g, c);
  3850.         rect->x = reg[i].x + st + off;
  3851.         rect->width = GetColWidth(g, col);
  3852.         if (cellValues->columnSpan)
  3853.             for (c = col + 1; c <= col + cellValues->columnSpan; c++)
  3854.                 rect->width += GetColWidth(g, c);
  3855.         if (g->grid.singleColScrollMode)
  3856.             rect->x -= g->grid.singleColScrollPos;
  3857.         if (clipped == True)
  3858.             ClipRectToReg(g, rect, ®[i]);
  3859.         return 0;
  3860.         }
  3861.     return -1;
  3862.     }
  3863.  
  3864. static int
  3865. RowColFirstSpan(XmLGridWidget g,
  3866.         int row,
  3867.         int col,
  3868.         int *firstRow,
  3869.         int *firstCol, 
  3870.         XRectangle *rect,
  3871.         Boolean lookLeft,
  3872.         Boolean lookUp)
  3873.     {
  3874.     XmLGridCell cell;
  3875.     int done;
  3876.  
  3877.     done = 0;
  3878.     while (!done)
  3879.         {
  3880.         cell = GetCell(g, row, col);
  3881.         if (!cell)
  3882.             return -1;
  3883.         if (XmLGridCellInRowSpan(cell) == True)
  3884.             {
  3885.             if (lookUp == True)
  3886.                 {
  3887.                 row--;
  3888.                 if (rect)
  3889.                     rect->y -= GetRowHeight(g, row);
  3890.                 }
  3891.             else
  3892.                 row = -1;
  3893.             if (row < 0)
  3894.                 done = 1;
  3895.             }
  3896.         else if (XmLGridCellInColumnSpan(cell) == True)
  3897.             {
  3898.             if (lookLeft == True)
  3899.                 {
  3900.                 col--;
  3901.                 if (rect)
  3902.                     rect->x -= GetColWidth(g, col);
  3903.                 }
  3904.             else
  3905.                 col = -1;
  3906.             if (col < 0)
  3907.                 done = 1;
  3908.             }
  3909.         else
  3910.             done = 1;
  3911.         }
  3912.     if (row < 0 || col < 0)
  3913.         return -1;
  3914.     *firstRow = row;
  3915.     *firstCol = col;
  3916.     return 0;
  3917.     }
  3918.  
  3919. static void
  3920. RowColSpanRect(XmLGridWidget g,
  3921.            int row,
  3922.            int col,
  3923.            XRectangle *rect)
  3924.     {
  3925.     XmLGridCell cell;
  3926.     XmLGridCellRefValues *cellValues;
  3927.     int r, c;
  3928.  
  3929.     cell = GetCell(g, row, col);
  3930.     cellValues = XmLGridCellGetRefValues(cell);
  3931.     rect->width = 0;
  3932.     rect->height = 0;
  3933.     for (r = row; r <= row + cellValues->rowSpan; r++)
  3934.         rect->height += GetRowHeight(g, r);
  3935.     for (c = col; c <= col + cellValues->columnSpan; c++)
  3936.         rect->width += GetColWidth(g, c);
  3937.     }
  3938.  
  3939. static XmLGridCell
  3940. GetCell(XmLGridWidget g,
  3941.     int row,
  3942.     int col)
  3943.     {
  3944.     XmLGridRow rowp;
  3945.  
  3946.     rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  3947.     if (!rowp)
  3948.         return 0;
  3949.     return (XmLGridCell)XmLArrayGet(XmLGridRowCells(rowp), col);
  3950.     }
  3951.  
  3952. static int
  3953. GetColWidth(XmLGridWidget g,
  3954.         int col)
  3955.     {
  3956.     XmLGridColumn colp;
  3957.  
  3958.     colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col);
  3959.     if (!colp)
  3960.         return 0;
  3961.     return XmLGridColumnWidthInPixels(colp);
  3962.     }
  3963.  
  3964. static int
  3965. GetRowHeight(XmLGridWidget g,
  3966.          int row)
  3967.     {
  3968.     XmLGridRow rowp;
  3969.  
  3970.     rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  3971.     if (!rowp)
  3972.         return 0;
  3973.     return XmLGridRowHeightInPixels(rowp);
  3974.     }
  3975.  
  3976. static int
  3977. ColIsVisible(XmLGridWidget g,
  3978.          int col)
  3979.     {
  3980.     XmLGridColumn c;
  3981.     int i, c1, c2;
  3982.  
  3983.     c = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col);
  3984.     if (!c)
  3985.         {
  3986.         XmLWarning((Widget)g, "ColumnIsVisible() - invalid column");
  3987.         return -1;
  3988.         }
  3989.     if (XmLGridColumnIsHidden(c) == True)
  3990.         return 0;
  3991.     if (g->grid.hsPolicy != XmCONSTANT)
  3992.         return 1;
  3993.     for (i = 0; i < 3; i ++)
  3994.         {
  3995.         c1 = g->grid.reg[i].col;
  3996.         c2 = c1 + g->grid.reg[i].ncol;
  3997.         if (col >= c1 && col < c2)
  3998.             return 1;
  3999.         }
  4000.     return 0;
  4001.     }
  4002.  
  4003. static int
  4004. RowIsVisible(XmLGridWidget g,
  4005.          int row)
  4006.     {
  4007.     XmLGridRow r;
  4008.     int i, r1, r2;
  4009.  
  4010.     r = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  4011.     if (!r)
  4012.         {
  4013.         XmLWarning((Widget)g, "RowIsVisible() - invalid row");
  4014.         return -1;
  4015.         }
  4016.     if (XmLGridRowIsHidden(r) == True)
  4017.         return 0;
  4018.     if (g->grid.vsPolicy != XmCONSTANT)
  4019.         return 1;
  4020.     for (i = 0; i < 9; i += 3)
  4021.         {
  4022.         r1 = g->grid.reg[i].row;
  4023.         r2 = r1 + g->grid.reg[i].nrow;
  4024.         if (row >= r1 && row < r2)
  4025.             return 1;
  4026.         }
  4027.     return 0;
  4028.     }
  4029.  
  4030. static XtGeometryResult
  4031. GeometryManager(Widget w,
  4032.         XtWidgetGeometry *request,
  4033.         XtWidgetGeometry *allow)
  4034.     {
  4035.     if (request->request_mode & CWWidth)
  4036.         w->core.width = request->width;
  4037.     if (request->request_mode & CWHeight)
  4038.         w->core.height = request->height;
  4039.     if (request->request_mode & CWX)
  4040.         w->core.x = request->x;
  4041.     if (request->request_mode & CWY)
  4042.         w->core.y = request->y;
  4043.     if (request->request_mode & CWBorderWidth)
  4044.         w->core.border_width = request->border_width;
  4045.     return XtGeometryYes;
  4046.     }
  4047.  
  4048. static void
  4049. ScrollCB(Widget w,
  4050.      XtPointer clientData,
  4051.      XtPointer callData)
  4052. {
  4053.     XmLGridWidget g;
  4054.     XmScrollBarCallbackStruct *cbs;
  4055.     unsigned char orientation;
  4056.     int visPos;
  4057.  
  4058.     g = (XmLGridWidget)(XtParent(w));
  4059.     cbs = (XmScrollBarCallbackStruct *)callData;
  4060.     visPos = cbs->value;
  4061.     XtVaGetValues(w, XmNorientation, &orientation, NULL);
  4062.     if (orientation == XmHORIZONTAL && g->grid.singleColScrollMode)
  4063.         {
  4064.         g->grid.singleColScrollPos = visPos;
  4065.         DrawArea(g, DrawHScroll, 0, 0);
  4066.         }
  4067.     else if (orientation == XmVERTICAL)
  4068.         {
  4069.         if (visPos == PosToVisPos(g, g->grid.scrollRow, 1))
  4070.             return;
  4071.         g->grid.scrollRow = VisPosToPos(g, visPos, 1);
  4072.         VertLayout(g, 0);
  4073.         DrawArea(g, DrawVScroll, 0, 0);
  4074.         }
  4075.     else
  4076.         {
  4077.         if (visPos == PosToVisPos(g, g->grid.scrollCol, 0))
  4078.             return;
  4079.         g->grid.scrollCol = VisPosToPos(g, visPos, 0);
  4080.         HorizLayout(g, 0);
  4081.         DrawArea(g, DrawHScroll, 0, 0);
  4082.         }
  4083.     }
  4084.  
  4085. static int
  4086. FindNextFocus(XmLGridWidget g,
  4087.           int row,
  4088.           int col,
  4089.           int rowDir,
  4090.           int colDir,
  4091.           int *nextRow,
  4092.           int *nextCol)
  4093.     {
  4094.     int traverse;
  4095.     int hrc, hcc, rc, cc;
  4096.     XmLGridColumn colp;
  4097.     XmLGridRow rowp;
  4098.     XmLGridCell cell;
  4099.  
  4100.     hcc = g->grid.headingColCount;
  4101.     cc = g->grid.colCount;
  4102.     hrc = g->grid.headingRowCount;
  4103.     rc = g->grid.rowCount;
  4104.     if (!rc || !cc)
  4105.         return -1;
  4106.     if (col < hcc)
  4107.         col = hcc;
  4108.     else if (col >= hcc + cc)
  4109.         col = hcc + cc - 1;
  4110.     if (row < hrc)
  4111.         row = hrc;
  4112.     else if (row >= hrc + rc)
  4113.         row = hrc + rc - 1;
  4114.     traverse = 0;
  4115.     while (1)
  4116.         {
  4117.         if (row < hrc || row >= hrc + rc)
  4118.             break;
  4119.         if (col < hcc || col >= hcc + cc)
  4120.             break;
  4121.         rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  4122.         colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col);
  4123.         cell = GetCell(g, row, col);
  4124.         if (cell &&
  4125.             RowPosToType(g, row) == XmCONTENT &&
  4126.             ColPosToType(g, col) == XmCONTENT &&
  4127.             XmLGridCellInRowSpan(cell) == False &&
  4128.             XmLGridCellInColumnSpan(cell) == False &&
  4129.             XmLGridRowIsHidden(rowp) == False &&
  4130.             XmLGridColumnIsHidden(colp) == False)
  4131.             {
  4132.             traverse = 1;
  4133.             break;
  4134.             }
  4135.         if (!rowDir && !colDir)
  4136.             break;
  4137.         row += rowDir;
  4138.         col += colDir;
  4139.         }
  4140.     if (!traverse)
  4141.         return -1;
  4142.     *nextRow = row;
  4143.     *nextCol = col;
  4144.     return 0;
  4145.     }
  4146.  
  4147. static int
  4148. SetFocus(XmLGridWidget g,
  4149.      int row,
  4150.      int col,
  4151.      int rowDir,
  4152.      int colDir)
  4153.     {
  4154.     if (FindNextFocus(g, row, col, rowDir, colDir, &row, &col) == -1)
  4155.         return -1;
  4156.     ChangeFocus(g, row, col);
  4157.     return 0;
  4158.     }
  4159.  
  4160. static void
  4161. ChangeFocus(XmLGridWidget g,
  4162.         int row,
  4163.         int col)
  4164.     {
  4165.     XmLGridCell cell;
  4166.     XmLGridCallbackStruct cbs;
  4167.     int focusRow, focusCol;
  4168.  
  4169.     focusRow = g->grid.focusRow;
  4170.     focusCol = g->grid.focusCol;
  4171.     g->grid.focusRow = row;
  4172.     g->grid.focusCol = col;
  4173.     if (focusRow != -1 && focusCol != -1)
  4174.         {
  4175.         cell = GetCell(g, focusRow, focusCol);
  4176.         if (cell)
  4177.             {
  4178.             if (g->grid.highlightRowMode == True)
  4179.                 DrawArea(g, DrawRow, focusRow, 0);
  4180.             else
  4181.                 DrawArea(g, DrawCell, focusRow, focusCol);
  4182.             cbs.reason = XmCR_CELL_FOCUS_OUT;
  4183.             cbs.columnType = ColPosToType(g, focusCol);
  4184.             cbs.column = ColPosToTypePos(g, cbs.columnType, focusCol);
  4185.             cbs.rowType = RowPosToType(g, focusRow);
  4186.             cbs.row = RowPosToTypePos(g, cbs.rowType, focusRow);
  4187.             XmLGridCellAction(cell, (Widget)g, &cbs);
  4188.             XtCallCallbackList((Widget)g, g->grid.cellFocusCallback,
  4189.                 (XtPointer)&cbs);
  4190.             }
  4191.         }
  4192.     if (row != -1 && col != -1)
  4193.         {
  4194.         cell = GetCell(g, row, col);
  4195.         if (cell)
  4196.             {
  4197.             if (g->grid.highlightRowMode == True)
  4198.                 DrawArea(g, DrawRow, row, 0);
  4199.             else
  4200.                 DrawArea(g, DrawCell, row, col);
  4201.             cbs.reason = XmCR_CELL_FOCUS_IN;
  4202.             cbs.columnType = ColPosToType(g, col);
  4203.             cbs.column = ColPosToTypePos(g, cbs.columnType, col);
  4204.             cbs.rowType = RowPosToType(g, row);
  4205.             cbs.row = RowPosToTypePos(g, cbs.rowType, row);
  4206.             XmLGridCellAction(cell, (Widget)g, &cbs);
  4207.             XtCallCallbackList((Widget)g, g->grid.cellFocusCallback,
  4208.                 (XtPointer)&cbs);
  4209.             }
  4210.         else
  4211.             {
  4212.             if (!XmLArrayGet(g->grid.rowArray, row))
  4213.                 g->grid.focusRow = -1;
  4214.             if (!XmLArrayGet(g->grid.colArray, col))
  4215.                 g->grid.focusCol = -1;
  4216.             }
  4217.         }
  4218.     }
  4219.     
  4220. static void
  4221. MakeColVisible(XmLGridWidget g,
  4222.            int col)
  4223.     {
  4224.     int st, width, scrollWidth, scrollCol, prevScrollCol;
  4225.  
  4226.     if (g->grid.hsPolicy != XmCONSTANT)
  4227.         return;
  4228.     if (col < g->grid.leftFixedCount ||
  4229.         col >= XmLArrayGetCount(g->grid.colArray) - g->grid.rightFixedCount)
  4230.         return;
  4231.     st = g->manager.shadow_thickness;
  4232.     scrollCol = col;
  4233.     if (col > g->grid.scrollCol)
  4234.         {
  4235.         scrollWidth = g->grid.reg[4].width - st * 2;
  4236.         width = 0;
  4237.         while (1)
  4238.             {
  4239.             width += GetColWidth(g, scrollCol);
  4240.             if (width > scrollWidth)
  4241.                 break;
  4242.             if (scrollCol < g->grid.leftFixedCount)
  4243.                 break;
  4244.             scrollCol--;
  4245.             }
  4246.         scrollCol++;
  4247.         if (scrollCol > col)
  4248.             scrollCol = col;
  4249.         /* only scroll if needed */
  4250.         if (scrollCol < g->grid.scrollCol)
  4251.             scrollCol = g->grid.scrollCol;
  4252.         }
  4253.     if (scrollCol == g->grid.scrollCol)
  4254.         return;
  4255.     prevScrollCol = g->grid.scrollCol;
  4256.     g->grid.scrollCol = scrollCol;
  4257.     HorizLayout(g, 0);
  4258.     if (g->grid.scrollCol != prevScrollCol)
  4259.         DrawArea(g, DrawHScroll, 0, 0);
  4260.     }
  4261.  
  4262. static void
  4263. MakeRowVisible(XmLGridWidget g,
  4264.            int row)
  4265.     {
  4266.     int st, height, scrollHeight, scrollRow, prevScrollRow;
  4267.  
  4268.     if (g->grid.vsPolicy != XmCONSTANT)
  4269.         return;
  4270.     if (row < g->grid.topFixedCount ||
  4271.         row >= XmLArrayGetCount(g->grid.rowArray) - g->grid.bottomFixedCount)
  4272.         return;
  4273.     st = g->manager.shadow_thickness;
  4274.     scrollRow = row;
  4275.     if (row > g->grid.scrollRow)
  4276.         {
  4277.         scrollHeight = g->grid.reg[4].height - st * 2;
  4278.         height = 0;
  4279.         while (1)
  4280.             {
  4281.             height += GetRowHeight(g, scrollRow);
  4282.             if (height > scrollHeight)
  4283.                 break;
  4284.             if (scrollRow < g->grid.topFixedCount)
  4285.                 break;
  4286.             scrollRow--;
  4287.             }
  4288.         scrollRow++;
  4289.         if (scrollRow > row)
  4290.             scrollRow = row;
  4291.         /* only scroll if needed */
  4292.         if (scrollRow < g->grid.scrollRow)
  4293.             scrollRow = g->grid.scrollRow;
  4294.         }
  4295.     if (scrollRow == g->grid.scrollRow)
  4296.         return;
  4297.     prevScrollRow = g->grid.scrollRow;
  4298.     g->grid.scrollRow = scrollRow;
  4299.     VertLayout(g, 0);
  4300.     if (g->grid.scrollRow != prevScrollRow)
  4301.         DrawArea(g, DrawVScroll, 0, 0);
  4302.     }
  4303.  
  4304. static void
  4305. TextAction(XmLGridWidget g,
  4306.        int action)
  4307.     {
  4308.     int row, col, reason, ret, isVisible;
  4309.     XRectangle rect;
  4310.     XtTranslations trans;
  4311.     WidgetClass wc;
  4312.     XmLGridCell cellp;
  4313.     XmLGridCallbackStruct cbs;
  4314.  
  4315.     if (!g->grid.text || !XtIsRealized(g->grid.text))
  4316.         return;
  4317.     row = g->grid.focusRow;
  4318.     col = g->grid.focusCol;
  4319.     if (row == -1 || col == -1)
  4320.         return;
  4321.     isVisible = 0;
  4322.     if (RowColToXY(g, row, col, True, &rect) != -1)
  4323.         isVisible = 1;
  4324.     cellp = GetCell(g, row, col);
  4325.     if (!cellp)
  4326.         return;
  4327.     cbs.rowType = XmCONTENT;
  4328.     cbs.row = RowPosToTypePos(g, XmCONTENT, row);
  4329.     cbs.columnType = XmCONTENT;
  4330.     cbs.column = ColPosToTypePos(g, XmCONTENT, col);
  4331.     cbs.clipRect = ▭
  4332.     switch (action)
  4333.         {
  4334.         case TEXT_EDIT:
  4335.         case TEXT_EDIT_INSERT:
  4336.             {
  4337.             if (g->grid.inEdit || !isVisible)    
  4338.                 return;
  4339.             g->grid.inEdit = 1;
  4340.             if (action == TEXT_EDIT)
  4341.                 cbs.reason = XmCR_EDIT_BEGIN;
  4342.             else
  4343.                 cbs.reason = XmCR_EDIT_INSERT;
  4344.             ret = XmLGridCellAction(cellp, (Widget)g, &cbs);
  4345.             if (ret)
  4346.                 {
  4347.                 reason = cbs.reason;
  4348.                 cbs.reason = XmCR_CONF_TEXT;
  4349.                 XmLGridCellAction(cellp, (Widget)g, &cbs);
  4350.                 cbs.reason = reason;
  4351.                 wc = g->grid.text->core.widget_class;
  4352.                 trans = (XtTranslations)wc->core_class.tm_table;
  4353.                 XtVaSetValues(g->grid.text, XmNtranslations, trans, NULL);
  4354.                 XtOverrideTranslations(g->grid.text, g->grid.editTrans);
  4355.                 XtMapWidget(g->grid.text);
  4356.                 g->grid.textHidden = 0;
  4357.                 XtCallCallbackList((Widget)g, g->grid.editCallback,
  4358.                     (XtPointer)&cbs);
  4359.                 }
  4360.             else
  4361.                 g->grid.inEdit = 0;
  4362.             break;
  4363.             }
  4364.         case TEXT_EDIT_CANCEL:
  4365.         case TEXT_EDIT_COMPLETE:
  4366.             {
  4367.             if (!g->grid.inEdit)
  4368.                 return;
  4369.             if (action == TEXT_EDIT_COMPLETE)
  4370.                 cbs.reason = XmCR_EDIT_COMPLETE;
  4371.             else
  4372.                 cbs.reason = XmCR_EDIT_CANCEL;
  4373.             XmLGridCellAction(cellp, (Widget)g, &cbs);
  4374.             wc = g->grid.text->core.widget_class;
  4375.             trans = (XtTranslations)wc->core_class.tm_table;
  4376.             XtVaSetValues(g->grid.text, XmNtranslations, trans, NULL);
  4377.             XtOverrideTranslations(g->grid.text, g->grid.traverseTrans);
  4378.             XtCallCallbackList((Widget)g, g->grid.editCallback,
  4379.                 (XtPointer)&cbs);
  4380.             XmTextSetString(g->grid.text, "");
  4381.             XmTextSetInsertionPosition(g->grid.text, 0);
  4382.             g->grid.inEdit = 0;
  4383.             XtUnmapWidget(g->grid.text);
  4384.             g->grid.textHidden = 1;
  4385.             XtConfigureWidget(g->grid.text, 0, 0, 30, 10, 0);
  4386.             break;
  4387.             }
  4388.         case TEXT_HIDE:
  4389.             {
  4390.             if (g->grid.textHidden || !isVisible)
  4391.                 return;
  4392.             XtUnmapWidget(g->grid.text);
  4393.             g->grid.textHidden = 1;
  4394.             break;
  4395.             }
  4396.         case TEXT_SHOW:
  4397.             {
  4398.             if (!g->grid.textHidden || !g->grid.inEdit || !isVisible)
  4399.                 return;
  4400.             if (rect.width == 0 || rect.height == 0)
  4401.                 TextAction(g, TEXT_EDIT_CANCEL);
  4402.             else
  4403.                 {
  4404.                 cbs.reason = XmCR_CONF_TEXT;
  4405.                 XmLGridCellAction(cellp, (Widget)g, &cbs);
  4406.                 XtMapWidget(g->grid.text);
  4407.                 g->grid.textHidden = 0;
  4408.                 }
  4409.             break;
  4410.             }
  4411.         }
  4412.     }
  4413.  
  4414. /*
  4415.    Getting and Setting Values
  4416. */
  4417.  
  4418. static void
  4419. GetSubValues(Widget w,
  4420.          ArgList args,
  4421.          Cardinal *nargs)
  4422.     {
  4423.     XmLGridWidget g;
  4424.     int i, c;
  4425.     long mask;
  4426.     XmLGridRow row;
  4427.     XmLGridColumn col;
  4428.     XmLGridCell cell;
  4429.  
  4430.     g = (XmLGridWidget)w;
  4431.     row = 0;
  4432.     col = 0;
  4433.     for (i = 0; i < *nargs; i++)
  4434.         {
  4435.         if (!args[i].name)
  4436.             continue;
  4437.         if (!strncmp(args[i].name, "row", 3))
  4438.             {
  4439.             if (!strcmp(args[i].name, XmNrowPtr))
  4440.                 {
  4441.                 row = (XmLGridRow)args[i].value;
  4442.                 continue;
  4443.                 }
  4444.             mask = 0;
  4445.             GetRowValueMask(g, args[i].name, &mask);
  4446.             if (!mask)
  4447.                 continue;
  4448.             if (!row)
  4449.                 {
  4450.                 XmLWarning(w, "GetValues() - invalid row");
  4451.                 continue;
  4452.                 }
  4453.             GetRowValue(g, row, args[i].value, mask);
  4454.             }
  4455.         else if (!strncmp(args[i].name, "column", 6))
  4456.             {
  4457.             if (!strcmp(args[i].name, XmNcolumnPtr))
  4458.                 {
  4459.                 col = (XmLGridColumn)args[i].value;
  4460.                 continue;
  4461.                 }
  4462.             mask = 0;
  4463.             GetColumnValueMask(g, args[i].name, &mask);
  4464.             if (!mask)
  4465.                 continue;
  4466.             if (!col)
  4467.                 {
  4468.                 XmLWarning(w, "GetValues() - invalid column");
  4469.                 continue;
  4470.                 }
  4471.             GetColumnValue(g, col, args[i].value, mask);
  4472.             }
  4473.         else if (!strncmp(args[i].name, "cell", 4))
  4474.             {
  4475.             mask = 0;
  4476.             CellValueGetMask(args[i].name, &mask);
  4477.             if (!mask)
  4478.                 continue;
  4479.             if (!row || !col)
  4480.                 {
  4481.                 XmLWarning(w, "GetValues() - invalid cell");
  4482.                 continue;
  4483.                 }
  4484.             c = XmLGridColumnGetPos(col);
  4485.             cell = (XmLGridCell)XmLArrayGet(XmLGridRowCells(row), c);
  4486.             GetCellValue(cell, args[i].value, mask);
  4487.             }
  4488.         }
  4489.     }
  4490.  
  4491. static void
  4492. SetSubValues(Widget w,
  4493.          ArgList args,
  4494.          Cardinal *nargs)
  4495.     {
  4496.     XmLGridWidget g;
  4497.     XmLGridRow row;
  4498.     XmLGridColumn col;
  4499.     XmLGridCell cell;
  4500.     XmLGridCellRefValues *values, *newValues, *prevValues;
  4501.     XmLArray cellArray;
  4502.     int r, r1, r2, rowsValid;
  4503.     int c, c1, c2, cd1, cd2, colsValid;
  4504.     unsigned char rowType, colType;
  4505.     long rowMask, colMask, cellMask;
  4506.     int i, nRefValues, allCols;
  4507.     int needsHorizResize, needsVertResize;
  4508.     char buf[256];
  4509.  
  4510.     newValues = (XmLGridCellRefValues *)NULL;
  4511.     g = (XmLGridWidget)w;
  4512.     needsHorizResize = 0;
  4513.     needsVertResize = 0;
  4514.     rowMask = 0;
  4515.     colMask = 0;
  4516.     cellMask = 0;
  4517.     for (i = 0; i < *nargs; i++)
  4518.         {
  4519.         if (!args[i].name)
  4520.             continue;
  4521.         if (!strncmp(args[i].name, "row", 3))
  4522.             {
  4523.             if (!strcmp(args[i].name, XmNrowPtr))
  4524.                 XmLWarning(w, "SetValues() - can't use XmNrowPtr");
  4525.             GetRowValueMask(g, args[i].name, &rowMask);
  4526.             }
  4527.         else if (!strncmp(args[i].name, "column", 6))
  4528.             {
  4529.             if (!strcmp(args[i].name, XmNcolumnPtr))
  4530.                 XmLWarning(w, "SetValues() - can't use XmNcolumnPtr");
  4531.             GetColumnValueMask(g, args[i].name, &colMask);
  4532.             }
  4533.         else if (!strncmp(args[i].name, "cell", 4))
  4534.             CellValueGetMask(args[i].name, &cellMask);
  4535.         else if (rowMask || colMask || cellMask)
  4536.             {
  4537.             sprintf(buf, "SetValues() - %s is not a row/column/cell resource",
  4538.                 args[i].name);
  4539.             XmLWarning(w, buf);
  4540.             }
  4541.         }
  4542.     if (rowMask || colMask || cellMask)
  4543.         {
  4544.         if (g->grid.rowType == XmINVALID_TYPE)
  4545.             rowType = XmCONTENT;
  4546.         else
  4547.             rowType = g->grid.rowType;
  4548.         rowsValid = 1;
  4549.         if (g->grid.cellRowRangeStart != -1 && g->grid.cellRowRangeEnd != -1)
  4550.             {
  4551.             r1 = RowTypePosToPos(g, rowType, g->grid.cellRowRangeStart, 0);
  4552.             r2 = RowTypePosToPos(g, rowType, g->grid.cellRowRangeEnd, 0);
  4553.             if (r1 < 0 || r2 < 0 || r1 > r2)
  4554.                 rowsValid = 0;
  4555.             r2++;
  4556.             }
  4557.         else if (g->grid.cellRow != -1)
  4558.             {
  4559.             r1 = RowTypePosToPos(g, rowType, g->grid.cellRow, 0);
  4560.             if (r1 == -1)
  4561.                 rowsValid = 0;
  4562.             r2 = r1 + 1;
  4563.             }
  4564.         else
  4565.             {
  4566.             r1 = RowTypePosToPos(g, rowType, 0, 0);
  4567.             if (r1 == -1)
  4568.                 r1 = 0;
  4569.             r2 = RowTypePosToPos(g, rowType, -1, 1);
  4570.             }
  4571.         if (!rowsValid)
  4572.             {
  4573.             XmLWarning(w, "SetValues() - invalid row(s) specified");
  4574.             r1 = 0;
  4575.             r2 = 0;
  4576.             }
  4577.         if (g->grid.colType == XmINVALID_TYPE)
  4578.             colType = XmCONTENT;
  4579.         else
  4580.             colType = g->grid.colType;
  4581.         colsValid = 1;
  4582.         if (g->grid.cellColRangeStart != -1 && g->grid.cellColRangeEnd != -1)
  4583.             {
  4584.             c1 = ColTypePosToPos(g, colType, g->grid.cellColRangeStart, 0);
  4585.             c2 = ColTypePosToPos(g, colType, g->grid.cellColRangeEnd, 0);
  4586.             if (c1 < 0 || c2 < 0 || c1 > c2)
  4587.                 colsValid = 0;
  4588.             c2++;
  4589.             }
  4590.         else if (g->grid.cellCol != -1)
  4591.             {
  4592.             c1 = ColTypePosToPos(g, colType, g->grid.cellCol, 0);
  4593.             if (c1 == -1)
  4594.                 colsValid = 0;
  4595.             c2 = c1 + 1;
  4596.             }
  4597.         else
  4598.             {
  4599.             c1 = ColTypePosToPos(g, colType, 0, 0);
  4600.             if (c1 == -1)
  4601.                 c1 = 0;
  4602.             c2 = ColTypePosToPos(g, colType, -1, 1);
  4603.             }
  4604.         if (!colsValid)
  4605.             {
  4606.             XmLWarning(w, "SetValues() - invalid column(s) specified");
  4607.             c1 = 0;
  4608.             c2 = 0;
  4609.             }
  4610.         if (g->grid.debugLevel)
  4611.             {
  4612.             fprintf(stderr, "XmLGrid: SetValues for rows %d to %d\n", r1, r2);
  4613.             fprintf(stderr, "XmLGrid: & columns %d to %d\n", c1, c2);
  4614.             }
  4615.         if (rowMask)
  4616.             for (r = r1; r < r2; r += g->grid.rowStep)
  4617.                 {
  4618.                 row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  4619.                 if (!row)
  4620.                     continue;
  4621.                 if (SetRowValues(g, row, rowMask))
  4622.                     needsVertResize = 1;
  4623.                 DrawArea(g, DrawRow, r, 0);
  4624.                 }
  4625.         if (colMask)
  4626.             for (c = c1; c < c2; c += g->grid.colStep)
  4627.                 {
  4628.                 col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  4629.                 if (!col)
  4630.                     continue;
  4631.                 if (SetColumnValues(g, col, colMask))
  4632.                     needsHorizResize = 1;
  4633.                 DrawArea(g, DrawCol, 0, c);
  4634.                 }
  4635.         if (cellMask)
  4636.             SetCellValuesPreprocess(g, cellMask);
  4637.         if (cellMask && g->grid.cellDefaults == True)
  4638.             {
  4639.             allCols = 0;
  4640.             if (g->grid.colType == XmINVALID_TYPE &&
  4641.                 g->grid.cellCol == -1 &&
  4642.                 g->grid.cellColRangeStart == -1 &&
  4643.                 g->grid.cellColRangeEnd == -1 &&
  4644.                 g->grid.colStep == 1)
  4645.                 allCols = 1;
  4646.  
  4647.             if (allCols)
  4648.                 {
  4649.                 /* set cell default values */
  4650.                 newValues = CellRefValuesCreate(g, g->grid.defCellValues);
  4651.                 newValues->refCount = 1;
  4652.                 SetCellRefValues(g, newValues, cellMask);
  4653.                 if (newValues->rowSpan || newValues->columnSpan)
  4654.                     {
  4655.                     newValues->rowSpan = 0;
  4656.                     newValues->columnSpan = 0;
  4657.                     XmLWarning((Widget)g,
  4658.                         "SetValues() - can't set default cell spans");
  4659.                     }
  4660.                 XmLGridCellDerefValues(g->grid.defCellValues);
  4661.                 g->grid.defCellValues = newValues;
  4662.                 cd1 = 0;
  4663.                 cd2 = XmLArrayGetCount(g->grid.colArray);
  4664.                 }
  4665.             else
  4666.                 {
  4667.                 cd1 = c1;
  4668.                 cd2 = c2;
  4669.                 }
  4670.             /* set column cell default values */
  4671.             for (c = cd1; c < cd2; c += g->grid.colStep)
  4672.                 {
  4673.                 col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  4674.                 if (!col)
  4675.                     continue;
  4676.                 if (allCols && !col->grid.defCellValues)
  4677.                     continue;
  4678.                 if (col->grid.defCellValues)
  4679.                     newValues = CellRefValuesCreate(g, col->grid.defCellValues);
  4680.                 else
  4681.                     newValues = CellRefValuesCreate(g, g->grid.defCellValues);
  4682.                 newValues->refCount = 1;
  4683.                 SetCellRefValues(g, newValues, cellMask);
  4684.                 if (newValues->rowSpan || newValues->columnSpan)
  4685.                     {
  4686.                     newValues->rowSpan = 0;
  4687.                     newValues->columnSpan = 0;
  4688.                     XmLWarning((Widget)g,
  4689.                         "SetValues() - can't set default cell spans");
  4690.                     }
  4691.                 if (col->grid.defCellValues)
  4692.                     XmLGridCellDerefValues(col->grid.defCellValues);
  4693.                 col->grid.defCellValues = newValues;
  4694.                 }
  4695.             }
  4696.         else if (cellMask)
  4697.             {
  4698.             /* set cell values */
  4699.             if (SetCellHasRefValues(cellMask))
  4700.                 {
  4701.                 cellArray = XmLArrayNew(0, 0);
  4702.                 XmLArrayAdd(cellArray, -1, (r2 - r1) * (c2 - c1));
  4703.                 nRefValues = 0;
  4704.                 for (r = r1; r < r2; r += g->grid.rowStep)
  4705.                     for (c = c1; c < c2; c += g->grid.colStep)
  4706.                         {
  4707.                         cell = GetCell(g, r, c);
  4708.                         if (!cell)
  4709.                             continue;
  4710.                         SetCellRefValuesPreprocess(g, r, c, cell, cellMask);
  4711.                         XmLArraySet(cellArray, nRefValues, cell);
  4712.                         nRefValues++;
  4713.                         }
  4714.                 XmLArraySort(cellArray, SetCellRefValuesCompare,
  4715.                     (void *)&cellMask, 0, nRefValues);
  4716.                 prevValues = 0;
  4717.                 for (i = 0; i < nRefValues; i++)
  4718.                     {
  4719.                     cell = (XmLGridCell)XmLArrayGet(cellArray, i);
  4720.                     values = XmLGridCellGetRefValues(cell);
  4721.                     if (values != prevValues)
  4722.                         {
  4723.                         newValues = CellRefValuesCreate(g, values);
  4724.                         SetCellRefValues(g, newValues, cellMask);
  4725.                         }
  4726.                     XmLGridCellSetRefValues(cell, newValues);
  4727.                     prevValues = values;
  4728.                     }
  4729.                 XmLArrayFree(cellArray);
  4730.                 }
  4731.             for (r = r1; r < r2; r += g->grid.rowStep)
  4732.                 for (c = c1; c < c2; c += g->grid.colStep)
  4733.                     {
  4734.                     row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  4735.                     col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  4736.                     cell = GetCell(g, r, c);
  4737.                     if (!row || !col || !cell)
  4738.                         continue;
  4739.                     if (SetCellValuesResize(g, row, col, cell, cellMask))
  4740.                         {
  4741.                         needsHorizResize = 1;
  4742.                         needsVertResize = 1;
  4743.                         }
  4744.                     SetCellValues(g, cell, cellMask);
  4745.                     if (!needsHorizResize && !needsVertResize)
  4746.                         DrawArea(g, DrawCell, r, c);
  4747.                     }
  4748.             }
  4749.         }
  4750.     if (needsHorizResize)
  4751.         HorizLayout(g, 1);
  4752.     if (needsVertResize)
  4753.         VertLayout(g, 1);
  4754.     if (needsHorizResize || needsVertResize)
  4755.         DrawArea(g, DrawAll, 0, 0);
  4756.     g->grid.rowType = XmINVALID_TYPE;
  4757.     g->grid.colType = XmINVALID_TYPE;
  4758.     g->grid.rowStep = 1;
  4759.     g->grid.colStep = 1;
  4760.     g->grid.cellRow = -1;
  4761.     g->grid.cellRowRangeStart = -1;
  4762.     g->grid.cellRowRangeEnd = -1;
  4763.     g->grid.cellCol = -1;
  4764.     g->grid.cellColRangeStart = -1;
  4765.     g->grid.cellColRangeEnd = -1;
  4766.     g->grid.cellDefaults = False;
  4767.     }
  4768.  
  4769. static Boolean
  4770. SetValues(Widget curW,
  4771.       Widget reqW,
  4772.       Widget newW,
  4773.       ArgList args,
  4774.       Cardinal *nargs)
  4775.     {
  4776.     XmLGridWidget g, cur;
  4777.     int hc, c, fc, hr, r, fr;
  4778.     int tfc, bfc, lfc, rfc;
  4779.     int needsVertLayout, needsHorizLayout, needsRedraw;
  4780.     XmLGridCellRefValues *cellValues;
  4781.  
  4782.     g = (XmLGridWidget)newW;
  4783.     cur = (XmLGridWidget)curW;
  4784.     needsRedraw = 0;
  4785.     needsVertLayout = 0;
  4786.     needsHorizLayout = 0;
  4787.  
  4788. #define NE(value) (g->value != cur->value)
  4789.     if (NE(grid.cScrollCol))
  4790.         {
  4791.         g->grid.scrollCol = g->grid.cScrollCol + g->grid.headingColCount;
  4792.         needsHorizLayout = 1;
  4793.         needsRedraw = 1;
  4794.         }
  4795.     if (NE(grid.cScrollRow))
  4796.         {
  4797.         g->grid.scrollRow = g->grid.cScrollRow + g->grid.headingRowCount;
  4798.         needsVertLayout = 1;
  4799.         needsRedraw = 1;
  4800.         }
  4801.     if (NE(grid.bottomFixedCount) ||
  4802.         NE(grid.bottomFixedMargin) ||
  4803.         NE(grid.topFixedCount) ||
  4804.         NE(grid.topFixedMargin) ||
  4805.         NE(grid.vsbDisplayPolicy))
  4806.         {
  4807.         needsVertLayout = 1;
  4808.         needsRedraw = 1;
  4809.         }
  4810.     if (NE(grid.leftFixedCount) ||
  4811.         NE(grid.leftFixedMargin) ||
  4812.         NE(grid.rightFixedCount) ||
  4813.         NE(grid.rightFixedMargin) ||
  4814.         NE(grid.hsbDisplayPolicy))
  4815.         {
  4816.         needsHorizLayout = 1;
  4817.         needsRedraw = 1;
  4818.         }
  4819.     if (NE(grid.layoutFrozen))
  4820.         {
  4821.         if (g->grid.layoutFrozen == False)
  4822.             {
  4823.             if (g->grid.needsVertLayout == True)
  4824.                 {
  4825.                 needsVertLayout = 1;
  4826.                 g->grid.needsVertLayout = False;
  4827.                 }
  4828.             if (g->grid.needsHorizLayout == True)
  4829.                 {
  4830.                 needsHorizLayout = 1;
  4831.                 g->grid.needsHorizLayout = False;
  4832.                 }
  4833.             needsRedraw = 1;
  4834.             }
  4835.         }
  4836.     if (NE(grid.scrollBarMargin) ||
  4837.         NE(manager.shadow_thickness) ||
  4838.         NE(core.border_width) ||
  4839.         NE(grid.vsPolicy) ||
  4840.         NE(grid.hsPolicy))
  4841.         {
  4842.         needsVertLayout = 1;
  4843.         needsHorizLayout = 1;
  4844.         needsRedraw = 1;
  4845.         }
  4846.     if (NE(grid.blankBg) ||
  4847.         NE(grid.highlightThickness) ||
  4848.         NE(grid.selectBg) ||
  4849.         NE(grid.selectFg) ||
  4850.         NE(grid.toggleTopColor) ||
  4851.         NE(grid.toggleBotColor) ||
  4852.         NE(grid.shadowRegions) ||
  4853.         NE(grid.shadowType))
  4854.         needsRedraw = 1;
  4855.     if (NE(grid.fontList))
  4856.         {
  4857.         XmFontListFree(cur->grid.fontList);
  4858.         CopyFontList(g);
  4859.         cellValues = CellRefValuesCreate(g, g->grid.defCellValues);
  4860.         cellValues->refCount = 1;
  4861.         XmFontListFree(cellValues->fontList);
  4862.         cellValues->fontList = XmFontListCopy(g->grid.fontList);
  4863.         XmLFontListGetDimensions(cellValues->fontList,
  4864.             &cellValues->fontWidth, &cellValues->fontHeight,
  4865.             g->grid.useAvgWidth);
  4866.         XmLGridCellDerefValues(g->grid.defCellValues);
  4867.         g->grid.defCellValues = cellValues;
  4868.         }
  4869.     if (NE(grid.allowDrop))
  4870.         DropRegister(g, g->grid.allowDrop); 
  4871.     if (g->grid.rowStep < 1)
  4872.         {
  4873.         XmLWarning(newW, "SetValues() - rowStep can't be < 1");
  4874.         g->grid.rowStep = 1;
  4875.         }
  4876.     if (g->grid.colStep < 1)
  4877.         {
  4878.         XmLWarning(newW, "SetValues() - colStep can't be < 1");
  4879.         g->grid.colStep = 1;
  4880.         }
  4881.     if (NE(grid.hsb) ||
  4882.         NE(grid.vsb) ||
  4883.         NE(grid.text))
  4884.         {
  4885.         XmLWarning(newW, "SetValues() - child Widgets are read-only");
  4886.         g->grid.hsb = cur->grid.hsb;
  4887.         g->grid.vsb = cur->grid.vsb;
  4888.         g->grid.text = cur->grid.text;
  4889.         }
  4890.     if (NE(grid.useTextWidget))
  4891.         {
  4892.         XmLWarning(newW, "SetValues() - can't set use of text widget");
  4893.         g->grid.useTextWidget = cur->grid.useTextWidget;
  4894.         }
  4895.     if (NE(grid.hiddenColCount) ||
  4896.         NE(grid.hiddenRowCount))
  4897.         {
  4898.         XmLWarning(newW, "SetValues() - can't set hidden rows or columns");
  4899.         g->grid.hiddenColCount = cur->grid.hiddenColCount;
  4900.         g->grid.hiddenRowCount = cur->grid.hiddenRowCount;
  4901.         }
  4902.  
  4903.     /* store fixed counts, add/removing rows/columns can change these */
  4904.     tfc = -1;
  4905.     bfc = -1;
  4906.     lfc = -1;
  4907.     rfc = -1;
  4908.     if (NE(grid.topFixedCount))
  4909.         tfc = g->grid.topFixedCount;
  4910.     if (NE(grid.bottomFixedCount))
  4911.         bfc = g->grid.bottomFixedCount;
  4912.     if (NE(grid.leftFixedCount))
  4913.         lfc = g->grid.leftFixedCount;
  4914.     if (NE(grid.rightFixedCount))
  4915.         rfc = g->grid.rightFixedCount;
  4916.     g->grid.topFixedCount = cur->grid.topFixedCount;
  4917.     g->grid.bottomFixedCount = cur->grid.bottomFixedCount;
  4918.     g->grid.leftFixedCount = cur->grid.leftFixedCount;
  4919.     g->grid.rightFixedCount = cur->grid.rightFixedCount;
  4920.  
  4921.     hc = g->grid.headingColCount - cur->grid.headingColCount;
  4922.     c = g->grid.colCount - cur->grid.colCount;
  4923.     fc = g->grid.footerColCount - cur->grid.footerColCount;
  4924.     hr = g->grid.headingRowCount - cur->grid.headingRowCount;
  4925.     r = g->grid.rowCount - cur->grid.rowCount;
  4926.     fr = g->grid.footerRowCount - cur->grid.footerRowCount;
  4927.     g->grid.headingColCount = cur->grid.headingColCount;
  4928.     g->grid.colCount = cur->grid.colCount;
  4929.     g->grid.footerColCount = cur->grid.footerColCount;
  4930.     g->grid.headingRowCount = cur->grid.headingRowCount;
  4931.     g->grid.rowCount = cur->grid.rowCount;
  4932.     g->grid.footerRowCount = cur->grid.footerRowCount;
  4933.     if (hc > 0)
  4934.         XmLGridAddColumns((Widget)g, XmHEADING, -1, hc);
  4935.     if (hc < 0)
  4936.         XmLGridDeleteColumns((Widget)g, XmHEADING,
  4937.             g->grid.headingColCount + hc, -(hc));
  4938.     if (c > 0)
  4939.         XmLGridAddColumns((Widget)g, XmCONTENT, -1, c);
  4940.     if (c < 0)
  4941.         XmLGridDeleteColumns((Widget)g, XmCONTENT,
  4942.             g->grid.colCount + c, -(c));
  4943.     if (fc > 0)
  4944.         XmLGridAddColumns((Widget)g, XmFOOTER, -1, fc);
  4945.     if (fc < 0)
  4946.         XmLGridDeleteColumns((Widget)g, XmFOOTER,
  4947.             g->grid.footerColCount + fc, -(fc));
  4948.     if (hr > 0)
  4949.         XmLGridAddRows((Widget)g, XmHEADING, -1, hr);
  4950.     if (hr < 0)
  4951.         XmLGridDeleteRows((Widget)g, XmHEADING,
  4952.             g->grid.headingRowCount + hr, -(hr));
  4953.     if (r > 0)
  4954.         XmLGridAddRows((Widget)g, XmCONTENT, -1, r);
  4955.     if (r < 0)
  4956.         XmLGridDeleteRows((Widget)g, XmCONTENT,
  4957.             g->grid.rowCount + r, -(r));
  4958.     if (fr > 0)
  4959.         XmLGridAddRows((Widget)g, XmFOOTER, -1, fr);
  4960.     if (fr < 0)
  4961.         XmLGridDeleteRows((Widget)g, XmFOOTER,
  4962.             g->grid.footerRowCount + fr, -(fr));
  4963.  
  4964.     /* restore fixed counts if user specified */
  4965.     if (tfc != -1)
  4966.         g->grid.topFixedCount = tfc;
  4967.     if (bfc != -1)
  4968.         g->grid.bottomFixedCount = bfc;
  4969.     if (lfc != -1)
  4970.         g->grid.leftFixedCount = lfc;
  4971.     if (rfc != -1)
  4972.         g->grid.rightFixedCount = rfc;
  4973.  
  4974.     if (g->grid.topFixedCount < g->grid.headingRowCount)
  4975.         {
  4976.         XmLWarning(newW,
  4977.             "SetValues() - can't set topFixedCount < headingRowCount");
  4978.         g->grid.topFixedCount = cur->grid.topFixedCount;
  4979.         }
  4980.     if (g->grid.bottomFixedCount < g->grid.footerRowCount)
  4981.         {
  4982.         XmLWarning(newW,
  4983.             "SetValues() - can't set bottomFixedCount < footerRowCount");
  4984.         g->grid.bottomFixedCount = cur->grid.bottomFixedCount;
  4985.         }
  4986.     if (g->grid.leftFixedCount < g->grid.headingColCount)
  4987.         {
  4988.         XmLWarning(newW,
  4989.             "SetValues() - can't set leftFixedCount < headingColumnCount");
  4990.         g->grid.leftFixedCount = cur->grid.leftFixedCount;
  4991.         }
  4992.     if (g->grid.rightFixedCount < g->grid.footerColCount)
  4993.         {
  4994.         XmLWarning(newW,
  4995.             "SetValues() - can't set rightFixedCount < footerColumnCount");
  4996.         g->grid.rightFixedCount = cur->grid.rightFixedCount;
  4997.         }
  4998.  
  4999.     if (NE(grid.simpleHeadings))
  5000.         {
  5001.         if (cur->grid.simpleHeadings)
  5002.             free((char *)cur->grid.simpleHeadings);
  5003.         if (g->grid.simpleHeadings)
  5004.             {
  5005.             g->grid.simpleHeadings = (char *)strdup(g->grid.simpleHeadings);
  5006.             SetSimpleHeadings(g, g->grid.simpleHeadings);
  5007.             }
  5008.         }
  5009.     if (NE(grid.simpleWidths))
  5010.         {
  5011.         if (cur->grid.simpleWidths)
  5012.             free((char *)cur->grid.simpleWidths);
  5013.         if (g->grid.simpleWidths)
  5014.             {
  5015.             g->grid.simpleWidths = (char *)strdup(g->grid.simpleWidths);
  5016.             SetSimpleWidths(g, g->grid.simpleWidths);
  5017.             }
  5018.         }
  5019.     if (NE(grid.visibleRows))
  5020.         {
  5021.         ApplyVisibleRows(g);
  5022.         needsVertLayout = 1;
  5023.         needsRedraw = 1;
  5024.         }
  5025.     if (NE(grid.visibleCols))
  5026.         {
  5027.         ApplyVisibleCols(g);
  5028.         needsHorizLayout = 1;
  5029.         needsRedraw = 1;
  5030.         }
  5031.  
  5032.     /* for the hidden columns stuff */
  5033.     if (NE(grid.showHideButton))
  5034.         {
  5035.         if (g->grid.showHideButton)
  5036.             {
  5037.             g->grid.hideButton = XtVaCreateWidget(
  5038.                 "hide", xmDrawnButtonWidgetClass,
  5039.             (Widget)g, XmNhighlightThickness, 0,
  5040.                 XmNshadowThickness, 1,
  5041.             XmNtraversalOn, False,
  5042.                   XmNbackground, g->core.background_pixel,
  5043.                 XmNforeground, g->manager.foreground,
  5044.                 XmNtopShadowColor, g->manager.top_shadow_color,
  5045.                 XmNbottomShadowColor, g->manager.bottom_shadow_color,
  5046.             NULL);
  5047.  
  5048.             XmLDrawnButtonSetType(g->grid.hideButton,
  5049.                           XmDRAWNB_DOUBLEARROW,
  5050.                           XmDRAWNB_RIGHT);
  5051.             }
  5052.         else 
  5053.             {
  5054.             XtDestroyWidget(g->grid.hideButton);
  5055.             }
  5056.  
  5057.         needsVertLayout = 1;
  5058.         needsHorizLayout = 1;
  5059.         needsRedraw = 1;
  5060.         }
  5061. #undef NE
  5062.  
  5063.     SetSubValues(newW, args, nargs);
  5064.  
  5065.     if (needsVertLayout)
  5066.         VertLayout(g, 1);
  5067.     if (needsHorizLayout)
  5068.         HorizLayout(g, 1);
  5069.     if (needsRedraw)
  5070.         DrawArea(g, DrawAll, 0, 0);
  5071.     return (False);
  5072.     }
  5073.  
  5074. static void
  5075. CopyFontList(XmLGridWidget g)
  5076.     {
  5077.     if (!g->grid.fontList)
  5078.         g->grid.fontList = XmLFontListCopyDefault((Widget)g);
  5079.     else
  5080.         g->grid.fontList = XmFontListCopy(g->grid.fontList);
  5081.     if (!g->grid.fontList)
  5082.         XmLWarning((Widget)g, "- fatal error - font list NULL");
  5083.     }
  5084.  
  5085. static Boolean
  5086. CvtStringToSizePolicy(Display *dpy,
  5087.               XrmValuePtr args,
  5088.               Cardinal *narg,
  5089.               XrmValuePtr fromVal,
  5090.               XrmValuePtr toVal,
  5091.               XtPointer *data)
  5092.     {
  5093.     static XmLStringToUCharMap map[] =
  5094.         {
  5095.         { "CONSTANT", XmCONSTANT },
  5096.         { "VARIABLE", XmVARIABLE },
  5097.         { 0, 0 },
  5098.         };
  5099.  
  5100.     return XmLCvtStringToUChar(dpy, "XmRGridSizePolicy", map, fromVal, toVal);
  5101.     }
  5102.  
  5103. static Boolean
  5104. CvtStringToRowColType(Display *dpy,
  5105.               XrmValuePtr args,
  5106.               Cardinal *narg,
  5107.               XrmValuePtr fromVal,
  5108.               XrmValuePtr toVal,
  5109.               XtPointer *data)
  5110.     {
  5111.     static XmLStringToUCharMap map[] =
  5112.         {
  5113.         { "HEADING",    XmHEADING },
  5114.         { "CONTENT",    XmCONTENT },
  5115.         { "FOOTER",     XmFOOTER },
  5116.         { "ALL_TYPES",  XmALL_TYPES },
  5117.         { 0, 0 },
  5118.         };
  5119.  
  5120.     return XmLCvtStringToUChar(dpy, "XmRRowColType", map, fromVal, toVal);
  5121.     }
  5122.  
  5123. static Boolean
  5124. CvtStringToSelectionPolicy(Display *dpy,
  5125.                XrmValuePtr args,
  5126.                Cardinal *narg,
  5127.                XrmValuePtr fromVal,
  5128.                XrmValuePtr toVal,
  5129.                XtPointer *data)
  5130.     {
  5131.     static XmLStringToUCharMap map[] =
  5132.         {
  5133.         { "SELECT_NONE", XmSELECT_NONE },
  5134.         { "SELECT_SINGLE_ROW", XmSELECT_SINGLE_ROW },
  5135.         { "SELECT_BROWSE_ROW", XmSELECT_BROWSE_ROW },
  5136.         { "SELECT_MULTIPLE_ROW", XmSELECT_MULTIPLE_ROW },
  5137.         { "SELECT_CELL", XmSELECT_CELL },
  5138.         { 0, 0 },
  5139.         };
  5140.  
  5141.     return XmLCvtStringToUChar(dpy, "XmRGridSelectionPolicy", map,
  5142.         fromVal, toVal);
  5143.     }
  5144.  
  5145. static Boolean
  5146. CvtStringToCellAlignment(Display *dpy,
  5147.              XrmValuePtr args,
  5148.              Cardinal *narg,
  5149.              XrmValuePtr fromVal,
  5150.              XrmValuePtr toVal,
  5151.              XtPointer *data)
  5152.     {
  5153.     static XmLStringToUCharMap map[] =
  5154.         {
  5155.         { "ALIGNMENT_LEFT", XmALIGNMENT_LEFT },
  5156.         { "ALIGNMENT_CENTER", XmALIGNMENT_CENTER },
  5157.         { "ALIGNMENT_RIGHT", XmALIGNMENT_RIGHT },
  5158.         { "ALIGNMENT_TOP_LEFT", XmALIGNMENT_TOP_LEFT },
  5159.         { "ALIGNMENT_TOP", XmALIGNMENT_TOP },
  5160.         { "ALIGNMENT_TOP_RIGHT", XmALIGNMENT_TOP_RIGHT },
  5161.         { "ALIGNMENT_BOTTOM_LEFT", XmALIGNMENT_BOTTOM_LEFT },
  5162.         { "ALIGNMENT_BOTTOM", XmALIGNMENT_BOTTOM },
  5163.         { "ALIGNMENT_BOTTOM_RIGHT", XmALIGNMENT_BOTTOM_RIGHT },
  5164.         { 0, 0 },
  5165.         };
  5166.  
  5167.     return XmLCvtStringToUChar(dpy, "XmRGridCellAlignment", map,
  5168.         fromVal, toVal);
  5169.     }
  5170.  
  5171. static Boolean
  5172. CvtStringToCellBorderType(Display *dpy,
  5173.               XrmValuePtr args,
  5174.               Cardinal *narg,
  5175.               XrmValuePtr fromVal,
  5176.               XrmValuePtr toVal,
  5177.               XtPointer *data)
  5178.     {
  5179.     static XmLStringToUCharMap map[] =
  5180.         {
  5181.         { "BORDER_NONE", XmBORDER_NONE },
  5182.         { "BORDER_LINE", XmBORDER_LINE },
  5183.         { "BORDER_DASH", XmBORDER_DASH },
  5184.         { 0, 0 },
  5185.         };
  5186.  
  5187.     return XmLCvtStringToUChar(dpy, "XmRGridCellBorderType", map,
  5188.         fromVal, toVal);
  5189.     }
  5190.  
  5191. static Boolean
  5192. CvtStringToCellType(Display *dpy,
  5193.             XrmValuePtr args,
  5194.             Cardinal *narg,
  5195.             XrmValuePtr fromVal,
  5196.             XrmValuePtr toVal,
  5197.             XtPointer *data)
  5198.     {
  5199.     static XmLStringToUCharMap map[] =
  5200.         {
  5201.         { "ICON_CELL",   XmICON_CELL },
  5202.         { "STRING_CELL", XmSTRING_CELL },
  5203.         { "PIXMAP_CELL", XmPIXMAP_CELL },
  5204.         { "TOGGLE_CELL", XmTOGGLE_CELL },
  5205.         { 0, 0 },
  5206.         };
  5207.  
  5208.     return XmLCvtStringToUChar(dpy, "XmRGridCellType", map, fromVal, toVal);
  5209.     }
  5210.  
  5211. static void
  5212. SetSimpleHeadings(XmLGridWidget g,
  5213.           char *data)
  5214.     {
  5215.     char *c;
  5216.     int n, count;
  5217.  
  5218.     if (!data || !*data)
  5219.         return;
  5220.     c = data;
  5221.     n = 1;
  5222.     while (*c)
  5223.         {
  5224.         if (*c == '|')
  5225.             n++;
  5226.         c++;
  5227.         }
  5228.     count = XmLArrayGetCount(g->grid.colArray);
  5229.     if (n > count)
  5230.         {
  5231.         XmLWarning((Widget)g,
  5232.             "SetSimpleHeadings() - headings given for non-existing columns");
  5233.         return;
  5234.         }
  5235.     if (g->grid.headingRowCount < 1)
  5236.         {
  5237.         XmLWarning((Widget)g, "SetSimpleHeadings() - no heading row exists");
  5238.         return;
  5239.         }
  5240.     XmLGridSetStrings((Widget)g, data);
  5241.     }
  5242.  
  5243. static void
  5244. SetSimpleWidths(XmLGridWidget g,
  5245.         char *data)
  5246.     {
  5247.     XmLGridColumn colp;
  5248.     int i, n, colCount, valid;
  5249.     Dimension prevWidth;
  5250.     unsigned char prevSizePolicy;
  5251.     long mask;
  5252.     struct WidthRec
  5253.         {
  5254.         Dimension width;
  5255.         unsigned char sizePolicy;
  5256.         } *widths;
  5257.  
  5258.     if (!data)
  5259.         return;
  5260.     i = ((int)strlen(data) / 2) + 1;
  5261.     widths = (struct WidthRec *)malloc(i * sizeof(struct WidthRec));
  5262.     valid = 1;
  5263.     n = 0;
  5264.     while (*data)
  5265.         {
  5266.         if (*data >= '0' && *data <= '9')
  5267.             {    
  5268.             widths[n].width = atoi(data);
  5269.             while (*data >= '0' && *data <= '9')
  5270.                 data++;
  5271.             }
  5272.         else
  5273.             {
  5274.             valid = 0;
  5275.             break;
  5276.             }
  5277.         if (*data == 'c' || *data == 'C')
  5278.             {
  5279.             widths[n].sizePolicy = XmVARIABLE;
  5280.             data++;
  5281.             }
  5282.         else if (*data == 'p' || *data == 'P')
  5283.             {
  5284.             widths[n].sizePolicy = XmCONSTANT;
  5285.             data++;
  5286.             }
  5287.         else
  5288.             {
  5289.             valid = 0;
  5290.             break;
  5291.             }
  5292.         while (*data == ' ')
  5293.             data++;
  5294.         n++;
  5295.         }
  5296.     if (!valid)
  5297.         {
  5298.         free((char *)widths);
  5299.         XmLWarning((Widget)g, "SetSimpleWidths() - invalid widths string");
  5300.         return;
  5301.         }
  5302.     colCount = XmLArrayGetCount(g->grid.colArray);
  5303.     if (n > colCount)
  5304.         {
  5305.         free((char *)widths);
  5306.         XmLWarning((Widget)g,
  5307.             "SetSimpleWidths() - widths given for non-existing columns");
  5308.         return;
  5309.         }
  5310.     prevWidth = g->grid.colWidth;
  5311.     prevSizePolicy = g->grid.colSizePolicy;
  5312.     for (i = 0; i < n; i++)
  5313.         {
  5314.         colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  5315.         if (!colp)
  5316.             continue;
  5317.         GetColumnValueMask(g, XmNcolumnWidth, &mask);
  5318.         GetColumnValueMask(g, XmNcolumnSizePolicy, &mask);
  5319.         g->grid.colWidth = widths[i].width;
  5320.         g->grid.colSizePolicy = widths[i].sizePolicy;
  5321.         SetColumnValues(g, colp, mask);
  5322.         }
  5323.     free((char *)widths);
  5324.     g->grid.colWidth = prevWidth;
  5325.     g->grid.colSizePolicy = prevSizePolicy;
  5326.     HorizLayout(g, 1);
  5327.     DrawArea(g, DrawAll, 0, 0);
  5328.     }
  5329.  
  5330. /*
  5331.    Getting and Setting Row Values
  5332. */
  5333.  
  5334. static void
  5335. GetRowValueMask(XmLGridWidget g,
  5336.         char *s,
  5337.         long *mask)
  5338.     {
  5339.     XmLGridClassPartOfWidget(g).getRowValueMaskProc(g, s, mask);
  5340.     }
  5341.  
  5342. /* Only to be called through Grid class */
  5343. static void 
  5344. _GetRowValueMask(XmLGridWidget g,
  5345.          char *s,
  5346.          long *mask)
  5347.     {
  5348.     static XrmQuark qHeight, qSizePolicy, qUserData;
  5349.     static int quarksValid = 0;
  5350.     XrmQuark q;
  5351.  
  5352.     if (!quarksValid)
  5353.         {
  5354.         qHeight = XrmStringToQuark(XmNrowHeight);
  5355.         qSizePolicy = XrmStringToQuark(XmNrowSizePolicy);
  5356.         qUserData = XrmStringToQuark(XmNrowUserData);
  5357.         quarksValid = 1;
  5358.         }
  5359.     q = XrmStringToQuark(s);
  5360.     if (q == qHeight)
  5361.             *mask |= XmLGridRowHeight;
  5362.     else if (q == qSizePolicy)
  5363.             *mask |= XmLGridRowSizePolicy;
  5364.     else if (q == qUserData)
  5365.             *mask |= XmLGridRowUserData;
  5366.     }
  5367.  
  5368. static void
  5369. GetRowValue(XmLGridWidget g,
  5370.         XmLGridRow row,
  5371.         XtArgVal value,
  5372.         long mask)
  5373.     {
  5374.     XmLGridClassPartOfWidget(g).getRowValueProc(g, row, value, mask);
  5375.     }
  5376.  
  5377. /* Only to be called through Grid class */
  5378. static void 
  5379. _GetRowValue(XmLGridWidget g,
  5380.          XmLGridRow row,
  5381.          XtArgVal value,
  5382.          long mask)
  5383.     {
  5384.     switch (mask)
  5385.         {
  5386.         case XmLGridRowHeight:
  5387.             *((Dimension *)value) = row->grid.height; 
  5388.             break;
  5389.         case XmLGridRowSizePolicy:
  5390.             *((unsigned char *)value) = row->grid.sizePolicy; 
  5391.             break;
  5392.         case XmLGridRowUserData:
  5393.             *((XtPointer *)value) = (XtPointer)row->grid.userData;
  5394.             break;
  5395.         }
  5396.     }
  5397.  
  5398. static int
  5399. SetRowValues(XmLGridWidget g,
  5400.          XmLGridRow row,
  5401.          long mask)
  5402.     {
  5403.     return XmLGridClassPartOfWidget(g).setRowValuesProc(g, row, mask);
  5404.     }
  5405.  
  5406. /* Only to be called through Grid class */
  5407. static int 
  5408. _SetRowValues(XmLGridWidget g, XmLGridRow row, long mask)
  5409.     {
  5410.     int needsResize = 0, visible = 0;
  5411.     Boolean newIsHidden;
  5412.  
  5413.     if (mask & XmLGridRowHeight || mask & XmLGridRowSizePolicy)
  5414.         {
  5415.         visible = RowIsVisible(g, XmLGridRowGetPos(row));
  5416.         XmLGridRowHeightChanged(row);
  5417.         }
  5418.     if (mask & XmLGridRowHeight)
  5419.         {
  5420.         if (g->grid.rowHeight > 0)
  5421.             newIsHidden = False;
  5422.         else
  5423.             newIsHidden = True;
  5424.         if (XmLGridRowIsHidden(row) != newIsHidden)
  5425.             {
  5426.             if (newIsHidden == True)
  5427.                 g->grid.hiddenRowCount++;
  5428.             else
  5429.                 g->grid.hiddenRowCount--;
  5430.             VisPosChanged(g, 1);
  5431.             needsResize = 1;
  5432.             }
  5433.         if (visible && !g->grid.inResize)
  5434.             needsResize = 1;
  5435.         row->grid.height = g->grid.rowHeight;
  5436.         }
  5437.     if (mask & XmLGridRowSizePolicy)
  5438.         {
  5439.         row->grid.sizePolicy = g->grid.rowSizePolicy;
  5440.         if (visible && !g->grid.inResize)
  5441.             needsResize = 1;
  5442.         }
  5443.     if (mask & XmLGridRowUserData)
  5444.         row->grid.userData = g->grid.rowUserData;
  5445.     return needsResize;
  5446.     }
  5447.  
  5448. /*
  5449.    Getting and Setting Column Values
  5450. */
  5451.  
  5452. static void
  5453. GetColumnValueMask(XmLGridWidget g,
  5454.            char *s,
  5455.            long *mask)
  5456.     {
  5457.     XmLGridClassPartOfWidget(g).getColumnValueMaskProc(g, s, mask);
  5458.     }
  5459.  
  5460. /* Only to be called through Grid class */
  5461. static void 
  5462. _GetColumnValueMask(XmLGridWidget g,
  5463.             char *s,
  5464.             long *mask)
  5465.     {
  5466.     static XrmQuark qWidth, qSizePolicy, qUserData, qResizable;
  5467.     static int quarksValid = 0;
  5468.     XrmQuark q;
  5469.  
  5470.     if (!quarksValid)
  5471.         {
  5472.         qWidth = XrmStringToQuark(XmNcolumnWidth);
  5473.         qSizePolicy = XrmStringToQuark(XmNcolumnSizePolicy);
  5474.         qUserData = XrmStringToQuark(XmNcolumnUserData);
  5475.         qResizable = XrmStringToQuark(XmNcolumnResizable);
  5476.         quarksValid = 1;
  5477.         }
  5478.     q = XrmStringToQuark(s);
  5479.     if (q == qWidth)
  5480.             *mask |= XmLGridColumnWidth;
  5481.     else if (q == qSizePolicy)
  5482.             *mask |= XmLGridColumnSizePolicy;
  5483.     else if (q == qUserData)
  5484.             *mask |= XmLGridColumnUserData;
  5485.     else if (q == qResizable)
  5486.             *mask |= XmLGridColumnResizable;
  5487.     }
  5488.  
  5489. static void
  5490. GetColumnValue(XmLGridWidget g,
  5491.            XmLGridColumn col,
  5492.            XtArgVal value,
  5493.            long mask)
  5494.     {
  5495.     XmLGridClassPartOfWidget(g).getColumnValueProc(g, col, value, mask);
  5496.     }
  5497.  
  5498. /* Only to be called through Grid class */
  5499. static void 
  5500. _GetColumnValue(XmLGridWidget g,
  5501.         XmLGridColumn col,
  5502.         XtArgVal value,
  5503.         long mask)
  5504.     {
  5505.     switch (mask)
  5506.         {
  5507.         case XmLGridColumnWidth:
  5508.             *((Dimension *)value) = col->grid.width; 
  5509.             break;
  5510.         case XmLGridColumnSizePolicy:
  5511.             *((unsigned char *)value) = col->grid.sizePolicy; 
  5512.             break;
  5513.         case XmLGridColumnUserData:
  5514.             *((XtPointer *)value) = col->grid.userData;
  5515.             break;
  5516.         case XmLGridColumnResizable:
  5517.             *((Boolean *)value) = col->grid.resizable;
  5518.             break;
  5519.  
  5520.         }
  5521.     }
  5522.  
  5523. static int
  5524. SetColumnValues(XmLGridWidget g,
  5525.         XmLGridColumn col,
  5526.         long mask)
  5527.     {
  5528.     return XmLGridClassPartOfWidget(g).setColumnValuesProc(g, col, mask);
  5529.     }
  5530.  
  5531. /* Only to be called through Grid class */
  5532. static int 
  5533. _SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask)
  5534.     {
  5535.     int needsResize = 0, visible = 0;
  5536.     Boolean newIsHidden;
  5537.  
  5538.     if (mask & XmLGridColumnWidth || mask & XmLGridColumnSizePolicy)
  5539.         {
  5540.         visible = ColIsVisible(g, XmLGridColumnGetPos(col));
  5541.         XmLGridColumnWidthChanged(col);
  5542.         }
  5543.     if (mask & XmLGridColumnWidth)
  5544.         {
  5545.         if (g->grid.colWidth > 0)
  5546.             newIsHidden = False;
  5547.         else
  5548.             newIsHidden = True;
  5549.         if (XmLGridColumnIsHidden(col) != newIsHidden)
  5550.             {
  5551.             if (newIsHidden == True)
  5552.                 g->grid.hiddenColCount++;
  5553.             else
  5554.                 g->grid.hiddenRowCount--;
  5555.             VisPosChanged(g, 0);
  5556.             needsResize = 1;
  5557.             }
  5558.         if (visible && !g->grid.inResize)
  5559.             needsResize = 1;
  5560.         col->grid.width = g->grid.colWidth;
  5561.         }
  5562.     if (mask & XmLGridColumnSizePolicy)
  5563.         {
  5564.         col->grid.sizePolicy = g->grid.colSizePolicy;
  5565.         if (visible && !g->grid.inResize)
  5566.             needsResize = 1;
  5567.         }
  5568.     if (mask & XmLGridColumnUserData)
  5569.         col->grid.userData = g->grid.colUserData;
  5570.     if (mask & XmLGridColumnResizable)
  5571.         col->grid.resizable = g->grid.colResizable;
  5572.     return needsResize;
  5573.     }
  5574.  
  5575. /*
  5576.    Getting and Setting Cell Values
  5577. */
  5578.  
  5579. static void
  5580. CellValueGetMask(char *s,
  5581.          long *mask)
  5582.     {
  5583.     static XrmQuark qAlignment, qBackground, qBottomBorderColor;
  5584.     static XrmQuark qBottomBorderType, qColumnSpan;
  5585.     static XrmQuark qEditable, qFontList, qForeground;
  5586.     static XrmQuark qLeftBorderColor, qLeftBorderType;
  5587.     static XrmQuark qMarginBottom, qMarginLeft, qMarginRight;
  5588.     static XrmQuark qMarginTop, qPixmap, qPixmapMask;
  5589.     static XrmQuark qRightBorderColor, qRightBorderType;
  5590.     static XrmQuark qRowSpan, qString, qToggleSet;
  5591.     static XrmQuark qTopBorderColor, qTopBorderType, qType;
  5592.     static XrmQuark qUserData;
  5593.     static int quarksValid = 0;
  5594.     XrmQuark q;
  5595.  
  5596.     if (!quarksValid)
  5597.         {
  5598.         qAlignment = XrmStringToQuark(XmNcellAlignment);
  5599.         qBackground = XrmStringToQuark(XmNcellBackground);
  5600.         qBottomBorderColor = XrmStringToQuark(XmNcellBottomBorderColor);
  5601.         qBottomBorderType = XrmStringToQuark(XmNcellBottomBorderType);
  5602.         qColumnSpan = XrmStringToQuark(XmNcellColumnSpan);
  5603.         qEditable = XrmStringToQuark(XmNcellEditable);
  5604.         qFontList = XrmStringToQuark(XmNcellFontList);
  5605.         qForeground = XrmStringToQuark(XmNcellForeground);
  5606.         qLeftBorderColor = XrmStringToQuark(XmNcellLeftBorderColor);
  5607.         qLeftBorderType = XrmStringToQuark(XmNcellLeftBorderType);
  5608.         qMarginBottom = XrmStringToQuark(XmNcellMarginBottom);
  5609.         qMarginLeft = XrmStringToQuark(XmNcellMarginLeft);
  5610.         qMarginRight = XrmStringToQuark(XmNcellMarginRight);
  5611.         qMarginTop= XrmStringToQuark(XmNcellMarginTop);
  5612.         qPixmap = XrmStringToQuark(XmNcellPixmap);
  5613.         qPixmapMask = XrmStringToQuark(XmNcellPixmapMask);
  5614.         qRightBorderColor = XrmStringToQuark(XmNcellRightBorderColor);
  5615.         qRightBorderType = XrmStringToQuark(XmNcellRightBorderType);
  5616.         qRowSpan = XrmStringToQuark(XmNcellRowSpan);
  5617.         qString = XrmStringToQuark(XmNcellString);
  5618.         qToggleSet = XrmStringToQuark(XmNcellToggleSet);
  5619.         qTopBorderColor = XrmStringToQuark(XmNcellTopBorderColor);
  5620.         qTopBorderType = XrmStringToQuark(XmNcellTopBorderType);
  5621.         qType = XrmStringToQuark(XmNcellType);
  5622.         qUserData = XrmStringToQuark(XmNcellUserData);
  5623.         quarksValid = 1;
  5624.         }
  5625.     q = XrmStringToQuark(s);
  5626.     if (q == qAlignment)
  5627.             *mask |= XmLGridCellAlignment;
  5628.     else if (q == qBackground)
  5629.             *mask |= XmLGridCellBackground;
  5630.     else if (q == qBottomBorderColor)
  5631.             *mask |= XmLGridCellBottomBorderColor;
  5632.     else if (q == qBottomBorderType)
  5633.             *mask |= XmLGridCellBottomBorderType;
  5634.     else if (q == qColumnSpan)
  5635.             *mask |= XmLGridCellColumnSpan;
  5636.     else if (q == qEditable)
  5637.             *mask |= XmLGridCellEditable;
  5638.     else if (q == qFontList)
  5639.             *mask |= XmLGridCellFontList;
  5640.     else if (q == qForeground)
  5641.             *mask |= XmLGridCellForeground;
  5642.     else if (q == qLeftBorderColor)
  5643.             *mask |= XmLGridCellLeftBorderColor;
  5644.     else if (q == qLeftBorderType)
  5645.             *mask |= XmLGridCellLeftBorderType;
  5646.     else if (q == qMarginBottom)
  5647.             *mask |= XmLGridCellMarginBottom;
  5648.     else if (q == qMarginLeft)
  5649.             *mask |= XmLGridCellMarginLeft;
  5650.     else if (q == qMarginRight)
  5651.             *mask |= XmLGridCellMarginRight;
  5652.     else if (q == qMarginTop)
  5653.             *mask |= XmLGridCellMarginTop;
  5654.     else if (q == qPixmap)
  5655.             *mask |= XmLGridCellPixmapF;
  5656.     else if (q == qPixmapMask)
  5657.             *mask |= XmLGridCellPixmapMask;
  5658.     else if (q == qRightBorderColor)
  5659.             *mask |= XmLGridCellRightBorderColor;
  5660.     else if (q == qRightBorderType)
  5661.             *mask |= XmLGridCellRightBorderType;
  5662.     else if (q == qRowSpan)
  5663.             *mask |= XmLGridCellRowSpan;
  5664.     else if (q == qString)
  5665.             *mask |= XmLGridCellString;
  5666.     else if (q == qToggleSet)
  5667.             *mask |= XmLGridCellToggleSet;
  5668.     else if (q == qTopBorderColor)
  5669.             *mask |= XmLGridCellTopBorderColor;
  5670.     else if (q == qTopBorderType)
  5671.             *mask |= XmLGridCellTopBorderType;
  5672.     else if (q == qType)
  5673.             *mask |= XmLGridCellType;
  5674.     else if (q == qUserData)
  5675.             *mask |= XmLGridCellUserData;
  5676.     }
  5677.  
  5678. static void
  5679. GetCellValue(XmLGridCell cell,
  5680.          XtArgVal value,
  5681.          long mask)
  5682.     {
  5683.     XmLGridCellRefValues *values;
  5684.     XmLGridCellPixmap *pix;
  5685.     XmString str;
  5686.  
  5687.     values = XmLGridCellGetRefValues(cell);
  5688.     switch (mask)
  5689.         {
  5690.         case XmLGridCellAlignment:
  5691.             *((unsigned char *)value) = values->alignment; 
  5692.             break;
  5693.         case XmLGridCellBackground:
  5694.             *((Pixel *)value) = values->background; 
  5695.             break;
  5696.         case XmLGridCellBottomBorderColor:
  5697.             *((Pixel *)value) = values->bottomBorderColor;
  5698.             break;
  5699.         case XmLGridCellBottomBorderType:
  5700.             *((unsigned char *)value) = values->bottomBorderType;
  5701.             break;
  5702.         case XmLGridCellColumnSpan:
  5703.             *((int *)value) = values->columnSpan;
  5704.             break;
  5705.         case XmLGridCellEditable:
  5706.             *((Boolean *)value) = values->editable;
  5707.             break;
  5708.         case XmLGridCellFontList:
  5709.             *((XmFontList *)value) = values->fontList; 
  5710.             break;
  5711.         case XmLGridCellForeground:
  5712.             *((Pixel *)value) = values->foreground; 
  5713.             break;
  5714.         case XmLGridCellLeftBorderColor:
  5715.             *((Pixel *)value) = values->leftBorderColor;
  5716.             break;
  5717.         case XmLGridCellLeftBorderType:
  5718.             *((unsigned char *)value) = values->leftBorderType;
  5719.             break;
  5720.         case XmLGridCellMarginBottom:
  5721.             *((Dimension *)value) = values->bottomMargin;
  5722.             break;
  5723.         case XmLGridCellMarginLeft:
  5724.             *((Dimension *)value) = values->leftMargin;
  5725.             break;
  5726.         case XmLGridCellMarginRight:
  5727.             *((Dimension *)value) = values->rightMargin;
  5728.             break;
  5729.         case XmLGridCellMarginTop:
  5730.             *((Dimension *)value) = values->topMargin;
  5731.             break;
  5732.         case XmLGridCellPixmapF:
  5733.             pix = XmLGridCellGetPixmap(cell);
  5734.             if (pix)
  5735.                 *((Pixmap *)value) = pix->pixmap;
  5736.             else
  5737.                 *((Pixmap *)value) = (Pixmap)XmUNSPECIFIED_PIXMAP;
  5738.             break;
  5739.         case XmLGridCellPixmapMask:
  5740.             pix = XmLGridCellGetPixmap(cell);
  5741.             if (pix)
  5742.                 *((Pixmap *)value) = pix->pixmask;
  5743.             else
  5744.                 *((Pixmap *)value) = (Pixmap)XmUNSPECIFIED_PIXMAP;
  5745.             break;
  5746.         case XmLGridCellRightBorderColor:
  5747.             *((Pixel *)value) = values->rightBorderColor;
  5748.             break;
  5749.         case XmLGridCellRightBorderType:
  5750.             *((unsigned char *)value) = values->rightBorderType;
  5751.             break;
  5752.         case XmLGridCellRowSpan:
  5753.             *((int *)value) = values->rowSpan;
  5754.             break;
  5755.         case XmLGridCellString:
  5756.             str = XmLGridCellGetString(cell);
  5757.             if (str)
  5758.                 *((XmString *)value) = XmStringCopy(str);
  5759.             else
  5760.                 *((XmString *)value) = 0;
  5761.             break;
  5762.         case XmLGridCellToggleSet:
  5763.             *((Boolean *)value) = XmLGridCellGetToggle(cell);
  5764.             break;
  5765.         case XmLGridCellTopBorderColor:
  5766.             *((Pixel *)value) = values->topBorderColor;
  5767.             break;
  5768.         case XmLGridCellTopBorderType:
  5769.             *((unsigned char *)value) = values->topBorderType;
  5770.             break;
  5771.         case XmLGridCellType:
  5772.             *((unsigned char *)value) = values->type;
  5773.             break;
  5774.         case XmLGridCellUserData:
  5775.             *((XtPointer *)value) = (XtPointer)values->userData;
  5776.             break;
  5777.         }
  5778.     }
  5779.  
  5780. static XmLGridCellRefValues *
  5781. CellRefValuesCreate(XmLGridWidget g,
  5782.             XmLGridCellRefValues *copy)
  5783.     {
  5784.     short width, height;
  5785.     XmLGridCellRefValues *values;
  5786.  
  5787.     values = (XmLGridCellRefValues *)malloc(sizeof(XmLGridCellRefValues));
  5788.     if (!copy)
  5789.         {
  5790.         /* default values */
  5791.         values->bottomBorderType = XmBORDER_LINE;
  5792.         values->leftBorderType = XmBORDER_LINE;
  5793.         values->rightBorderType = XmBORDER_LINE;
  5794.         values->topBorderType = XmBORDER_LINE;
  5795.         XmLFontListGetDimensions(g->grid.fontList, &width, &height,
  5796.             g->grid.useAvgWidth);
  5797.         values->alignment = XmALIGNMENT_CENTER;
  5798.         values->background = g->core.background_pixel;
  5799.         values->bottomBorderColor = g->manager.bottom_shadow_color;
  5800.         values->bottomMargin = 0;
  5801.         values->columnSpan = 0;
  5802.         values->editable = False;
  5803.         values->fontHeight = height;
  5804.         values->fontList = XmFontListCopy(g->grid.fontList);
  5805.         values->fontWidth = width;
  5806.         values->foreground = g->manager.foreground;
  5807.         values->leftBorderColor = g->manager.top_shadow_color;
  5808.         values->leftMargin = 0;
  5809.         values->refCount = 0;
  5810.         values->rightBorderColor = g->manager.bottom_shadow_color;
  5811.         values->rightMargin = 0;
  5812.         values->rowSpan = 0;
  5813.         values->topBorderColor = g->manager.top_shadow_color;
  5814.         values->topMargin = 0;
  5815.         values->type = XmSTRING_CELL;
  5816.         values->userData = 0;
  5817.         }
  5818.     else
  5819.         {
  5820.         /* copy values */
  5821.         *values = *copy;
  5822.         values->fontList = XmFontListCopy(copy->fontList);
  5823.         values->refCount = 0;
  5824.         }
  5825.     return values;
  5826.     }
  5827.  
  5828. static void
  5829. SetCellValuesPreprocess(XmLGridWidget g,
  5830.             long mask)
  5831.     {
  5832.     XmLGridCellRefValues *newValues;
  5833.     int x, y;
  5834.     short width, height;
  5835.     Display *dpy;
  5836.     Window pixRoot;
  5837.     unsigned int pixWidth, pixHeight;
  5838.     unsigned int pixBW, pixDepth;
  5839.  
  5840.     /* calculate font width and height if set */
  5841.     newValues = &g->grid.cellValues;
  5842.     if (mask & XmLGridCellFontList)
  5843.         {
  5844.         XmLFontListGetDimensions(newValues->fontList, &width, &height,
  5845.             g->grid.useAvgWidth);
  5846.         newValues->fontWidth = width;
  5847.         newValues->fontHeight = height;
  5848.         }
  5849.     if (mask & XmLGridCellPixmapF)
  5850.         {
  5851.         if (g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP &&
  5852.             g->grid.globalPixmapWidth &&
  5853.             g->grid.globalPixmapHeight)
  5854.             {
  5855.             g->grid.cellPixmapWidth = g->grid.globalPixmapWidth;
  5856.             g->grid.cellPixmapHeight = g->grid.globalPixmapHeight;
  5857.             }
  5858.         else if (g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP)
  5859.             {
  5860.             dpy = XtDisplay(g);
  5861.             XGetGeometry(dpy, g->grid.cellPixmap, &pixRoot,
  5862.                 &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth);
  5863.             g->grid.cellPixmapWidth = (Dimension)pixWidth;
  5864.             g->grid.cellPixmapHeight = (Dimension)pixHeight;
  5865.             }
  5866.         else
  5867.             {
  5868.             g->grid.cellPixmapWidth = 0;
  5869.             g->grid.cellPixmapHeight = 0;
  5870.             }
  5871.         }
  5872.     }
  5873.  
  5874. static int
  5875. SetCellHasRefValues(long mask)
  5876.     {
  5877.     long unrefMask;
  5878.  
  5879.     /* return 1 if mask contains any reference counted values */
  5880.     unrefMask = XmLGridCellPixmapF | XmLGridCellPixmapMask |
  5881.         XmLGridCellString | XmLGridCellToggleSet;
  5882.     mask = mask | unrefMask;
  5883.     mask = mask ^ unrefMask;
  5884.     if (!mask)
  5885.         return 0;
  5886.     return 1;
  5887.     }
  5888.  
  5889. static int
  5890. SetCellValuesResize(XmLGridWidget g,
  5891.             XmLGridRow row,
  5892.             XmLGridColumn col,
  5893.             XmLGridCell cell,
  5894.             long mask)
  5895.     {
  5896.     return XmLGridClassPartOfWidget(g).setCellValuesResizeProc(g, row, col,
  5897.         cell, mask);
  5898.     }
  5899.  
  5900. static int 
  5901. _SetCellValuesResize(XmLGridWidget g,
  5902.              XmLGridRow row,
  5903.              XmLGridColumn col,
  5904.              XmLGridCell cell,
  5905.              long mask)
  5906.     {
  5907.     XmLGridCellPixmap *cellPix;
  5908.     int pixResize, needsResize, rowVisible, colVisible;
  5909.  
  5910.     needsResize = 0;
  5911.     pixResize = 0;
  5912.     if (mask & XmLGridCellPixmapF)
  5913.         {
  5914.         pixResize = 1;
  5915.         if (!(mask & XmLGridCellType))
  5916.             {
  5917.             /* no resize needed if we replace with an equal size pixmap */
  5918.             cellPix = XmLGridCellGetPixmap(cell);
  5919.             if (cellPix && cellPix->pixmap != XmUNSPECIFIED_PIXMAP &&
  5920.                 g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP)
  5921.                 {
  5922.                 if (cellPix->width == g->grid.cellPixmapWidth &&
  5923.                     cellPix->height == g->grid.cellPixmapHeight)
  5924.                     pixResize = 0;
  5925.                 }
  5926.             }
  5927.         }
  5928.     if (mask & XmLGridCellType || mask & XmLGridCellFontList || pixResize ||
  5929.         mask & XmLGridCellRowSpan || mask & XmLGridCellColumnSpan ||
  5930.         mask & XmLGridCellMarginLeft || mask & XmLGridCellMarginRight ||
  5931.         mask & XmLGridCellMarginTop || mask & XmLGridCellMarginBottom)
  5932.         {
  5933.         XmLGridRowHeightChanged(row);
  5934.         XmLGridColumnWidthChanged(col);
  5935.         rowVisible = RowIsVisible(g, XmLGridRowGetPos(row));
  5936.         colVisible = ColIsVisible(g, XmLGridColumnGetPos(col));
  5937.         if (rowVisible | colVisible)
  5938.             needsResize = 1;
  5939.         }
  5940.     return needsResize;
  5941.     }
  5942.  
  5943. static void 
  5944. SetCellValues(XmLGridWidget g,
  5945.           XmLGridCell cell,
  5946.           long mask)
  5947.     {
  5948.     /* set non-reference counted cell values */
  5949.     if (mask & XmLGridCellPixmapF)
  5950.         XmLGridCellSetPixmap(cell, g->grid.cellPixmap,
  5951.             g->grid.cellPixmapWidth, g->grid.cellPixmapHeight);
  5952.     if (mask & XmLGridCellPixmapMask)
  5953.         XmLGridCellSetPixmask(cell, g->grid.cellPixmapMask);
  5954.     if (mask & XmLGridCellString)
  5955.         XmLGridCellSetString(cell, g->grid.cellString, True);
  5956.     if (mask & XmLGridCellToggleSet)
  5957.         XmLGridCellSetToggle(cell, g->grid.cellToggleSet);
  5958.     }
  5959.  
  5960. static void
  5961. SetCellRefValues(XmLGridWidget g,
  5962.          XmLGridCellRefValues *values,
  5963.          long mask)
  5964.     {
  5965.     XmLGridCellRefValues *newValues;
  5966.  
  5967.     /* set reference counted cell values */
  5968.     newValues = &g->grid.cellValues;
  5969.     if (mask & XmLGridCellAlignment)
  5970.         values->alignment = newValues->alignment;
  5971.     if (mask & XmLGridCellBackground)
  5972.         values->background = newValues->background;
  5973.     if (mask & XmLGridCellBottomBorderColor)
  5974.         values->bottomBorderColor = newValues->bottomBorderColor;
  5975.     if (mask & XmLGridCellBottomBorderType)
  5976.         values->bottomBorderType = newValues->bottomBorderType;
  5977.     if (mask & XmLGridCellColumnSpan)
  5978.         values->columnSpan = newValues->columnSpan;
  5979.     if (mask & XmLGridCellEditable)
  5980.         values->editable = newValues->editable;
  5981.     if (mask & XmLGridCellFontList)
  5982.         {
  5983.         XmFontListFree(values->fontList);
  5984.         values->fontList = XmFontListCopy(newValues->fontList);
  5985.         values->fontWidth = newValues->fontWidth;
  5986.         values->fontHeight = newValues->fontHeight;
  5987.         }
  5988.     if (mask & XmLGridCellForeground)
  5989.         values->foreground = newValues->foreground;
  5990.     if (mask & XmLGridCellLeftBorderColor)
  5991.         values->leftBorderColor = newValues->leftBorderColor;
  5992.     if (mask & XmLGridCellLeftBorderType)
  5993.         values->leftBorderType = newValues->leftBorderType;
  5994.     if (mask & XmLGridCellRightBorderColor)
  5995.         values->rightBorderColor = newValues->rightBorderColor;
  5996.     if (mask & XmLGridCellRightBorderType)
  5997.         values->rightBorderType = newValues->rightBorderType;
  5998.     if (mask & XmLGridCellMarginBottom)
  5999.         values->bottomMargin = newValues->bottomMargin;
  6000.     if (mask & XmLGridCellMarginLeft)
  6001.         values->leftMargin = newValues->leftMargin;
  6002.     if (mask & XmLGridCellMarginRight)
  6003.         values->rightMargin = newValues->rightMargin;
  6004.     if (mask & XmLGridCellMarginTop)
  6005.         values->topMargin = newValues->topMargin;
  6006.     if (mask & XmLGridCellRowSpan)
  6007.         values->rowSpan = newValues->rowSpan;
  6008.     if (mask & XmLGridCellTopBorderColor)
  6009.         values->topBorderColor = newValues->topBorderColor;
  6010.     if (mask & XmLGridCellTopBorderType)
  6011.         values->topBorderType = newValues->topBorderType;
  6012.     if (mask & XmLGridCellType)
  6013.         {
  6014.         values->type = newValues->type;
  6015.         /* backwards compatibility cell types */
  6016.         if (values->type == XmLABEL_CELL)
  6017.             {
  6018.             values->type = XmSTRING_CELL;
  6019.             values->editable = False;
  6020.             }
  6021.         else if (values->type == XmTEXT_CELL)
  6022.             {
  6023.             values->type = XmSTRING_CELL;
  6024.             values->editable = True;
  6025.             }
  6026.         }
  6027.     if (mask & XmLGridCellUserData)
  6028.         values->userData = newValues->userData;
  6029.     }
  6030.  
  6031. static int
  6032. SetCellRefValuesCompare(void *userData,
  6033.             void **item1,
  6034.             void **item2)
  6035.     {
  6036.     XmLGridCell cell1, cell2;
  6037.     XmLGridCellRefValues *values1, *values2;
  6038.     long mask;
  6039.  
  6040.     mask = *((long *)userData);
  6041.     cell1 = (XmLGridCell)*item1;
  6042.     cell2 = (XmLGridCell)*item2;
  6043.     values1 = XmLGridCellGetRefValues(cell1);
  6044.     values2 = XmLGridCellGetRefValues(cell2);
  6045.     if (values1 == values2)
  6046.         return 0;
  6047.  
  6048. #define RVCOMPARE(res, var) \
  6049.     if (!(mask & res)) \
  6050.         { \
  6051.         if (values1->var < values2->var) \
  6052.             return -1; \
  6053.         if (values1->var > values2->var) \
  6054.             return 1; \
  6055.         }
  6056.     RVCOMPARE(XmLGridCellAlignment, alignment)
  6057.     RVCOMPARE(XmLGridCellBackground, background)
  6058.     RVCOMPARE(XmLGridCellBottomBorderColor, bottomBorderColor)
  6059.     RVCOMPARE(XmLGridCellBottomBorderType, bottomBorderType)
  6060.     RVCOMPARE(XmLGridCellColumnSpan, columnSpan)
  6061.     RVCOMPARE(XmLGridCellEditable, editable)
  6062.     RVCOMPARE(XmLGridCellFontList, fontList)
  6063.     RVCOMPARE(XmLGridCellForeground, foreground)
  6064.     RVCOMPARE(XmLGridCellLeftBorderColor, leftBorderColor)
  6065.     RVCOMPARE(XmLGridCellLeftBorderType, leftBorderType)
  6066.     RVCOMPARE(XmLGridCellMarginBottom, bottomMargin)
  6067.     RVCOMPARE(XmLGridCellMarginLeft, leftMargin)
  6068.     RVCOMPARE(XmLGridCellMarginRight, rightMargin)
  6069.     RVCOMPARE(XmLGridCellMarginTop, topMargin)
  6070.     RVCOMPARE(XmLGridCellRightBorderColor, rightBorderColor)
  6071.     RVCOMPARE(XmLGridCellRightBorderType, rightBorderType)
  6072.     RVCOMPARE(XmLGridCellRowSpan, rowSpan)
  6073.     RVCOMPARE(XmLGridCellTopBorderColor, topBorderColor)
  6074.     RVCOMPARE(XmLGridCellTopBorderType, topBorderType)
  6075.     RVCOMPARE(XmLGridCellType, type)
  6076.     RVCOMPARE(XmLGridCellUserData, userData)
  6077. #undef RVCOMPARE
  6078.  
  6079.     /* If the two cell values are equal, we merge them
  6080.        into one record here.  This speeds up the sort
  6081.          and will allow the merge to compare just the values
  6082.        pointers to test equality. Note that this will not
  6083.        merge every possible item that could be merged, we
  6084.        don't want to do that because of the performance impact */
  6085.     if (values1 < values2)
  6086.         XmLGridCellSetRefValues(cell1, values2);
  6087.     else
  6088.         XmLGridCellSetRefValues(cell2, values1);
  6089.     return 0;
  6090.     }
  6091.  
  6092. static void
  6093. SetCellRefValuesPreprocess(XmLGridWidget g,
  6094.                int row,
  6095.                int col,
  6096.                XmLGridCell cell,
  6097.                long mask)
  6098.     {
  6099.     int r, c, rowSpan, colSpan;
  6100.     XmLGridCell spanCell;
  6101.     XmLGridCellRefValues *oldValues, *newValues;
  6102.     unsigned char oldType, newType;
  6103.     XmLGridCallbackStruct cbs;
  6104.  
  6105.     if (mask & XmLGridCellType)
  6106.         {
  6107.         oldType = XmLGridCellGetRefValues(cell)->type;
  6108.         newType = g->grid.cellValues.type;
  6109.         if (oldType != newType)
  6110.             {
  6111.             cbs.reason = XmCR_FREE_VALUE;
  6112.             XmLGridCellAction(cell, (Widget)g, &cbs);
  6113.             }
  6114.         }
  6115.     if (mask & XmLGridCellRowSpan || mask & XmLGridCellColumnSpan)
  6116.         {
  6117.         /* expose old cell area in case the span area shrinks */
  6118.         DrawArea(g, DrawCell, row, col);
  6119.         oldValues = XmLGridCellGetRefValues(cell);
  6120.         newValues = &g->grid.cellValues;
  6121.         if (mask & XmLGridCellRowSpan)
  6122.             {
  6123.             g->grid.mayHaveRowSpans = 1;
  6124.             if (newValues->rowSpan < 0)
  6125.                 {
  6126.                 XmLWarning((Widget)g,
  6127.                     "SetValues() - row span can't be < 0");
  6128.                 newValues->rowSpan = 0;
  6129.                 }
  6130.             rowSpan = newValues->rowSpan;
  6131.             }
  6132.         else
  6133.             rowSpan = oldValues->rowSpan;
  6134.         if (mask & XmLGridCellColumnSpan)
  6135.             {
  6136.             if (newValues->columnSpan < 0)
  6137.                 {
  6138.                 XmLWarning((Widget)g,
  6139.                     "SetValues() - column span can't be < 0");
  6140.                 newValues->columnSpan = 0;
  6141.                 }
  6142.             colSpan = newValues->columnSpan;
  6143.             }
  6144.         else
  6145.             colSpan = oldValues->columnSpan;
  6146.         /* clear old span */
  6147.         for (c = col; c <= col + oldValues->columnSpan; c++)
  6148.             for (r = row; r <= row + oldValues->rowSpan; r++)
  6149.                 {
  6150.                 /* skip the cell itself */
  6151.                 if (c == col && r == row)
  6152.                     continue;
  6153.                 spanCell = GetCell(g, r, c);
  6154.                 if (!spanCell)
  6155.                     continue;
  6156.                 XmLGridCellSetInRowSpan(spanCell, False);
  6157.                 XmLGridCellSetInColumnSpan(spanCell, False);
  6158.                 }
  6159.         /* set new span */
  6160.         for (c = col; c <= col + colSpan; c++)
  6161.             for (r = row; r <= row + rowSpan; r++)
  6162.                 {
  6163.                 /* skip the cell itself */
  6164.                 if (c == col && r == row)
  6165.                     continue;
  6166.                 spanCell = GetCell(g, r, c);
  6167.                 if (!spanCell)
  6168.                     continue;
  6169.                 if (r == row)
  6170.                     XmLGridCellSetInColumnSpan(spanCell, True);
  6171.                 else
  6172.                     XmLGridCellSetInRowSpan(spanCell, True);
  6173.                 }
  6174.         }
  6175.     }
  6176.  
  6177. /*
  6178.    Read, Write, Copy, Paste
  6179. */
  6180.  
  6181. static int
  6182. Read(XmLGridWidget g,
  6183.      int format,
  6184.      char delimiter,
  6185.      int row,
  6186.      int col,
  6187.      char *data)
  6188.     {
  6189.     char *c1, *c2, buf[256], *bufp;
  6190.     int r, c, i, j, len, n, needsResize, allowSet, done;
  6191.     XmString str;
  6192.     XmLGridCell cell;
  6193.     XmLGridRow rowp;
  6194.     XmLGridColumn colp;
  6195.     XmLGridCellRefValues *cellValues;
  6196.     XmLGridCallbackStruct cbs;
  6197.  
  6198.     if (format == XmFORMAT_PAD)
  6199.         {
  6200.         XmLWarning((Widget)g, "Read() - FORMAT_PAD not supported");
  6201.         return 0;
  6202.         }
  6203.     if (format == XmFORMAT_XL ||
  6204.         format == XmFORMAT_DROP ||
  6205.         format == XmFORMAT_PASTE)
  6206.         delimiter = '\t';
  6207.     c1 = data;
  6208.     c2 = data;
  6209.     r = row;
  6210.     c = col;
  6211.     needsResize = 0;
  6212.     done = 0;
  6213.     n = 0;
  6214.     while (!done)
  6215.         {
  6216.         if (!(*c2) || *c2 == delimiter || *c2 == '\n')
  6217.             {
  6218.             len = c2 - c1;
  6219.             if (len < 256)
  6220.                 bufp = buf;
  6221.             else
  6222.                 bufp = (char *)malloc(len + 1);
  6223.             if (format == XmFORMAT_XL)
  6224.                 {
  6225.                 /* strip leading and trailing double-quotes */
  6226.                 if (len && c1[0] == '"')
  6227.                     {
  6228.                     c1++;
  6229.                     len--;
  6230.                     }
  6231.                 if (len && c1[len - 1] == '"')
  6232.                     len--;
  6233.                 }
  6234.             j = 0;
  6235.             for (i = 0; i < len; i++)
  6236.                 {
  6237.                 if (c1[0] == '\\' && c1[1] == 'n')
  6238.                     {
  6239.                     bufp[j++] = '\n';
  6240.                     c1 += 2;
  6241.                     i++;
  6242.                     }
  6243.                 else
  6244.                     bufp[j++] = *c1++;
  6245.                 }
  6246.             bufp[j] = 0;
  6247.             j = 0;
  6248.             str = XmStringCreateLtoR(bufp, XmSTRING_DEFAULT_CHARSET);
  6249.             if (bufp != buf)
  6250.                 free((char *)bufp);
  6251.             rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  6252.             colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  6253.             cell = GetCell(g, r, c);
  6254.             allowSet = 1;
  6255.             if (cell && (format == XmFORMAT_PASTE || format == XmFORMAT_DROP))
  6256.                 {
  6257.                 cellValues = XmLGridCellGetRefValues(cell);
  6258.                 if (cellValues->type != XmSTRING_CELL ||
  6259.                     cellValues->editable != True ||
  6260.                     RowPosToType(g, r) != XmCONTENT ||
  6261.                     ColPosToType(g, c) != XmCONTENT)
  6262.                     allowSet = 0;
  6263.                 }
  6264.             if (cell && allowSet)
  6265.                 {
  6266.                 XmLGridCellSetString(cell, str, False);
  6267.                 if (SetCellValuesResize(g, rowp, colp, cell, XmLGridCellString))
  6268.                     needsResize = 1;
  6269.                 if (!needsResize)
  6270.                     DrawArea(g, DrawCell, r, c);
  6271.                 cbs.columnType = ColPosToType(g, c);
  6272.                 cbs.column = ColPosToTypePos(g, cbs.columnType, c);
  6273.                 cbs.rowType = RowPosToType(g, r);
  6274.                 cbs.row = RowPosToTypePos(g, cbs.rowType, r);
  6275.                 if (format == XmFORMAT_PASTE)
  6276.                     {
  6277.                     cbs.reason = XmCR_CELL_PASTE;
  6278.                     XtCallCallbackList((Widget)g, g->grid.cellPasteCallback,
  6279.                         (XtPointer)&cbs);
  6280.                     }
  6281.                 else if (format == XmFORMAT_DROP)
  6282.                     {
  6283.                     cbs.reason = XmCR_CELL_DROP;
  6284.                     XtCallCallbackList((Widget)g, g->grid.cellDropCallback,
  6285.                         (XtPointer)&cbs);
  6286.                     }
  6287.                 n++;
  6288.                 }
  6289.             else
  6290.                 XmStringFree(str);
  6291.             }
  6292.         if (!(*c2))
  6293.             done = 1;
  6294.         else if (*c2 == delimiter)
  6295.             {
  6296.             c++;
  6297.             c1 = c2 + 1;
  6298.             }
  6299.         else if (*c2 == '\n')
  6300.             {
  6301.             r++;
  6302.             c = col;
  6303.             c1 = c2 + 1;
  6304.             }
  6305.         c2++;
  6306.         }
  6307.     if (needsResize)
  6308.         {
  6309.         VertLayout(g, 1);
  6310.         HorizLayout(g, 1);
  6311.         DrawArea(g, DrawAll, 0, 0);
  6312.         }
  6313.     return n;
  6314.     }
  6315.  
  6316. static void
  6317. Write(XmLGridWidget g,
  6318.       FILE *file,
  6319.       int format,
  6320.       char delimiter,
  6321.       Boolean skipHidden,
  6322.       int row,
  6323.       int col,
  6324.       int nrow,
  6325.       int ncol)
  6326.     {
  6327.     int r, c, i, first, last;
  6328.     char *cs = NULL;
  6329.     Boolean set;
  6330.     XmString str;
  6331.     XmLGridColumn colp;
  6332.     XmLGridRow rowp;
  6333.     XmLGridCell cell;
  6334.  
  6335.     first = 1;
  6336.     for (r = row; r < row + nrow; r++)
  6337.         {
  6338.         rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  6339.         if (!rowp)
  6340.             continue;
  6341.         if (skipHidden == True && XmLGridRowIsHidden(rowp) == True)
  6342.             continue;
  6343.         if (first)
  6344.             first = 0;
  6345.         else
  6346.             fprintf(file, "\n");
  6347.         for (c = col; c < col + ncol; c++)
  6348.             {
  6349.             colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  6350.             if (!colp)
  6351.                 continue;
  6352.             if (skipHidden == True && XmLGridColumnIsHidden(colp) == True)
  6353.                 continue;
  6354.             cell = GetCell(g, r, c);
  6355.             if (!cell)
  6356.                 continue;
  6357.             str = XmLGridCellGetString(cell);
  6358.             set = False;
  6359.             if (str)
  6360.                 {
  6361.                 cs = CvtXmStringToStr(str);
  6362.                 if (cs)
  6363.                     set = True;
  6364.                 }
  6365.             if (set == False)
  6366.                 cs = "";
  6367.             fprintf(file, "%s", cs);
  6368.  
  6369.             last = 0;
  6370.             if (c == col + ncol - 1)
  6371.                 last = 1;
  6372.             if (!last && format == XmFORMAT_DELIMITED)
  6373.                 fprintf(file, "%c", delimiter);
  6374.             else if (!last && format == XmFORMAT_XL)
  6375.                 fprintf(file, "\t");
  6376.             else if (format == XmFORMAT_PAD)
  6377.                 {
  6378.                 if (colp->grid.sizePolicy == XmVARIABLE)
  6379.                     for (i = 0; i < (int)(colp->grid.width - strlen(cs)); i++)
  6380.                         fprintf(file, " ");
  6381.                 }
  6382.  
  6383.             if (set == True)
  6384.                 free(cs);
  6385.             }
  6386.         }
  6387.     }
  6388.  
  6389. static char *
  6390. CopyDataCreate(XmLGridWidget g, int selected, int row, int col, int nrow, int ncol)
  6391.     {
  6392.     XmLGridColumn colp;
  6393.     XmLGridRow rowp;
  6394.     XmLGridCell cell;
  6395.     char *buf, *cs = NULL;
  6396.     XmString str;
  6397.     Boolean set;
  6398.     int r, c, wroteStr, bufsize, buflen, len;
  6399.  
  6400.     if (selected)
  6401.         {
  6402.         row = 0;
  6403.         nrow = XmLArrayGetCount(g->grid.rowArray);
  6404.         col = 0;
  6405.         ncol = XmLArrayGetCount(g->grid.colArray);
  6406.         }
  6407.     bufsize = 1024;
  6408.     buflen = 0;
  6409.     buf = (char *)malloc(bufsize);
  6410.  
  6411.     for (r = row; r < row + nrow; r++)
  6412.         {
  6413.         wroteStr = 0;
  6414.         rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  6415.         if (!rowp)
  6416.             continue;
  6417.         for (c = col; c < col + ncol; c++)
  6418.             {
  6419.             colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  6420.             if (!colp)
  6421.                 continue;
  6422.             cell = GetCell(g, r, c);
  6423.             if (!cell)
  6424.                 continue;
  6425.             if (selected &&
  6426.                 XmLGridRowIsSelected(rowp) == False &&
  6427.                 XmLGridColumnIsSelected(colp) == False &&
  6428.                 XmLGridCellIsSelected(cell) == False)
  6429.                 continue;
  6430.             str = XmLGridCellGetString(cell);
  6431.             set = False;
  6432.             if (str)
  6433.                 {
  6434.                 cs = CvtXmStringToStr(str);
  6435.                 if (cs)
  6436.                     set = True;
  6437.                 }
  6438.             if (set == False)
  6439.                 cs = "";
  6440.             if (wroteStr)
  6441.                 buf[buflen++] = '\t';
  6442.  
  6443.             len = strlen(cs);
  6444.             /* allocate if string plus tab plus new-line plus 0 if too large */
  6445.             while (len + buflen + 3 > bufsize)
  6446.                 bufsize *= 2;
  6447.             buf = (char *)realloc(buf, bufsize);
  6448.             strcpy(&buf[buflen], cs);
  6449.             buflen += len;
  6450.             if (set == True)
  6451.                 free(cs);
  6452.             wroteStr = 1;
  6453.             }
  6454.         if (wroteStr)
  6455.             buf[buflen++] = '\n';
  6456.         }
  6457.     if (!buflen)
  6458.         {
  6459.         free((char *)buf);
  6460.         return 0;
  6461.         }
  6462.     buf[buflen - 1] = 0;
  6463.     return buf;
  6464.     }
  6465.  
  6466. static Boolean
  6467. Copy(XmLGridWidget g,
  6468.      Time time,
  6469.      int selected,
  6470.      int row,
  6471.      int col,
  6472.      int nrow,
  6473.      int ncol)
  6474.     {
  6475.     int i;
  6476.     long itemID;
  6477.     Display *dpy;
  6478.     Window win;
  6479.     XmString clipStr;
  6480.     char *buf;
  6481. #ifdef MOTIF11
  6482.     int dataID;
  6483. #else
  6484.     long ldataID;
  6485. #endif
  6486.  
  6487.     if (!XtIsRealized((Widget)g))
  6488.         {
  6489.         XmLWarning((Widget)g, "Copy() - widget not realized");
  6490.         return False;
  6491.         }
  6492.     dpy = XtDisplay((Widget)g);
  6493.     win = XtWindow((Widget)g);
  6494.     buf = CopyDataCreate(g, selected, row, col, nrow, ncol);
  6495.     if (!buf)
  6496.         return False;
  6497.     clipStr = XmStringCreateSimple("Grid Copy");
  6498.     for (i = 0; i < 10000; i++)
  6499.         if (XmClipboardStartCopy(dpy, win, clipStr, time, NULL,
  6500.             NULL, &itemID) == ClipboardSuccess)
  6501.             break;
  6502.     XmStringFree(clipStr);
  6503.     if (i == 10000)
  6504.         {
  6505.         XmLWarning((Widget)g, "Copy() - start clipboard copy failed");
  6506.         return False;
  6507.         }
  6508.     for (i = 0; i < 10000; i++)
  6509. #ifdef MOTIF11
  6510.         if (XmClipboardCopy(dpy, win, itemID, "STRING", buf,
  6511.             (long)strlen(buf) + 1, 0, &dataID) == ClipboardSuccess)
  6512. #else
  6513.         if (XmClipboardCopy(dpy, win, itemID, "STRING", buf,
  6514.             (long)strlen(buf) + 1, 0, &ldataID) == ClipboardSuccess)
  6515. #endif
  6516.             break;
  6517.     free((char *)buf);
  6518.     if (i == 10000)
  6519.         {
  6520.         XmLWarning((Widget)g, "Copy() - clipboard copy transfer failed");
  6521.         return False;
  6522.         }
  6523.     for (i = 0; i < 10000; i++)
  6524.         if (XmClipboardEndCopy(dpy, win, itemID) == ClipboardSuccess)
  6525.             break;
  6526.     if (i == 10000)
  6527.         {
  6528.         XmLWarning((Widget)g, "Copy() - end clipboard copy failed");
  6529.         return False;
  6530.         }
  6531.     return True;
  6532.     }
  6533.  
  6534. static Boolean
  6535. Paste(XmLGridWidget g,
  6536.       int row,
  6537.       int col)
  6538.     {
  6539.     Display *dpy;
  6540.     Window win;
  6541.     int i, res, done;
  6542.     unsigned long len, reclen;
  6543.     char *buf;
  6544.  
  6545.     if (!XtIsRealized((Widget)g))
  6546.         {
  6547.         XmLWarning((Widget)g, "Paste() - widget not realized");
  6548.         return False;
  6549.         }
  6550.     dpy = XtDisplay((Widget)g);
  6551.     win = XtWindow((Widget)g);
  6552.     for (i = 0; i < 10000; i++)
  6553.         if (XmClipboardInquireLength(dpy, win, "STRING", &len) ==
  6554.             ClipboardSuccess)
  6555.             break;
  6556.     if (i == 10000)
  6557.         {
  6558.         XmLWarning((Widget)g, "Paste() - can't retrieve clipboard length");
  6559.         return False;
  6560.         }
  6561.     if (!len)
  6562.         return False;
  6563.     buf = (char *)malloc((int)len);
  6564.     done = 0;
  6565.     while (!done)
  6566.         {
  6567.         res = XmClipboardRetrieve(dpy, win, "STRING", buf, len,
  6568.             &reclen, NULL);
  6569.         switch (res)
  6570.             {
  6571.             case ClipboardSuccess:
  6572.                 done = 2;
  6573.                 break;
  6574.             case ClipboardTruncate:
  6575.             case ClipboardNoData:
  6576.                 done = 1;
  6577.                 break;
  6578.             case ClipboardLocked:
  6579.                 break;
  6580.             }
  6581.         }
  6582.     if (done != 2 || reclen != len)
  6583.         {
  6584.         free((char *)buf);
  6585.         XmLWarning((Widget)g, "Paste() - retrieve from clipboard failed");
  6586.         return False;
  6587.         }
  6588.     Read(g, XmFORMAT_PASTE, 0, row, col, buf);
  6589.     free((char *)buf);
  6590.     return True;
  6591.     }
  6592.  
  6593. /*
  6594.    Utility
  6595. */
  6596.  
  6597. static void
  6598. GetCoreBackground(Widget w,
  6599.           int offset,
  6600.           XrmValue *value)
  6601.     {
  6602.     value->addr = (caddr_t)&w->core.background_pixel;
  6603.     }
  6604.  
  6605. static void
  6606. GetManagerForeground(Widget w,
  6607.              int offset,
  6608.              XrmValue *value)
  6609.     {
  6610.     XmLGridWidget g;
  6611.  
  6612.     g = (XmLGridWidget)w;
  6613.     value->addr = (caddr_t)&g->manager.foreground;
  6614.     }
  6615.  
  6616. static void
  6617. ClipRectToReg(XmLGridWidget g,
  6618.           XRectangle *rect,
  6619.           GridReg *reg)
  6620.     {
  6621.     int i, st;
  6622.     XRectangle regRect;
  6623.  
  6624.     st = g->manager.shadow_thickness;
  6625.     if (!reg->width || !reg->height)
  6626.         i = XmLRectOutside;
  6627.     else 
  6628.         {
  6629.         regRect.x = reg->x + st;
  6630.         regRect.y = reg->y + st;
  6631.         regRect.width = reg->width - st * 2;
  6632.         regRect.height = reg->height - st * 2;
  6633.         i = XmLRectIntersect(rect, ®Rect);
  6634.         }
  6635.     if (i == XmLRectInside)
  6636.         return;
  6637.     if (i == XmLRectOutside)
  6638.         {
  6639.         rect->width = 0;
  6640.         rect->height = 0;
  6641.         return;
  6642.         }
  6643.     if (rect->y + (int)rect->height - 1 >= reg->y + (int)reg->height - st)
  6644.         rect->height = reg->y + reg->height - rect->y - st;
  6645.     if (rect->x + (int)rect->width - 1 >= reg->x + (int)reg->width - st)
  6646.         rect->width = reg->x + reg->width - rect->x - st;
  6647.     if (rect->y < reg->y + st)
  6648.         {
  6649.         rect->height -= (reg->y + st) - rect->y;
  6650.         rect->y = reg->y + st;
  6651.         }
  6652.     if (rect->x < reg->x + st)
  6653.         {
  6654.         rect->width -= (reg->x + st) - rect->x;
  6655.         rect->x = reg->x + st;
  6656.         }
  6657.     }
  6658.  
  6659. static char *
  6660. FileToString(FILE *file)
  6661.     {
  6662.     long len, n;
  6663.     char *s;
  6664.  
  6665.     if (!file)
  6666.         return 0;
  6667.     fseek(file, 0L, 2);
  6668.     len = ftell(file);
  6669.     s = (char *)malloc((int)len + 1);
  6670.     if (!s)
  6671.         return 0;
  6672.     s[len] = 0;
  6673.     fseek(file, 0L, 0);
  6674.     n = fread(s, 1, (int)len, file);
  6675.     if (n != len)
  6676.         {
  6677.         free((char *)s);
  6678.         return 0;
  6679.         }
  6680.     return s;
  6681.     }
  6682.  
  6683. static char *
  6684. CvtXmStringToStr(XmString str)
  6685.     {
  6686.     XmStringContext context;
  6687.     XmStringCharSet charset;
  6688.     XmStringDirection dir;
  6689.     Boolean sep;
  6690.     char *text, *c;
  6691.     int len, size;
  6692.  
  6693.     if (!XmStringInitContext(&context, str))
  6694.         return 0;
  6695.     size = 0;
  6696.     c = 0;
  6697.     while (XmStringGetNextSegment(context, &text, &charset, &dir, &sep))
  6698.         {
  6699.         len = strlen(text);
  6700.         size += len + 3;
  6701.         if (!c)
  6702.             {
  6703.             c = (char *)malloc(size);
  6704.             *c = 0;
  6705.             }
  6706.         else
  6707.             c = (char *)realloc(c, size);
  6708.         strcat(c, text);
  6709.         if (sep == True)
  6710.             {
  6711.             len = strlen(c);
  6712.             c[len] = '\\';
  6713.             c[len + 1] = 'n';
  6714.             c[len + 2] = 0;
  6715.             }
  6716.         XtFree(text);
  6717.         XtFree(charset);
  6718.         }
  6719.     XmStringFreeContext(context);
  6720.     return c;
  6721.     }
  6722.  
  6723. static XmLGridWidget 
  6724. WidgetToGrid(Widget w,
  6725.          char *funcname)
  6726.     {
  6727.     char buf[256];
  6728.  
  6729.     if (!XmLIsGrid(w))
  6730.         {
  6731.         sprintf(buf, "%s - widget not an XmLGrid", funcname);
  6732.         XmLWarning(w, buf);
  6733.         return 0;
  6734.         }
  6735.     return (XmLGridWidget)w;
  6736.     }
  6737.  
  6738. /*
  6739.    Actions, Callbacks and Handlers
  6740. */
  6741.  
  6742. static void
  6743. ButtonMotion(Widget w,
  6744.          XEvent *event,
  6745.          String *params,
  6746.          Cardinal *nparam)
  6747.     {
  6748.     XmLGridWidget g;
  6749.     XMotionEvent *me;
  6750.     char dragTimerSet;
  6751.     int row, col, x, y;
  6752.  
  6753.     if (event->type != MotionNotify)
  6754.         return;
  6755.     g = (XmLGridWidget)w;
  6756.     me = (XMotionEvent *)event;
  6757.     if (g->grid.inMode == InResize)
  6758.         {
  6759.         if (g->grid.resizeIsVert)
  6760.             DrawResizeLine(g, me->y, 0);
  6761.         else
  6762.             DrawResizeLine(g, me->x, 0);
  6763.         }
  6764.  
  6765.     /* drag scrolling */
  6766.     dragTimerSet = 0;
  6767.     if (g->grid.inMode == InSelect)
  6768.         {
  6769.         if (g->grid.vsPolicy == XmCONSTANT)
  6770.             {
  6771.             y = g->grid.reg[4].y;
  6772.             if (g->grid.selectionPolicy == XmSELECT_CELL &&
  6773.                 g->grid.extendRow != -1 &&
  6774.                 g->grid.extendCol != -1 &&
  6775.                 RowPosToType(g, g->grid.extendRow) == XmHEADING)
  6776.                 ;
  6777.             else if (me->y < y)
  6778.                 dragTimerSet |= DragUp;
  6779.             y += g->grid.reg[4].height;
  6780.             if (me->y > y)
  6781.                 dragTimerSet |= DragDown;
  6782.             }
  6783.         if (g->grid.hsPolicy == XmCONSTANT)
  6784.             {
  6785.             x = g->grid.reg[4].x;
  6786.             if (g->grid.selectionPolicy == XmSELECT_CELL &&
  6787.                 g->grid.extendCol != -1 &&
  6788.                 g->grid.extendRow != -1 &&
  6789.                 ColPosToType(g, g->grid.extendCol) == XmHEADING)
  6790.                 ;
  6791.             else if (me->x < x)
  6792.                 dragTimerSet |= DragLeft;
  6793.             x += g->grid.reg[4].width;
  6794.             if (me->x > x)
  6795.                 dragTimerSet |= DragRight;
  6796.             }
  6797.         }
  6798.     if (!g->grid.dragTimerSet && dragTimerSet)
  6799.         g->grid.dragTimerId = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  6800.             80, DragTimer, (caddr_t)g);
  6801.     else if (g->grid.dragTimerSet && !dragTimerSet)
  6802.         XtRemoveTimeOut(g->grid.dragTimerId);
  6803.     g->grid.dragTimerSet = dragTimerSet;
  6804.  
  6805.     /* Extend Selection */
  6806.     if (g->grid.inMode == InSelect && XYToRowCol(g, me->x, me->y,
  6807.         &row, &col) != -1)
  6808.         {
  6809.         if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW &&
  6810.             RowPosToType(g, row) == XmCONTENT)
  6811.             ExtendSelect(g, event, False, row, col);
  6812.         else if (g->grid.selectionPolicy == XmSELECT_CELL)
  6813.             ExtendSelect(g, event, False, row, col);
  6814.         }
  6815.  
  6816.     if (g->grid.inMode == InSelect &&
  6817.         g->grid.selectionPolicy == XmSELECT_BROWSE_ROW &&
  6818.         XYToRowCol(g, me->x, me->y, &row, &col) != -1)
  6819.         {
  6820.         if (RowPosToType(g, row) == XmCONTENT)
  6821.             {
  6822.             if (!SetFocus(g, row, col, 0, 1))
  6823.                 SelectTypeArea(g, SelectRow, event,
  6824.                     RowPosToTypePos(g, XmCONTENT,
  6825.                     g->grid.focusRow), 0, True, True);
  6826.             }
  6827.         }
  6828.     }
  6829.  
  6830. static void
  6831. DragTimer(XtPointer clientData,
  6832.       XtIntervalId *intervalId)
  6833.     {
  6834.     Widget w;
  6835.     XmLGridWidget g;
  6836.     XRectangle rect;
  6837.     XmLGridRow rowp;
  6838.     XmLGridColumn colp;
  6839.     int r, c, min, max, inc, pi, ss, value, newValue;
  6840.     int extRow, extCol;
  6841.  
  6842.     g = (XmLGridWidget)clientData;
  6843.     w = (Widget)g;
  6844.     extRow = -1;
  6845.     extCol = -1;
  6846.     if (g->grid.vsPolicy == XmCONSTANT && ((g->grid.dragTimerSet & DragUp) ||
  6847.         (g->grid.dragTimerSet & DragDown)))
  6848.         {
  6849.         XtVaGetValues(g->grid.vsb,
  6850.             XmNminimum, &min,
  6851.             XmNmaximum, &max,
  6852.             XmNvalue, &value,
  6853.             XmNsliderSize, &ss,
  6854.             XmNincrement, &inc,
  6855.             XmNpageIncrement, &pi,
  6856.             NULL);
  6857.         newValue = value;
  6858.         if (g->grid.dragTimerSet & DragUp)
  6859.             newValue--;
  6860.         else
  6861.             newValue++;
  6862.         if (newValue != value && newValue >= min && newValue <= (max - ss))
  6863.             {
  6864.             XmScrollBarSetValues(g->grid.vsb, newValue, ss, inc, pi, True);
  6865.             r = g->grid.reg[4].row;
  6866.             if (g->grid.dragTimerSet & DragDown)
  6867.                 r += g->grid.reg[4].nrow - 1;
  6868.             /* simple check to make sure row selected is totally visible */
  6869.             if (g->grid.reg[4].nrow)
  6870.                 {
  6871.                 rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r);
  6872.                 if (rowp && !RowColToXY(g, r, 0, True, &rect))
  6873.                     {
  6874.                     if (GetRowHeight(g, r) != rect.height)
  6875.                         r--;
  6876.                     }
  6877.                 }
  6878.             if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW)
  6879.                 {
  6880.                 if (!SetFocus(g, r, g->grid.focusCol, -1, 1))
  6881.                     SelectTypeArea(g, SelectRow, (XEvent *)0,
  6882.                         RowPosToTypePos(g, XmCONTENT, g->grid.focusRow),
  6883.                         0, True, True);
  6884.                 }
  6885.             else if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW)
  6886.                 ExtendSelect(g, (XEvent *)0, False, r, g->grid.focusCol);
  6887.             else if (g->grid.selectionPolicy == XmSELECT_CELL)
  6888.                 {
  6889.                 extRow = r;
  6890.                 extCol = g->grid.extendToCol;
  6891.                 }
  6892.             }
  6893.         }
  6894.     if (g->grid.hsPolicy == XmCONSTANT && ((g->grid.dragTimerSet & DragLeft) ||
  6895.         (g->grid.dragTimerSet & DragRight)))
  6896.         {
  6897.         XtVaGetValues(g->grid.hsb,
  6898.             XmNminimum, &min,
  6899.             XmNmaximum, &max,
  6900.             XmNvalue, &value,
  6901.             XmNsliderSize, &ss,
  6902.             XmNincrement, &inc,
  6903.             XmNpageIncrement, &pi,
  6904.             NULL);
  6905.         newValue = value;
  6906.         if (g->grid.dragTimerSet & DragLeft)
  6907.             newValue--;
  6908.         else
  6909.             newValue++;
  6910.         if (newValue != value && newValue >= min && newValue <= (max - ss))
  6911.             {
  6912.             XmScrollBarSetValues(g->grid.hsb, newValue, ss, inc, pi, True);
  6913.             c = g->grid.reg[4].col;
  6914.             if (g->grid.dragTimerSet & DragRight)
  6915.                 c += g->grid.reg[4].ncol - 1;
  6916.             if (g->grid.selectionPolicy == XmSELECT_CELL)
  6917.                 {
  6918.                 /* simple check to make sure col selected is totally visible */
  6919.                 if (g->grid.reg[4].ncol)
  6920.                     {
  6921.                     colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c);
  6922.                     if (colp && !RowColToXY(g, c, 0, True, &rect))
  6923.                         {
  6924.                         if (GetColWidth(g, c) != rect.width)
  6925.                             c--;
  6926.                         }
  6927.                     }
  6928.                 if (extRow == -1)
  6929.                     extRow = g->grid.extendToRow;
  6930.                 extCol = c;
  6931.                 }
  6932.             }
  6933.         }
  6934.     if (extRow != -1 && extCol != -1)
  6935.         ExtendSelect(g, (XEvent *)0, False, extRow, extCol);
  6936.     g->grid.dragTimerId = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  6937.         80, DragTimer, (caddr_t)g);
  6938.     }
  6939.  
  6940. static void
  6941. CursorMotion(Widget w,
  6942.          XEvent *event,
  6943.          String *params,
  6944.          Cardinal *nparam)
  6945.     {
  6946.     XmLGridWidget g;
  6947.     XMotionEvent *me;
  6948.     int isVert, row, col;
  6949.     char defineCursor;
  6950.  
  6951.     if (event->type != MotionNotify)
  6952.         return;
  6953.     g = (XmLGridWidget)w;
  6954.     me = (XMotionEvent *)event;
  6955.     defineCursor = CursorNormal;
  6956.     if (PosIsResize(g, me->x, me->y, &row, &col, &isVert))
  6957.         {
  6958.         if (isVert)
  6959.             defineCursor = CursorVResize;
  6960.         else
  6961.             defineCursor = CursorHResize;
  6962.         }
  6963.     DefineCursor(g, defineCursor);
  6964.     }
  6965.  
  6966. static void
  6967. Edit(Widget w,
  6968.      XEvent *event,
  6969.      String *params,
  6970.      Cardinal *nparam)
  6971.     {
  6972.     XmLGridWidget g;
  6973.  
  6974.     g = (XmLGridWidget)XtParent(w);
  6975.     TextAction(g, TEXT_EDIT_INSERT);
  6976.     }
  6977.  
  6978. static void
  6979. EditCancel(Widget w,
  6980.        XEvent *event,
  6981.        String *params,
  6982.        Cardinal *nparam)
  6983.     {
  6984.     XmLGridWidget g;
  6985.  
  6986.     g = (XmLGridWidget)XtParent(w);
  6987.     TextAction(g, TEXT_EDIT_CANCEL);
  6988.     }
  6989.  
  6990. static void
  6991. EditComplete(Widget w,
  6992.          XEvent *event,
  6993.          String *params,
  6994.          Cardinal *nparam)
  6995.     {
  6996.     XmLGridWidget g;
  6997.  
  6998.     g = (XmLGridWidget)XtParent(w);
  6999.     TextAction(g, TEXT_EDIT_COMPLETE);
  7000.     if (*nparam == 1)
  7001.         Traverse(w, event, params, nparam);
  7002.     }
  7003.  
  7004. #ifndef MOTIF11
  7005. extern Widget _XmGetTextualDragIcon(Widget);
  7006. #endif
  7007.  
  7008. static void
  7009. DragStart(Widget w,
  7010.       XEvent *event,
  7011.       String *params,
  7012.       Cardinal *nparam)
  7013.     {
  7014. #ifndef MOTIF11
  7015.     XmLGridWidget g;
  7016.     Widget dragIcon;
  7017.     Atom exportTargets[1];
  7018.     Arg args[10];
  7019.     char *data;
  7020.     XButtonEvent *be;
  7021.     int row, col;
  7022.     XmLGridColumn colp;
  7023.     XmLGridRow rowp;
  7024.     XmLGridCell cell;
  7025.     static XtCallbackRec dragFinish[2] =
  7026.         { { DragFinish, NULL }, { NULL, NULL } };
  7027.  
  7028.     g = (XmLGridWidget)w;
  7029.     be = (XButtonEvent *)event;
  7030.     if (!g->grid.allowDrag || !be)
  7031.         return;
  7032.     if (XYToRowCol(g, be->x, be->y, &row, &col) == -1)
  7033.         return;
  7034.     rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  7035.     colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col);
  7036.     cell = GetCell(g, row, col);
  7037.     if (!rowp || !colp || !cell)
  7038.         return;
  7039.     if (XmLGridRowIsSelected(rowp) == False &&
  7040.         XmLGridColumnIsSelected(colp) == False &&
  7041.         XmLGridCellIsSelected(cell) == False)
  7042.         return;
  7043.     data = CopyDataCreate(g, 1, 0, 0, 0, 0);
  7044.     if (!data)
  7045.         return;
  7046.     dragIcon = _XmGetTextualDragIcon((Widget)w);
  7047.     exportTargets[0] = XA_STRING;
  7048.     dragFinish[0].closure = (XtPointer)data;
  7049.     XtSetArg(args[0], XmNconvertProc, DragConvert);
  7050.     XtSetArg(args[1], XmNexportTargets, exportTargets);
  7051.     XtSetArg(args[2], XmNnumExportTargets, 1);
  7052.     XtSetArg(args[3], XmNdragOperations, XmDROP_COPY);
  7053.     XtSetArg(args[4], XmNsourceCursorIcon, dragIcon);
  7054.     XtSetArg(args[4], XmNclientData, (XtPointer)data);
  7055.     XtSetArg(args[5], XmNdragDropFinishCallback, dragFinish);
  7056.     XmDragStart(w, event, args, 6);
  7057. #endif
  7058.     }
  7059.  
  7060. static Boolean
  7061. DragConvert(Widget w,
  7062.         Atom *selection,
  7063.         Atom *target,
  7064.         Atom *type,
  7065.         XtPointer *value,
  7066.         unsigned long *length,
  7067.         int *format)
  7068.     {
  7069. #ifdef MOTIF11
  7070.     return FALSE;
  7071. #else
  7072.     Atom targetsA, timestampA, multipleA, *exportTargets;
  7073.     int n;
  7074.     char *data, *dataCopy;
  7075.  
  7076.     if (!XmIsDragContext(w))
  7077.         return FALSE;
  7078.     targetsA = XInternAtom(XtDisplay(w), "TARGETS", FALSE);
  7079.     timestampA = XInternAtom(XtDisplay(w), "TIMESTAMP", FALSE);
  7080.     multipleA = XInternAtom(XtDisplay(w), "MULTIPLE", FALSE);
  7081.     if (*target == targetsA)
  7082.         {
  7083.         n = 4;
  7084.         exportTargets = (Atom *)XtMalloc(sizeof(Atom) * n);
  7085.         exportTargets[0] = XA_STRING;
  7086.         exportTargets[1] = targetsA;
  7087.         exportTargets[2] = multipleA;
  7088.         exportTargets[3] = timestampA;
  7089.         *type = XA_ATOM;
  7090.         *value = (XtPointer)exportTargets;
  7091.         *format = 32;
  7092.         *length = (n * sizeof(Atom)) >> 2;
  7093.         return TRUE;
  7094.         }
  7095.     else if (*target == XA_STRING)
  7096.         {
  7097.         XtVaGetValues(w, XmNclientData, &data, NULL);
  7098.           *type = XA_STRING;
  7099.         dataCopy = XtMalloc(strlen(data));
  7100.         strncpy(dataCopy, data, strlen(data));
  7101.           *value = (XtPointer)dataCopy;
  7102.           *length = strlen(data);
  7103.           *format = 8;
  7104.           return TRUE;
  7105.         }
  7106.     return FALSE;
  7107. #endif
  7108.     }
  7109.  
  7110. static void
  7111. DragFinish(Widget w,
  7112.        XtPointer clientData,
  7113.        XtPointer callData)
  7114.     {
  7115.     free ((char *)clientData);
  7116.     }
  7117.  
  7118. static void
  7119. DropRegister(XmLGridWidget g, Boolean set)
  7120.     {
  7121. #ifndef MOTIF11
  7122.     Atom importTargets[1];
  7123.     Arg args[4];
  7124.  
  7125.     if (set == True)
  7126.         {
  7127.         importTargets[0] = XA_STRING;
  7128.         XtSetArg(args[0], XmNdropSiteOperations, XmDROP_COPY);
  7129.         XtSetArg(args[1], XmNimportTargets, importTargets);
  7130.         XtSetArg(args[2], XmNnumImportTargets, 1);
  7131.         XtSetArg(args[3], XmNdropProc, DropStart);
  7132.         XmDropSiteRegister((Widget)g, args, 4);
  7133.         }
  7134.     else
  7135.         XmDropSiteUnregister((Widget)g);
  7136. #endif
  7137.     }
  7138.  
  7139. static void
  7140. DropStart(Widget w,
  7141.       XtPointer clientData,
  7142.       XtPointer callData)
  7143.     {
  7144. #ifndef MOTIF11
  7145.     XmLGridWidget g;
  7146.     XmDropProcCallbackStruct *cbs;
  7147.     XmDropTransferEntryRec te[2];
  7148.     Atom *exportTargets;
  7149.     Arg args[10];
  7150.     int row, col, i, n, valid;
  7151.  
  7152.     g = (XmLGridWidget)w;
  7153.     cbs = (XmDropProcCallbackStruct *)callData;
  7154.     if (g->grid.allowDrop == False || cbs->dropAction == XmDROP_HELP)
  7155.         {
  7156.         cbs->dropSiteStatus = XmINVALID_DROP_SITE;
  7157.         return;
  7158.         }
  7159.     valid = 0;
  7160.     if (XYToRowCol(g, cbs->x, cbs->y, &row, &col) != -1 &&
  7161.         cbs->dropAction == XmDROP && cbs->operation == XmDROP_COPY)
  7162.         {
  7163.         XtVaGetValues(cbs->dragContext,
  7164.             XmNexportTargets, &exportTargets,
  7165.             XmNnumExportTargets, &n,
  7166.             NULL);
  7167.         for (i = 0; i < n; i++)
  7168.             if (exportTargets[i] == XA_STRING)
  7169.                 valid = 1;
  7170.         }
  7171.     if (!valid)
  7172.         {
  7173.         cbs->operation = (long)XmDROP_NOOP;
  7174.         cbs->dropSiteStatus = XmINVALID_DROP_SITE;
  7175.         XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE);
  7176.         XtSetArg(args[1], XmNnumDropTransfers, 0);
  7177.         XmDropTransferStart(cbs->dragContext, args, 2);
  7178.         return;
  7179.         }
  7180.     g->grid.dropLoc.row = row;
  7181.     g->grid.dropLoc.col = col;
  7182.     cbs->operation = (long)XmDROP_COPY;
  7183.     te[0].target = XA_STRING;
  7184.     te[0].client_data = (XtPointer)g;
  7185.     XtSetArg(args[0], XmNdropTransfers, te);
  7186.     XtSetArg(args[1], XmNnumDropTransfers, 1);
  7187.     XtSetArg(args[2], XmNtransferProc, DropTransfer);
  7188.     XmDropTransferStart(cbs->dragContext, args, 3);
  7189. #endif
  7190.     }
  7191.  
  7192. static void
  7193. DropTransfer(Widget w,
  7194.          XtPointer clientData,
  7195.          Atom *selType,
  7196.          Atom *type,
  7197.          XtPointer value,
  7198.          unsigned long *length,
  7199.          int *format)
  7200.     {
  7201. #ifndef MOTIF11
  7202.     XmLGridWidget g;
  7203.     char *buf;
  7204.     int len;
  7205.  
  7206.     if (!value)
  7207.         return;
  7208.     g = (XmLGridWidget)clientData;
  7209.     len = (int)*length;
  7210.     if (len < 0)
  7211.         return;
  7212.     buf = (char *)malloc(len + 1);
  7213.     strncpy(buf, (char *)value, len);
  7214.     XtFree((char *)value);
  7215.     buf[len] = 0;
  7216.     Read(g, XmFORMAT_DROP, 0, g->grid.dropLoc.row, g->grid.dropLoc.col, buf);
  7217.     free((char *)buf);
  7218. #endif
  7219.     }
  7220.  
  7221. static void
  7222. Select(Widget w,
  7223.        XEvent *event,
  7224.        String *params,
  7225.        Cardinal *nparam)
  7226.     {
  7227.     XmLGridWidget g;
  7228.     Display *dpy;
  7229.     Window win;
  7230.     static XrmQuark qACTIVATE, qBEGIN, qEXTEND, qEND;
  7231.     static XrmQuark qTOGGLE;
  7232.     static int quarksValid = 0;
  7233.     XrmQuark q;
  7234.     int isVert;
  7235.     int row, col, clickTime, resizeRow, resizeCol;
  7236.     XButtonEvent *be;
  7237.     XRectangle rect;
  7238.     XmLGridRow rowp;
  7239.     XmLGridCell cellp;
  7240.     XmLGridColumn colp;
  7241.     XmLGridCallbackStruct cbs;
  7242.     Boolean flag;
  7243.  
  7244.     if (*nparam != 1)
  7245.         return;
  7246.  
  7247.     if (XmLIsGrid(w))
  7248.         g = (XmLGridWidget)w;
  7249.     else
  7250.         g = (XmLGridWidget)XtParent(w);
  7251.     dpy = XtDisplay(g);
  7252.     win = XtWindow(g);
  7253.     if (!quarksValid)
  7254.         {
  7255.         qACTIVATE = XrmStringToQuark("ACTIVATE");
  7256.         qBEGIN = XrmStringToQuark("BEGIN");
  7257.         qEXTEND = XrmStringToQuark("EXTEND");
  7258.         qEND = XrmStringToQuark("END");
  7259.         qTOGGLE = XrmStringToQuark("TOGGLE");
  7260.         }
  7261.     q = XrmStringToQuark(params[0]);
  7262.     be = 0;
  7263.     if (event->type == KeyPress || event->type == KeyRelease)
  7264.         {
  7265.         row = g->grid.focusRow;
  7266.         col = g->grid.focusCol;
  7267.         }
  7268.     else /* Button */
  7269.         {
  7270.         be = (XButtonEvent *)event;
  7271.         if (XYToRowCol(g, be->x, be->y, &row, &col) == -1)
  7272.             {
  7273.             row = -1;
  7274.             col = -1;
  7275.             }
  7276.         }
  7277.     /* double click activate check */
  7278.     if (q == qBEGIN && be)
  7279.         {
  7280.         clickTime = XtGetMultiClickTime(dpy);
  7281.         if (row != -1 && col != -1 &&
  7282.             row == g->grid.lastSelectRow && col == g->grid.lastSelectCol &&
  7283.             (be->time - g->grid.lastSelectTime) < clickTime)
  7284.             q = qACTIVATE;
  7285.         g->grid.lastSelectRow = row;
  7286.         g->grid.lastSelectCol = col;
  7287.         g->grid.lastSelectTime = be->time;
  7288.         }
  7289.     else if (q == qBEGIN)
  7290.         g->grid.lastSelectTime = 0;
  7291.  
  7292.     if (q == qBEGIN && be && PosIsResize(g, be->x, be->y,
  7293.         &resizeRow, &resizeCol, &isVert))
  7294.         {
  7295.         g->grid.resizeIsVert = isVert;
  7296.         g->grid.inMode = InResize;
  7297.         g->grid.resizeLineXY = -1; 
  7298.         g->grid.resizeRow = resizeRow;
  7299.         g->grid.resizeCol = resizeCol;
  7300.         if (isVert)
  7301.             {
  7302.             DrawResizeLine(g, be->y, 0);
  7303.             DefineCursor(g, CursorVResize);
  7304.             }
  7305.         else
  7306.             {
  7307.             DrawResizeLine(g, be->x, 0);
  7308.             DefineCursor(g, CursorHResize);
  7309.             }
  7310.         }
  7311.     else if (q == qBEGIN || q == qEXTEND || q == qTOGGLE)
  7312.         {
  7313.         if (g->grid.inMode != InNormal)
  7314.             return;
  7315.         if (row == -1 || col == -1)
  7316.             return;
  7317.         if (RowPosToType(g, row) == XmCONTENT &&
  7318.             ColPosToType(g, col) == XmCONTENT)
  7319.             {
  7320.             TextAction(g, TEXT_EDIT_COMPLETE);
  7321.             if (q != qEXTEND)
  7322.                 {
  7323.                 SetFocus(g, row, col, 0, 1);
  7324.                 ExtendSelect(g, event, False, -1, -1);
  7325.                 }
  7326.             XmProcessTraversal(g->grid.text, XmTRAVERSE_CURRENT);
  7327.             }
  7328.         if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW &&
  7329.             RowPosToType(g, row) == XmCONTENT)
  7330.             {
  7331.             flag = True;
  7332.             rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  7333.             if (q == qBEGIN && rowp && XmLGridRowIsSelected(rowp) == True)
  7334.                 flag = False;
  7335.             if (q == qTOGGLE && rowp && XmLGridRowIsSelected(rowp) == True)
  7336.                 flag = False;
  7337.             if (q == qBEGIN)
  7338.                 SelectTypeArea(g, SelectRow, event, -1, 0, False, True);
  7339.             if (be && q == qEXTEND)
  7340.                 ExtendSelect(g, event, False, row, col);
  7341.             else
  7342.                 SelectTypeArea(g, SelectRow, event,
  7343.                     RowPosToTypePos(g, XmCONTENT, row), 0, flag, True);
  7344.             }
  7345.         if (g->grid.selectionPolicy == XmSELECT_CELL)
  7346.             {
  7347.             if (q == qBEGIN)
  7348.                 {
  7349.                 SelectTypeArea(g, SelectCell, event, -1, -1, False, True);
  7350.                 SelectTypeArea(g, SelectRow, event, -1, 0, False, True);
  7351.                 SelectTypeArea(g, SelectCol, event, 0, -1, False, True);
  7352.                 }
  7353.             else if (q == qTOGGLE)
  7354.                 ExtendSelect(g, event, False, -1, -1);
  7355.             if (RowPosToType(g, row) == XmFOOTER ||
  7356.                 ColPosToType(g, col) == XmFOOTER)
  7357.                 ExtendSelect(g, event, False, -1, -1);
  7358.             if (be && q == qEXTEND)
  7359.                 ExtendSelect(g, event, False, row, col);
  7360.             else if (RowPosToType(g, row) == XmCONTENT &&
  7361.                 ColPosToType(g, col) == XmCONTENT)
  7362.                 {
  7363.                 flag = True;
  7364.                 cellp = GetCell(g, row, col);
  7365.                 if (q == qTOGGLE && cellp &&
  7366.                     XmLGridCellIsSelected(cellp) == True)
  7367.                     flag = False;
  7368.                 SelectTypeArea(g, SelectCell, event,
  7369.                     RowPosToTypePos(g, XmCONTENT, row),
  7370.                     ColPosToTypePos(g, XmCONTENT, col), flag, True);
  7371.                 }
  7372.             else if (RowPosToType(g, row) == XmHEADING &&
  7373.                 ColPosToType(g, col) == XmCONTENT)
  7374.                 {
  7375.                 if (q == qTOGGLE)
  7376.                     {
  7377.                     colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col);
  7378.                     if (colp && XmLGridColumnIsSelected(colp) == True)
  7379.                         g->grid.extendSelect = False;
  7380.                     }
  7381.                 ExtendSelect(g, event, True, row, col);
  7382.                 }
  7383.             else if (ColPosToType(g, col) == XmHEADING &&
  7384.                 RowPosToType(g, row) == XmCONTENT)
  7385.                 {
  7386.                 if (q == qTOGGLE)
  7387.                     {
  7388.                     rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  7389.                     if (rowp && XmLGridRowIsSelected(rowp) == True)
  7390.                         g->grid.extendSelect = False;
  7391.                     }
  7392.                 ExtendSelect(g, event, True, row, col);
  7393.                 }
  7394.             }
  7395.         if (g->grid.selectionPolicy == XmSELECT_SINGLE_ROW &&
  7396.             RowPosToType(g, row) == XmCONTENT)
  7397.             {
  7398.             flag = True;
  7399.             rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row);
  7400.             if (rowp && XmLGridRowIsSelected(rowp) == True)
  7401.                 flag = False;
  7402.             SelectTypeArea(g, SelectRow, event,
  7403.                 RowPosToTypePos(g, XmCONTENT, row), 0, flag, True);
  7404.             }
  7405.         if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW &&
  7406.             RowPosToType(g, row) == XmCONTENT)
  7407.             SelectTypeArea(g, SelectRow, event,
  7408.                 RowPosToTypePos(g, XmCONTENT, row), 0, True, True);
  7409.         if (g->grid.selectionPolicy == XmSELECT_NONE ||
  7410.             (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW &&
  7411.             RowPosToType(g, row) != XmCONTENT) ||
  7412.             (g->grid.selectionPolicy == XmSELECT_SINGLE_ROW &&
  7413.             RowPosToType(g, row) != XmCONTENT) ||
  7414.             (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW &&
  7415.             RowPosToType(g, row) != XmCONTENT) )
  7416.             {
  7417.             cbs.reason = XmCR_SELECT_CELL;
  7418.             cbs.event = event;
  7419.             cbs.columnType = ColPosToType(g, col);
  7420.             cbs.column = ColPosToTypePos(g, cbs.columnType, col);
  7421.             cbs.rowType = RowPosToType(g, row);
  7422.             cbs.row = RowPosToTypePos(g, cbs.rowType, row);
  7423.             XtCallCallbackList((Widget)g, g->grid.selectCallback,
  7424.                 (XtPointer)&cbs);
  7425.             }
  7426.         g->grid.inMode = InSelect;
  7427.         }
  7428.     else if (q == qEND && g->grid.inMode == InResize)
  7429.         {
  7430.         int r, c, width, height;
  7431.         r = g->grid.resizeRow;
  7432.         c = g->grid.resizeCol;
  7433.         g->grid.resizeRow = -1;
  7434.         g->grid.resizeCol = -1;
  7435.         if (!RowColToXY(g, r, c, False, &rect))
  7436.             {
  7437.             if (g->grid.resizeIsVert)
  7438.                 {
  7439.                 cbs.rowType = RowPosToType(g, r);
  7440.                 cbs.row = RowPosToTypePos(g, cbs.rowType, r);
  7441.                 height = 0;
  7442.                 if (g->grid.resizeLineXY > rect.y)
  7443.                     height = g->grid.resizeLineXY - rect.y -
  7444.                         (rect.height - GetRowHeight(g, r));
  7445.                 if (height < 6 && g->grid.allowRowHide == False)
  7446.                     height = 6;
  7447.                 XtVaSetValues((Widget)g,
  7448.                     XmNrowType, cbs.rowType,
  7449.                     XmNrow, cbs.row,
  7450.                     XmNrowHeight, height,
  7451.                     XmNrowSizePolicy, XmCONSTANT,
  7452.                     NULL);
  7453.                 cbs.reason = XmCR_RESIZE_ROW;
  7454.                 }
  7455.             else
  7456.                 {
  7457.                 cbs.columnType = ColPosToType(g, c);
  7458.                 cbs.column = ColPosToTypePos(g, cbs.columnType, c);
  7459.                 width = 0;
  7460.                 if (g->grid.resizeLineXY > rect.x)
  7461.                     width = g->grid.resizeLineXY - rect.x -
  7462.                         (rect.width - GetColWidth(g, c));
  7463.                 if (width < 6 && g->grid.allowColHide == False)
  7464.                     width = 6;
  7465.                 XtVaSetValues((Widget)g,
  7466.                     XmNcolumnType, cbs.columnType,
  7467.                     XmNcolumn, cbs.column,
  7468.                     XmNcolumnWidth, width,
  7469.                     XmNcolumnSizePolicy, XmCONSTANT,
  7470.                     NULL);
  7471.                 cbs.reason = XmCR_RESIZE_COLUMN;
  7472.                 }
  7473.             XtCallCallbackList((Widget)g, g->grid.resizeCallback,
  7474.                 (XtPointer)&cbs);
  7475.             }
  7476.         DrawResizeLine(g, 0, 2);
  7477.         DefineCursor(g, CursorNormal);
  7478.         g->grid.inMode = InNormal;
  7479.         }
  7480.     else if (q == qEND)
  7481.         {
  7482.         g->grid.inMode = InNormal;
  7483.         if (g->grid.dragTimerSet)
  7484.             XtRemoveTimeOut(g->grid.dragTimerId);
  7485.         g->grid.dragTimerSet = 0;
  7486.  
  7487.         /* XFE Additions to handle button up events in menus - they generate activate events */
  7488.           {
  7489.             if (XmIsMenuShell(XmLShellOfWidget((Widget)g)))
  7490.             {
  7491.               cbs.reason = XmCR_ACTIVATE;
  7492.               cbs.event = event;
  7493.               cbs.columnType = ColPosToType(g, col);
  7494.               cbs.column = ColPosToTypePos(g, cbs.columnType, col);
  7495.               cbs.rowType = RowPosToType(g, row);
  7496.               cbs.row = RowPosToTypePos(g, cbs.rowType, row);
  7497.               XtCallCallbackList((Widget)g, g->grid.activateCallback,
  7498.                      (XtPointer)&cbs);              
  7499.             }
  7500.           }
  7501.         }
  7502.     if (q == qACTIVATE)
  7503.         {
  7504.         cbs.reason = XmCR_ACTIVATE;
  7505.         cbs.event = event;
  7506.         cbs.columnType = ColPosToType(g, col);
  7507.         cbs.column = ColPosToTypePos(g, cbs.columnType, col);
  7508.         cbs.rowType = RowPosToType(g, row);
  7509.         cbs.row = RowPosToTypePos(g, cbs.rowType, row);
  7510.         XtCallCallbackList((Widget)g, g->grid.activateCallback,
  7511.             (XtPointer)&cbs);
  7512.         }
  7513.     }
  7514.  
  7515. static void
  7516. Traverse(Widget w,
  7517.      XEvent *event,
  7518.      String *params,
  7519.      Cardinal *nparam)
  7520.     {
  7521.     XmLGridWidget g;
  7522.     static XrmQuark qDOWN, qEXTEND_DOWN, qEXTEND_LEFT;
  7523.     static XrmQuark qEXTEND_PAGE_DOWN, qEXTEND_PAGE_LEFT;
  7524.     static XrmQuark qEXTEND_PAGE_RIGHT, qEXTEND_PAGE_UP;
  7525.     static XrmQuark qEXTEND_RIGHT, qEXTEND_UP, qLEFT, qPAGE_DOWN;
  7526.     static XrmQuark qPAGE_LEFT, qPAGE_RIGHT, qPAGE_UP, qRIGHT;
  7527.     static XrmQuark qTO_BOTTOM, qTO_BOTTOM_RIGHT, qTO_LEFT;
  7528.     static XrmQuark qTO_RIGHT, qTO_TOP, qTO_TOP_LEFT, qUP;
  7529.     static int quarksValid = 0;
  7530.     int extend, focusRow, focusCol, rowDir, colDir;
  7531.     int rowLoc, colLoc, prevRowLoc, prevColLoc;
  7532.     int scrollRow, scrollCol, prevScrollRow, prevScrollCol;
  7533.     XrmQuark q;
  7534.  
  7535.     g = (XmLGridWidget)XtParent(w);
  7536.     if (*nparam != 1)
  7537.         return;
  7538.     if (!quarksValid)
  7539.         {
  7540.         qDOWN = XrmStringToQuark("DOWN");
  7541.         qEXTEND_DOWN = XrmStringToQuark("EXTEND_DOWN");
  7542.         qEXTEND_LEFT = XrmStringToQuark("EXTEND_LEFT");
  7543.         qEXTEND_PAGE_DOWN = XrmStringToQuark("EXTEND_PAGE_DOWN");
  7544.         qEXTEND_PAGE_LEFT = XrmStringToQuark("EXTEND_PAGE_LEFT");
  7545.         qEXTEND_PAGE_RIGHT = XrmStringToQuark("EXTEND_PAGE_RIGHT");
  7546.         qEXTEND_PAGE_UP = XrmStringToQuark("EXTEND_PAGE_UP");
  7547.         qEXTEND_RIGHT = XrmStringToQuark("EXTEND_RIGHT");
  7548.         qEXTEND_UP = XrmStringToQuark("EXTEND_UP");
  7549.         qLEFT = XrmStringToQuark("LEFT");
  7550.         qPAGE_DOWN = XrmStringToQuark("PAGE_DOWN");
  7551.         qPAGE_LEFT = XrmStringToQuark("PAGE_LEFT");
  7552.         qPAGE_RIGHT = XrmStringToQuark("PAGE_RIGHT");
  7553.         qPAGE_UP = XrmStringToQuark("PAGE_UP");
  7554.         qRIGHT = XrmStringToQuark("RIGHT");
  7555.         qTO_BOTTOM = XrmStringToQuark("TO_BOTTOM");
  7556.         qTO_BOTTOM_RIGHT = XrmStringToQuark("TO_BOTTOM_RIGHT");
  7557.         qTO_LEFT = XrmStringToQuark("TO_LEFT");
  7558.         qTO_RIGHT = XrmStringToQuark("TO_RIGHT");
  7559.         qTO_TOP = XrmStringToQuark("TO_TOP");
  7560.         qTO_TOP_LEFT = XrmStringToQuark("TO_TOP_LEFT");
  7561.         qUP = XrmStringToQuark("UP");
  7562.         quarksValid = 1;
  7563.         }
  7564.     q = XrmStringToQuark(params[0]);
  7565.     extend = 0;
  7566.     /* map the extends to their counterparts and set extend flag */
  7567.     if (q == qEXTEND_DOWN)
  7568.         {
  7569.         q = qDOWN;
  7570.         extend = 1;
  7571.         }
  7572.     else if (q == qEXTEND_LEFT)
  7573.         {
  7574.         q = qLEFT;
  7575.         extend = 1;
  7576.         }
  7577.     else if (q == qEXTEND_PAGE_DOWN)
  7578.         {
  7579.         q = qPAGE_DOWN;
  7580.         extend = 1;
  7581.         }
  7582.     else if (q == qEXTEND_PAGE_LEFT)
  7583.         {
  7584.         q = qPAGE_LEFT;
  7585.         extend = 1;
  7586.         }
  7587.     else if (q == qEXTEND_PAGE_RIGHT)
  7588.         {
  7589.         q = qPAGE_RIGHT;
  7590.         extend = 1;
  7591.         }
  7592.     else if (q == qEXTEND_PAGE_UP)
  7593.         {
  7594.         q = qPAGE_UP;
  7595.         extend = 1;
  7596.         }
  7597.     else if (q == qEXTEND_RIGHT)
  7598.         {
  7599.         q = qRIGHT;
  7600.         extend = 1;
  7601.         }
  7602.     else if (q == qEXTEND_UP)
  7603.         {
  7604.         q = qUP;
  7605.         extend = 1;
  7606.         }
  7607.     if (extend && g->grid.selectionPolicy != XmSELECT_MULTIPLE_ROW &&
  7608.         g->grid.selectionPolicy != XmSELECT_CELL)
  7609.         return;
  7610.     if (extend && g->grid.extendRow != -1 && g->grid.extendCol != -1)
  7611.         {
  7612.         focusRow = g->grid.extendToRow;
  7613.         focusCol = g->grid.extendToCol;
  7614.         }
  7615.     else
  7616.         {
  7617.         focusRow = g->grid.focusRow;
  7618.         focusCol = g->grid.focusCol;
  7619.         }
  7620.     rowDir = 0;
  7621.     colDir = 0;
  7622.     if (focusRow < g->grid.topFixedCount)
  7623.         prevRowLoc = 0;
  7624.     else if (focusRow >= XmLArrayGetCount(g->grid.rowArray) -
  7625.         g->grid.bottomFixedCount)
  7626.         prevRowLoc = 2;
  7627.     else
  7628.         prevRowLoc = 1;
  7629.     if (focusCol < g->grid.leftFixedCount)
  7630.         prevColLoc = 0;
  7631.     else if (focusCol >= XmLArrayGetCount(g->grid.colArray) -
  7632.         g->grid.rightFixedCount)
  7633.         prevColLoc = 2;
  7634.     else
  7635.         prevColLoc = 1;
  7636.     /* calculate new focus row, col and walk direction */
  7637.     if (q == qDOWN)
  7638.         {
  7639.         focusRow++;
  7640.         rowDir = 1;
  7641.         }
  7642.     else if (q == qLEFT)
  7643.         {
  7644.         focusCol--;
  7645.         colDir = -1;
  7646.         }
  7647.     else if (q == qPAGE_DOWN)
  7648.         {
  7649.         if (prevRowLoc == 1)
  7650.             focusRow = g->grid.reg[4].row + g->grid.reg[4].nrow - 1;
  7651.         if (focusRow == g->grid.focusRow)
  7652.             focusRow += 4;
  7653.         rowDir = 1;
  7654.         }
  7655.     else if (q == qPAGE_LEFT)
  7656.         {
  7657.         if (prevColLoc == 1)
  7658.             focusCol = g->grid.reg[4].col - 1;
  7659.         if (focusCol == g->grid.focusCol)
  7660.             focusCol -= 4;
  7661.         colDir = -1;
  7662.         }
  7663.     else if (q == qPAGE_RIGHT)
  7664.         {
  7665.         if (prevColLoc == 1)
  7666.             focusCol = g->grid.reg[4].col + g->grid.reg[4].ncol - 1;
  7667.         if (focusCol == g->grid.focusCol)
  7668.             focusCol += 4;
  7669.         colDir = 1;
  7670.         }
  7671.     else if (q == qPAGE_UP)
  7672.         {
  7673.         if (prevRowLoc == 1)
  7674.             focusRow = g->grid.reg[4].row - 1;
  7675.         if (focusRow == g->grid.focusRow)
  7676.             focusRow -= 4;
  7677.         rowDir = -1;
  7678.         }
  7679.     else if (q == qRIGHT)
  7680.         {
  7681.         focusCol++;
  7682.         colDir = 1;
  7683.         }
  7684.     else if (q == qTO_BOTTOM)
  7685.         {
  7686.         focusRow = XmLArrayGetCount(g->grid.rowArray) - 1;
  7687.         rowDir = -1;
  7688.         }
  7689.     else if (q == qTO_BOTTOM_RIGHT)
  7690.         {
  7691.         focusCol = XmLArrayGetCount(g->grid.colArray) - 1;
  7692.         focusRow = XmLArrayGetCount(g->grid.rowArray) - 1;
  7693.         rowDir = -1;
  7694.         colDir = -1;
  7695.         }
  7696.     else if (q == qTO_LEFT)
  7697.         {
  7698.         focusCol = 0;
  7699.         colDir = 1;
  7700.         }
  7701.     else if (q == qTO_RIGHT)
  7702.         {
  7703.         focusCol = XmLArrayGetCount(g->grid.colArray) - 1;
  7704.         colDir = -1;
  7705.         }
  7706.     else if (q == qTO_TOP)
  7707.         {
  7708.         focusRow = 0;
  7709.         rowDir = 1;
  7710.         }
  7711.     else if (q == qTO_TOP_LEFT)
  7712.         {
  7713.         focusCol = 0;
  7714.         focusRow = 0;
  7715.         rowDir = 1;
  7716.         colDir = 1;
  7717.         }
  7718.     else if (q == qUP)
  7719.         {
  7720.         focusRow -= 1;
  7721.         rowDir = -1;
  7722.         }
  7723.     if (!rowDir && !colDir)
  7724.         return;
  7725.     if (extend)
  7726.         {
  7727.         if (FindNextFocus(g, focusRow, focusCol, rowDir, colDir,
  7728.             &focusRow, &focusCol) == -1)
  7729.             return;
  7730.         ExtendSelect(g, event, False, focusRow, focusCol);
  7731.         }
  7732.     else
  7733.         {
  7734.         if (SetFocus(g, focusRow, focusCol, rowDir, colDir) == -1)
  7735.             return;
  7736.         ExtendSelect(g, event, False, -1, -1);
  7737.         focusRow = g->grid.focusRow;
  7738.         focusCol = g->grid.focusCol;
  7739.         if (g->grid.selectionPolicy == XmSELECT_CELL)
  7740.             {
  7741.             SelectTypeArea(g, SelectRow, event, -1, 0, False, True);
  7742.             SelectTypeArea(g, SelectCol, event, 0, -1, False, True);
  7743.             SelectTypeArea(g, SelectCell, event, -1, -1, False, True);
  7744.             SelectTypeArea(g, SelectCell, event,
  7745.                 RowPosToTypePos(g, XmCONTENT, focusRow),
  7746.                 ColPosToTypePos(g, XmCONTENT, focusCol),
  7747.                 True, True);
  7748.             }
  7749.         else if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW)
  7750.             SelectTypeArea(g, SelectRow, event,
  7751.                 RowPosToTypePos(g, XmCONTENT, focusRow), 0, True, True);
  7752.         }
  7753.     scrollRow = -1;
  7754.     scrollCol = -1;
  7755.     if (q == qPAGE_UP)
  7756.         scrollRow = ScrollRowBottomPos(g, focusRow);
  7757.     else if (q == qPAGE_DOWN)
  7758.         scrollRow = focusRow;
  7759.     else if (q == qPAGE_LEFT)
  7760.         scrollCol = ScrollColRightPos(g, focusCol);
  7761.     else if (q == qPAGE_RIGHT)
  7762.         scrollCol = focusCol;
  7763.     else
  7764.         {
  7765.         if (focusRow < g->grid.topFixedCount)
  7766.             rowLoc = 0;
  7767.         else if (focusRow >= XmLArrayGetCount(g->grid.rowArray) -
  7768.             g->grid.bottomFixedCount)
  7769.             rowLoc = 2;
  7770.         else
  7771.             rowLoc = 1;
  7772.         if (prevRowLoc != 0 && rowLoc == 0)
  7773.             scrollRow = g->grid.reg[0].nrow;
  7774.         else if (prevRowLoc != 2 && rowLoc == 2)
  7775.             scrollRow = g->grid.reg[6].row - 1;
  7776.  
  7777.         if (focusCol < g->grid.leftFixedCount)
  7778.             colLoc = 0;
  7779.         else if (focusCol >= XmLArrayGetCount(g->grid.colArray) -
  7780.             g->grid.rightFixedCount)
  7781.             colLoc = 2;
  7782.         else
  7783.             colLoc = 1;
  7784.         if (prevColLoc != 0 && colLoc == 0)
  7785.             scrollCol = g->grid.reg[0].ncol;
  7786.         else if (prevColLoc != 2 && colLoc == 2)
  7787.             scrollCol = g->grid.reg[2].col - 1;
  7788.         }
  7789.     if (g->grid.vsPolicy == XmVARIABLE)
  7790.         ;
  7791.     else if (scrollRow != -1)
  7792.         {
  7793.         prevScrollRow = g->grid.scrollRow;
  7794.         g->grid.scrollRow = scrollRow;
  7795.         VertLayout(g, 0);
  7796.         if (g->grid.scrollRow != prevScrollRow)
  7797.             DrawArea(g, DrawVScroll, 0, 0);
  7798.         }
  7799.     else
  7800.         MakeRowVisible(g, focusRow);
  7801.     if (g->grid.hsPolicy == XmVARIABLE)
  7802.         ;
  7803.     else if (scrollCol != -1)
  7804.         {
  7805.         prevScrollCol = g->grid.scrollCol;
  7806.         g->grid.scrollCol = scrollCol;
  7807.         HorizLayout(g, 0);
  7808.         if (g->grid.scrollCol != prevScrollCol)
  7809.             DrawArea(g, DrawHScroll, 0, 0);
  7810.         }
  7811.     else
  7812.         MakeColVisible(g, focusCol);
  7813.     }
  7814.  
  7815. static void
  7816. TextActivate(Widget w,
  7817.          XtPointer clientData,
  7818.          XtPointer callData)
  7819.     {
  7820.     XmLGridWidget g;
  7821.     XmAnyCallbackStruct *cbs;
  7822.     String params[1];
  7823.     Cardinal nparam;
  7824.  
  7825.     cbs = (XmAnyCallbackStruct *)callData;
  7826.     g = (XmLGridWidget)XtParent(w);
  7827.     if (g->grid.inEdit)
  7828.         {
  7829.         nparam = 0;
  7830.         EditComplete(w, cbs->event, params, &nparam);
  7831.         }
  7832.     else
  7833.         {
  7834.         params[0] = "ACTIVATE";
  7835.         nparam = 1;
  7836.         Select(XtParent(w), cbs->event, params, &nparam);
  7837.         }
  7838.     }
  7839.  
  7840. static void
  7841. TextFocus(Widget w,
  7842.       XtPointer clientData,
  7843.       XtPointer callData)
  7844.     {
  7845.     XmLGridWidget g;
  7846.     XmAnyCallbackStruct *cbs;
  7847.     int focusRow, focusCol;
  7848.  
  7849.     cbs = (XmAnyCallbackStruct *)callData;
  7850.     g = (XmLGridWidget)XtParent(w);
  7851.     if (cbs->reason == XmCR_FOCUS)
  7852.         g->grid.focusIn = 1;
  7853.     else
  7854.         g->grid.focusIn = 0;
  7855.     focusRow = g->grid.focusRow;
  7856.     focusCol = g->grid.focusCol;
  7857.     if (focusRow != -1 && focusCol != -1)
  7858.         {
  7859.         if (g->grid.highlightRowMode == True)
  7860.             DrawArea(g, DrawRow, focusRow, 0);
  7861.         else
  7862.             DrawArea(g, DrawCell, focusRow, focusCol);
  7863.         }
  7864.     }
  7865.  
  7866. static void
  7867. TextMapped(Widget w,
  7868.        XtPointer clientData,
  7869.        XEvent *event,
  7870.        Boolean *con)
  7871.     {
  7872.     XmLGridWidget g;
  7873.  
  7874.     g = (XmLGridWidget)(XtParent(w));
  7875.     if (event->type != MapNotify)
  7876.         return;
  7877.     if (g->grid.textHidden)
  7878.         XtUnmapWidget(g->grid.text);
  7879.     }
  7880.  
  7881. static void
  7882. TextModifyVerify(Widget w,
  7883.          XtPointer clientData,
  7884.          XtPointer callData)
  7885.     {
  7886.     XmLGridWidget g;
  7887.     XmTextVerifyCallbackStruct *cbs;
  7888.  
  7889.     g = (XmLGridWidget)XtParent(w);
  7890.     cbs = (XmTextVerifyCallbackStruct *)callData;
  7891.     if (!cbs->event || g->grid.ignoreModifyVerify || g->grid.inEdit)
  7892.         return;
  7893.     TextAction(g, TEXT_EDIT);
  7894.     if (!g->grid.inEdit)
  7895.         cbs->doit = False;
  7896.     }
  7897.  
  7898. /*
  7899.    XmLGridRow
  7900. */
  7901.  
  7902. static
  7903. XmLGridRow XmLGridRowNew(Widget grid)
  7904.     {
  7905.     return XmLGridClassPartOfWidget(grid).rowNewProc(grid);
  7906.     }
  7907.  
  7908. /* Only to be called through Grid class */
  7909. static XmLGridRow 
  7910. _GridRowNew(Widget grid)
  7911.     {
  7912.     XmLGridWidget g;
  7913.     XmLGridRow row;
  7914.     int size;
  7915.  
  7916.     g = (XmLGridWidget)grid;
  7917.     size = XmLGridClassPartOfWidget(grid).rowRecSize;
  7918.     row = (XmLGridRow)malloc(size);
  7919.     row->grid.grid = grid;
  7920.     row->grid.heightInPixels = 0;
  7921.     row->grid.heightInPixelsValid = 0;
  7922.     row->grid.height = 1;
  7923.     row->grid.selected = False;
  7924.     row->grid.sizePolicy = XmVARIABLE;
  7925.     row->grid.userData = 0;
  7926.     row->grid.cellArray = XmLArrayNew(0, 0);
  7927.     return row;
  7928.     }
  7929.  
  7930. static void
  7931. XmLGridRowFree(Widget grid,
  7932.            XmLGridRow row)
  7933.     {
  7934.     XmLGridClassPartOfWidget(grid).rowFreeProc(row);
  7935.     }
  7936.  
  7937. /* Only to be called through Grid class */
  7938. static void
  7939. _GridRowFree(XmLGridRow row)
  7940.     {
  7941.     int i, count;
  7942.  
  7943.     count = XmLArrayGetCount(row->grid.cellArray);
  7944.     for (i = 0; i < count; i++)
  7945.         XmLGridCellFree(row->grid.grid,
  7946.             (XmLGridCell)XmLArrayGet(row->grid.cellArray, i));
  7947.     XmLArrayFree(row->grid.cellArray);
  7948.     free ((char *)row);
  7949.     }
  7950.  
  7951. static
  7952. XmLArray XmLGridRowCells(XmLGridRow row)
  7953.     {
  7954.     return row->grid.cellArray;
  7955.     }
  7956.  
  7957. static int
  7958. XmLGridRowGetPos(XmLGridRow row)
  7959.     {
  7960.     return row->grid.pos;
  7961.     }
  7962.  
  7963. static int
  7964. XmLGridRowGetVisPos(XmLGridRow row)
  7965.     {
  7966.     return row->grid.visPos;
  7967.     }
  7968.  
  7969. static Boolean
  7970. XmLGridRowIsHidden(XmLGridRow row)
  7971.     {
  7972.     if (!row->grid.height)
  7973.         return True;
  7974.     return False;
  7975.     }
  7976.  
  7977. static Boolean
  7978. XmLGridRowIsSelected(XmLGridRow row)
  7979.     {
  7980.     return row->grid.selected;
  7981.     }
  7982.  
  7983. static void
  7984. XmLGridRowSetSelected(XmLGridRow row,
  7985.               Boolean selected)
  7986.     {
  7987.     row->grid.selected = selected;
  7988.     }
  7989.  
  7990. static void
  7991. XmLGridRowSetVisPos(XmLGridRow row,
  7992.             int visPos)
  7993.     {
  7994.     row->grid.visPos = visPos;
  7995.     }
  7996.  
  7997. static int
  7998. XmLGridRowHeightInPixels(XmLGridRow row)
  7999.     {
  8000.     int i, count;
  8001.     Dimension height, maxHeight;
  8002.     XmLGridWidget g;
  8003.     XmLGridCell cell;
  8004.     XmLGridCallbackStruct cbs;
  8005.     XmLGridCellRefValues *cellValues;
  8006.  
  8007.     if (row->grid.sizePolicy == XmCONSTANT)
  8008.         return row->grid.height;
  8009.     if (!row->grid.height)
  8010.         return 0;
  8011.     if (!row->grid.heightInPixelsValid)
  8012.         {
  8013.         g = (XmLGridWidget)row->grid.grid;
  8014.         count = XmLArrayGetCount(row->grid.cellArray);
  8015.         if (!count)
  8016.             {
  8017.             cellValues = g->grid.defCellValues;
  8018.             maxHeight = 4 + row->grid.height * cellValues->fontHeight +
  8019.                 cellValues->topMargin + cellValues->bottomMargin;
  8020.             }
  8021.         else
  8022.             maxHeight = 0;
  8023.         for (i = 0; i < count; i++)
  8024.             {
  8025.             cell = (XmLGridCell)XmLArrayGet(row->grid.cellArray, i);
  8026.             cbs.reason = XmCR_PREF_HEIGHT;
  8027.             cbs.rowType = RowPosToType(g, row->grid.pos);
  8028.             cbs.row = RowPosToTypePos(g, cbs.rowType, row->grid.pos);
  8029.             cbs.columnType = ColPosToType(g, i);
  8030.             cbs.column = ColPosToTypePos(g, cbs.columnType, i);
  8031.             cbs.object = (void *)row;
  8032.             height = XmLGridCellAction(cell, (Widget)g, &cbs);
  8033.             if (height > maxHeight)
  8034.                 maxHeight = height;
  8035.             }
  8036.         row->grid.heightInPixels = maxHeight;
  8037.         row->grid.heightInPixelsValid = 1;
  8038.         }
  8039.     return row->grid.heightInPixels;
  8040.     }
  8041.  
  8042. static void
  8043. XmLGridRowHeightChanged(XmLGridRow row)
  8044.     {
  8045.     row->grid.heightInPixelsValid = 0;
  8046.     }
  8047.  
  8048. /*
  8049.    XmLGridColumn
  8050. */
  8051.  
  8052. static XmLGridColumn
  8053. XmLGridColumnNew(Widget grid)
  8054.     {
  8055.     return XmLGridClassPartOfWidget(grid).columnNewProc(grid);
  8056.     }
  8057.  
  8058. /* Only to be called through Grid class */
  8059. static XmLGridColumn 
  8060. _GridColumnNew(Widget grid)
  8061.     {
  8062.     XmLGridWidget g;
  8063.     XmLGridColumn column;
  8064.     int size;
  8065.  
  8066.     g = (XmLGridWidget)grid;
  8067.     size = XmLGridClassPartOfWidget(grid).columnRecSize;
  8068.     column = (XmLGridColumn)malloc(size);
  8069.     column->grid.grid = grid;
  8070.     column->grid.widthInPixels = 0;
  8071.     column->grid.widthInPixelsValid = 0;
  8072.     column->grid.defCellValues = 0;
  8073.     column->grid.selected = False;
  8074.     column->grid.sizePolicy = XmVARIABLE;
  8075.     column->grid.width = 8;
  8076.     column->grid.userData = 0;
  8077.     column->grid.resizable = True;
  8078.     return column;
  8079.     }
  8080.  
  8081. static void
  8082. XmLGridColumnFree(Widget grid,
  8083.           XmLGridColumn column)
  8084.     {
  8085.     XmLGridClassPartOfWidget(grid).columnFreeProc(column);
  8086.     }
  8087.  
  8088. /* Only to be called through Grid class */
  8089. static void
  8090. _GridColumnFree(XmLGridColumn column)
  8091.     {
  8092.     if (column->grid.defCellValues)
  8093.         XmLGridCellDerefValues(column->grid.defCellValues);
  8094.     free((char *)column);
  8095.     }
  8096.  
  8097. static int
  8098. XmLGridColumnGetPos(XmLGridColumn column)
  8099.     {
  8100.     return column->grid.pos;
  8101.     }
  8102.  
  8103. static int
  8104. XmLGridColumnGetVisPos(XmLGridColumn column)
  8105.     {
  8106.     return column->grid.visPos;
  8107.     }
  8108.  
  8109. static Boolean
  8110. XmLGridColumnIsHidden(XmLGridColumn column)
  8111.     {
  8112.     if (!column->grid.width)
  8113.         return True;
  8114.     return False;
  8115.     }
  8116.  
  8117. static Boolean
  8118. XmLGridColumnIsSelected(XmLGridColumn column)
  8119.     {
  8120.     return column->grid.selected;
  8121.     }
  8122.  
  8123. static void
  8124. XmLGridColumnSetSelected(XmLGridColumn column,
  8125.              Boolean selected)
  8126.     {
  8127.     column->grid.selected = selected;
  8128.     }
  8129.  
  8130. static void
  8131. XmLGridColumnSetVisPos(XmLGridColumn column,
  8132.                int visPos)
  8133.     {
  8134.     column->grid.visPos = visPos;
  8135.     }
  8136.  
  8137. static int
  8138. XmLGridColumnWidthInPixels(XmLGridColumn column)
  8139.     {
  8140.     int i, count;
  8141.     Dimension width, maxWidth;
  8142.     XmLGridCell cell;
  8143.     XmLGridWidget g;
  8144.     XmLGridCallbackStruct cbs;
  8145.     XmLGridCellRefValues *cellValues;
  8146.  
  8147.     if (column->grid.sizePolicy == XmCONSTANT)
  8148.         return column->grid.width;
  8149.     if (!column->grid.width)
  8150.         return 0;
  8151.     if (!column->grid.widthInPixelsValid)
  8152.         {
  8153.         g = (XmLGridWidget)column->grid.grid;
  8154.         count = XmLArrayGetCount(g->grid.rowArray);
  8155.         if (!count)
  8156.             {
  8157.             cellValues = g->grid.defCellValues;
  8158.             maxWidth = 4 + column->grid.width * cellValues->fontWidth +
  8159.                 cellValues->leftMargin + cellValues->rightMargin;
  8160.             }
  8161.         else
  8162.             maxWidth = 0;
  8163.         for (i = 0; i < count; i++)
  8164.             {
  8165.             cell = GetCell(g, i, column->grid.pos);
  8166.             cbs.reason = XmCR_PREF_WIDTH;
  8167.             cbs.rowType = RowPosToType(g, i);
  8168.             cbs.row = RowPosToTypePos(g, cbs.rowType, i);
  8169.             cbs.columnType = ColPosToType(g, column->grid.pos);
  8170.             cbs.column = ColPosToTypePos(g, cbs.columnType, column->grid.pos);
  8171.             cbs.object = (void *)column;
  8172.             width = XmLGridCellAction(cell, (Widget)g, &cbs);
  8173.             if (width > maxWidth)
  8174.                 maxWidth = width;
  8175.             }
  8176.         column->grid.widthInPixels = maxWidth;
  8177.         column->grid.widthInPixelsValid = 1;
  8178.         }
  8179.     return column->grid.widthInPixels;
  8180.     }
  8181.  
  8182. static void
  8183. XmLGridColumnWidthChanged(XmLGridColumn column)
  8184.     {
  8185.     column->grid.widthInPixelsValid = 0;
  8186.     }
  8187.  
  8188. /*
  8189.    XmLGridCell
  8190. */
  8191.  
  8192. static XmLGridCell
  8193. XmLGridCellNew(void)
  8194.     {
  8195.     XmLGridCell c;
  8196.  
  8197.     c = (XmLGridCell)malloc(sizeof(struct _XmLGridCellRec));
  8198.     c->cell.refValues = 0;
  8199.     c->cell.flags = 0;
  8200.     return c;
  8201.     }
  8202.  
  8203. static void
  8204. XmLGridCellFree(Widget grid,
  8205.         XmLGridCell cell)
  8206.     {
  8207.     XmLGridCallbackStruct cbs;
  8208.  
  8209.     cbs.reason = XmCR_FREE_VALUE;
  8210.     XmLGridCellAction(cell, grid, &cbs);
  8211.     XmLGridCellDerefValues(cell->cell.refValues);
  8212.     free((char *)cell);
  8213.     }
  8214.  
  8215. static int
  8216. XmLGridCellAction(XmLGridCell cell,
  8217.           Widget w,
  8218.           XmLGridCallbackStruct *cbs)
  8219.     {
  8220.     return XmLGridClassPartOfWidget(w).cellActionProc(cell, w, cbs);
  8221.     }
  8222.  
  8223. /* Only to be called through Grid class */
  8224. static int
  8225. _GridCellAction(XmLGridCell cell,
  8226.         Widget w,
  8227.         XmLGridCallbackStruct *cbs)
  8228.     {
  8229.     int ret;
  8230.  
  8231.     ret = 0;
  8232.     switch (cbs->reason)
  8233.         {
  8234.         case XmCR_CELL_DRAW:
  8235.             _XmLGridCellDrawBackground(cell, w, cbs->clipRect, cbs->drawInfo);
  8236.             _XmLGridCellDrawValue(cell, w, cbs->clipRect, cbs->drawInfo);
  8237.             _XmLGridCellDrawBorders(cell, w, cbs->clipRect, cbs->drawInfo);
  8238.             break;
  8239.         case XmCR_CELL_FOCUS_IN:
  8240.             break;
  8241.         case XmCR_CELL_FOCUS_OUT:
  8242.             break;
  8243.         case XmCR_CONF_TEXT:
  8244.             _XmLGridCellConfigureText(cell, w, cbs->clipRect);
  8245.             break;
  8246.         case XmCR_EDIT_BEGIN:
  8247.             ret = _XmLGridCellBeginTextEdit(cell, w, cbs->clipRect);
  8248.             break;
  8249.         case XmCR_EDIT_CANCEL:
  8250.             break;
  8251.         case XmCR_EDIT_COMPLETE:
  8252.             _XmLGridCellCompleteTextEdit(cell, w);
  8253.             break;
  8254.         case XmCR_EDIT_INSERT:
  8255.             ret = _XmLGridCellBeginTextEdit(cell, w, cbs->clipRect);
  8256.             if (ret)
  8257.                 _XmLGridCellInsertText(cell, w);
  8258.             break;
  8259.         case XmCR_FREE_VALUE:
  8260.             _XmLGridCellFreeValue(cell);
  8261.             break;
  8262.         case XmCR_PREF_HEIGHT:
  8263.             ret = _XmLGridCellGetHeight(cell, w,(XmLGridRow)cbs->object);
  8264.             break;
  8265.         case XmCR_PREF_WIDTH:
  8266.             ret = _XmLGridCellGetWidth(cell, w,(XmLGridColumn)cbs->object);
  8267.             break;
  8268.         }
  8269.     return ret;
  8270.     }
  8271.  
  8272. static XmLGridCellRefValues *
  8273. XmLGridCellGetRefValues(XmLGridCell cell)
  8274.     {
  8275.     return cell->cell.refValues;
  8276.     }
  8277.  
  8278. static void
  8279. XmLGridCellSetRefValues(XmLGridCell cell,
  8280.             XmLGridCellRefValues *values)
  8281.     {
  8282.     values->refCount++;
  8283.     XmLGridCellDerefValues(cell->cell.refValues);
  8284.     cell->cell.refValues = values;
  8285.     }
  8286.  
  8287. static void
  8288. XmLGridCellDerefValues(XmLGridCellRefValues *values)
  8289.     {
  8290.     if (!values)
  8291.         return;
  8292.     values->refCount--;
  8293.     if (!values->refCount)
  8294.         {
  8295.         XmFontListFree(values->fontList);
  8296.         free((char *)values);
  8297.         }
  8298.     }
  8299.  
  8300. static Boolean
  8301. XmLGridCellInRowSpan(XmLGridCell cell)
  8302.     {
  8303.     if (cell->cell.flags & XmLGridCellInRowSpanFlag)
  8304.         return True;
  8305.     return False;
  8306.     }
  8307.  
  8308. static Boolean
  8309. XmLGridCellInColumnSpan(XmLGridCell cell)
  8310.     {
  8311.     if (cell->cell.flags & XmLGridCellInColumnSpanFlag)
  8312.         return True;
  8313.     return False;
  8314.     }
  8315.  
  8316. static Boolean
  8317. XmLGridCellIsSelected(XmLGridCell cell)
  8318.     {
  8319.     if (cell->cell.flags & XmLGridCellSelectedFlag)
  8320.         return True;
  8321.     return False;
  8322.     }
  8323.  
  8324. static Boolean
  8325. XmLGridCellIsValueSet(XmLGridCell cell)
  8326.     {
  8327.     if (cell->cell.flags & XmLGridCellValueSetFlag)
  8328.         return True;
  8329.     return False;
  8330.     }
  8331.  
  8332. static void
  8333. XmLGridCellSetValueSet(XmLGridCell cell,
  8334.                Boolean set)
  8335.     {
  8336.     cell->cell.flags |= XmLGridCellValueSetFlag;
  8337.     if (set != True)
  8338.         cell->cell.flags ^= XmLGridCellValueSetFlag;
  8339.     }
  8340.  
  8341. static void
  8342. XmLGridCellSetInRowSpan(XmLGridCell cell,
  8343.             Boolean set)
  8344.     {
  8345.     cell->cell.flags |= XmLGridCellInRowSpanFlag;
  8346.     if (set != True)
  8347.         cell->cell.flags ^= XmLGridCellInRowSpanFlag;
  8348.     }
  8349.  
  8350. static void
  8351. XmLGridCellSetInColumnSpan(XmLGridCell cell,
  8352.                Boolean set)
  8353.     {
  8354.     cell->cell.flags |= XmLGridCellInColumnSpanFlag;
  8355.     if (set != True)
  8356.         cell->cell.flags ^= XmLGridCellInColumnSpanFlag;
  8357.     }
  8358.  
  8359. static void
  8360. XmLGridCellSetSelected(XmLGridCell cell,
  8361.                Boolean selected)
  8362.     {
  8363.     cell->cell.flags |= XmLGridCellSelectedFlag;
  8364.     if (selected != True)
  8365.         cell->cell.flags ^= XmLGridCellSelectedFlag;
  8366.     }
  8367.  
  8368. static void
  8369. XmLGridCellAllocIcon(XmLGridCell cell)
  8370.     {
  8371.     XmLGridCellIcon *icon;
  8372.  
  8373.     icon = (XmLGridCellIcon *)malloc(sizeof(XmLGridCellIcon));
  8374.     icon->pix.pixmap = XmUNSPECIFIED_PIXMAP;
  8375.     icon->pix.pixmask = XmUNSPECIFIED_PIXMAP;
  8376.     icon->pix.width = 0;
  8377.     icon->pix.height = 0;
  8378.     icon->string = 0;
  8379.     cell->cell.value = (void *)icon;
  8380.     XmLGridCellSetValueSet(cell, True);
  8381.     }
  8382.  
  8383. static void
  8384. XmLGridCellAllocPixmap(XmLGridCell cell)
  8385.     {
  8386.     XmLGridCellPixmap *pix;
  8387.  
  8388.     pix = (XmLGridCellPixmap *)malloc(sizeof(XmLGridCellPixmap));
  8389.     pix->width = 0;
  8390.     pix->height = 0;
  8391.     pix->pixmap = XmUNSPECIFIED_PIXMAP;
  8392.     pix->pixmask = XmUNSPECIFIED_PIXMAP;
  8393.     cell->cell.value = (void *)pix;
  8394.     XmLGridCellSetValueSet(cell, True);
  8395.     }
  8396.  
  8397. static void
  8398. XmLGridCellSetString(XmLGridCell cell,
  8399.              XmString string,
  8400.              Boolean copy)
  8401.     {
  8402.     XmLGridCellIcon *icon;
  8403.  
  8404.     if (cell->cell.refValues->type == XmSTRING_CELL)
  8405.         {
  8406.         _XmLGridCellFreeValue(cell);
  8407.         if (string)
  8408.             {
  8409.             if (copy == True)
  8410.                 cell->cell.value = (void *)XmStringCopy(string);
  8411.             else
  8412.                 cell->cell.value = (void *)string;
  8413.             XmLGridCellSetValueSet(cell, True);
  8414.             }
  8415.         else
  8416.             XmLGridCellSetValueSet(cell, False);
  8417.         }
  8418.     else if (cell->cell.refValues->type == XmICON_CELL)
  8419.         {
  8420.         if (XmLGridCellIsValueSet(cell) == False)
  8421.             XmLGridCellAllocIcon(cell);
  8422.         icon = (XmLGridCellIcon *)cell->cell.value;
  8423.         if (icon->string)
  8424.             XmStringFree(icon->string);
  8425.         if (string && copy == True)
  8426.             icon->string = XmStringCopy(string);
  8427.         else
  8428.             icon->string = string;
  8429.         }
  8430.     else if (string && copy == False)
  8431.         XmStringFree(string);
  8432.     }
  8433.  
  8434. static XmString
  8435. XmLGridCellGetString(XmLGridCell cell)
  8436.     {
  8437.     XmString str;
  8438.  
  8439.     str = 0;
  8440.     if (cell->cell.refValues->type == XmSTRING_CELL)
  8441.         {
  8442.         if (XmLGridCellIsValueSet(cell) == True)
  8443.             str = (XmString)cell->cell.value;
  8444.         }
  8445.     else if (cell->cell.refValues->type == XmICON_CELL)
  8446.         {
  8447.         if (XmLGridCellIsValueSet(cell) == True)
  8448.             str = ((XmLGridCellIcon *)cell->cell.value)->string;
  8449.         }
  8450.     return str;
  8451.     }
  8452.  
  8453. static void
  8454. XmLGridCellSetToggle(XmLGridCell cell,
  8455.              Boolean state)
  8456.     {
  8457.     if (cell->cell.refValues->type == XmTOGGLE_CELL)
  8458.         {
  8459.         if (state)
  8460.             cell->cell.value = (void *)1;
  8461.         else
  8462.             cell->cell.value = (void *)0;
  8463.         XmLGridCellSetValueSet(cell, True);
  8464.         }
  8465.     }
  8466.  
  8467. static Boolean
  8468. XmLGridCellGetToggle(XmLGridCell cell)
  8469.     {
  8470.     Boolean toggled;
  8471.  
  8472.     toggled = False;
  8473.     if (cell->cell.refValues->type == XmTOGGLE_CELL)
  8474.         {
  8475.         if (XmLGridCellIsValueSet(cell) == True &&
  8476.             cell->cell.value == (void *)1)
  8477.             toggled = True;
  8478.         }
  8479.     return toggled;
  8480.     }
  8481.  
  8482. static void
  8483. XmLGridCellSetPixmap(XmLGridCell cell,
  8484.              Pixmap pixmap,
  8485.              Dimension width,
  8486.              Dimension height)
  8487.     {
  8488.     XmLGridCellPixmap *pix;
  8489.  
  8490.     pix = 0;
  8491.     if (cell->cell.refValues->type == XmPIXMAP_CELL)
  8492.         {
  8493.         if (XmLGridCellIsValueSet(cell) == False)
  8494.             XmLGridCellAllocPixmap(cell);
  8495.         pix = (XmLGridCellPixmap *)cell->cell.value;
  8496.         }
  8497.     else if (cell->cell.refValues->type == XmICON_CELL)
  8498.         {
  8499.         if (XmLGridCellIsValueSet(cell) == False)
  8500.             XmLGridCellAllocIcon(cell);
  8501.         pix = &((XmLGridCellIcon *)cell->cell.value)->pix;
  8502.         }
  8503.     if (!pix)
  8504.         return;
  8505.     pix->pixmap = pixmap;
  8506.     pix->height = height;
  8507.     pix->width = width;
  8508.     }
  8509.  
  8510. static void
  8511. XmLGridCellSetPixmask(XmLGridCell cell,
  8512.               Pixmap pixmask)
  8513.     {
  8514.     XmLGridCellPixmap *pix;
  8515.  
  8516.     if (XmLGridCellIsValueSet(cell) == False)
  8517.         {
  8518.         fprintf(stderr, "XmLGridCellSetPixmask: pixmap must be set ");
  8519.         fprintf(stderr, "before pixmask\n");
  8520.         return; 
  8521.         }
  8522.     pix = 0;
  8523.     if (cell->cell.refValues->type == XmPIXMAP_CELL)
  8524.         pix = (XmLGridCellPixmap *)cell->cell.value;
  8525.     else if (cell->cell.refValues->type == XmICON_CELL)
  8526.         pix = &((XmLGridCellIcon *)cell->cell.value)->pix;
  8527.     if (!pix)
  8528.         return;
  8529.     pix->pixmask = pixmask;
  8530.     }
  8531.  
  8532. static XmLGridCellPixmap *
  8533. XmLGridCellGetPixmap(XmLGridCell cell)
  8534.     {
  8535.     XmLGridCellPixmap *pix;
  8536.  
  8537.     pix = 0;
  8538.     if (cell->cell.refValues->type == XmPIXMAP_CELL)
  8539.         {
  8540.         if (XmLGridCellIsValueSet(cell) == True)
  8541.             pix = (XmLGridCellPixmap *)cell->cell.value;
  8542.         }
  8543.     else if (cell->cell.refValues->type == XmICON_CELL)
  8544.         {
  8545.         if (XmLGridCellIsValueSet(cell) == True)
  8546.             pix = &((XmLGridCellIcon *)cell->cell.value)->pix;
  8547.         }
  8548.     return pix;
  8549.     }
  8550.  
  8551. /* Only to be called by XmLGridCellAction() */
  8552. void 
  8553. _XmLGridCellDrawBackground(XmLGridCell cell,
  8554.                Widget w,
  8555.                XRectangle *clipRect,
  8556.                XmLGridDrawStruct *ds)
  8557.     {
  8558.     Display *dpy;
  8559.     Window win;
  8560.  
  8561.     dpy = XtDisplay(w);
  8562.     win = XtWindow(w);
  8563.     if (ds->drawSelected == True)
  8564.         XSetForeground(dpy, ds->gc, ds->selectBackground);
  8565.     else
  8566.         XSetForeground(dpy, ds->gc, ds->background);
  8567.     XFillRectangle(dpy, win, ds->gc, clipRect->x, clipRect->y,
  8568.         clipRect->width, clipRect->height);
  8569.     }
  8570.  
  8571. /* Only to be called by XmLGridCellAction() */
  8572. void 
  8573. _XmLGridCellDrawBorders(XmLGridCell cell,
  8574.             Widget w,
  8575.             XRectangle *clipRect,
  8576.             XmLGridDrawStruct *ds)
  8577.     {
  8578.     XmLGridWidget g;
  8579.     Display *dpy;
  8580.     Window win;
  8581.     GC gc;
  8582.     Pixel black, white;
  8583.     int x1, x2, y1, y2, loff, roff;
  8584.     int drawLeft, drawRight, drawBot, drawTop;
  8585.     XRectangle *cellRect;
  8586.     unsigned char borderType;
  8587.  
  8588.     g = (XmLGridWidget)w;
  8589.     dpy = XtDisplay(w);
  8590.     win = XtWindow(w);
  8591.     gc = ds->gc;
  8592.     cellRect = ds->cellRect;
  8593.     black = BlackPixelOfScreen(XtScreen(w));
  8594.     white = WhitePixelOfScreen(XtScreen(w));
  8595.     x1 = clipRect->x;
  8596.     x2 = clipRect->x + clipRect->width - 1;
  8597.     y1 = clipRect->y;
  8598.     y2 = clipRect->y + clipRect->height - 1;
  8599.     drawLeft = 1;
  8600.     drawRight = 1;
  8601.     drawBot = 1;
  8602.     drawTop = 1;
  8603.     if (cellRect->x != clipRect->x)    
  8604.         drawLeft = 0;
  8605.     if (cellRect->x + cellRect->width != clipRect->x + clipRect->width)
  8606.         drawRight = 0;
  8607.     if (cellRect->y != clipRect->y)
  8608.         drawTop = 0;
  8609.     if (cellRect->y + cellRect->height != clipRect->y + clipRect->height)
  8610.         drawBot = 0;
  8611.     borderType = cell->cell.refValues->rightBorderType;
  8612.     if (borderType != XmBORDER_NONE && drawRight)
  8613.         {
  8614.         if (borderType == XmBORDER_DASH)
  8615.             XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter);
  8616.         XSetForeground(dpy, gc, cell->cell.refValues->rightBorderColor);
  8617.         XDrawLine(dpy, win, gc, x2, y1, x2, y2);
  8618.         if (borderType == XmBORDER_DASH)
  8619.             XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter);
  8620.         }
  8621.     borderType = cell->cell.refValues->bottomBorderType;
  8622.     if (borderType != XmBORDER_NONE && drawBot)
  8623.         {
  8624.         if (borderType == XmBORDER_DASH)
  8625.             XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter);
  8626.         XSetForeground(dpy, gc, cell->cell.refValues->bottomBorderColor);
  8627.         XDrawLine(dpy, win, gc, x1, y2, x2, y2);
  8628.         if (borderType == XmBORDER_DASH)
  8629.             XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter);
  8630.         }    
  8631.     borderType = cell->cell.refValues->topBorderType;
  8632.     if (borderType != XmBORDER_NONE && drawTop)
  8633.         {
  8634.         if (borderType == XmBORDER_DASH)
  8635.             XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter);
  8636.         XSetForeground(dpy, gc, cell->cell.refValues->topBorderColor);
  8637.         XDrawLine(dpy, win, gc, x1, y1, x2, y1);
  8638.         if (borderType == XmBORDER_DASH)
  8639.             XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter);
  8640.         }
  8641.     borderType = cell->cell.refValues->leftBorderType;
  8642.     if (borderType != XmBORDER_NONE && drawLeft)
  8643.         {
  8644.         if (borderType == XmBORDER_DASH)
  8645.             XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter);
  8646.         XSetForeground(dpy, gc, cell->cell.refValues->leftBorderColor);
  8647.         XDrawLine(dpy, win, gc, x1, y1, x1, y2);
  8648.         if (borderType == XmBORDER_DASH)
  8649.             XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter);
  8650.         }
  8651.     if (ds->drawFocusType == XmDRAW_FOCUS_NONE)
  8652.         return;
  8653.     if (ds->drawFocusType == XmDRAW_FOCUS_LEFT)
  8654.         drawRight = 0;
  8655.     else if (ds->drawFocusType == XmDRAW_FOCUS_RIGHT)
  8656.         drawLeft = 0;
  8657.     else if (ds->drawFocusType == XmDRAW_FOCUS_MID)
  8658.         {
  8659.         drawLeft = 0;
  8660.         drawRight = 0;
  8661.         }
  8662.     if (!drawLeft)
  8663.         loff = 0;
  8664.     else
  8665.         loff = 2;
  8666.     if (!drawRight)
  8667.         roff = 0;
  8668.     else
  8669.         roff = 2;
  8670.     if (g->grid.highlightThickness < 2)
  8671.         return;
  8672.     XSetForeground(dpy, gc, g->manager.highlight_color);
  8673.     if (drawTop)
  8674.         XDrawLine(dpy, win, gc, x1, y1, x2, y1);
  8675.     if (drawLeft)
  8676.         XDrawLine(dpy, win, gc, x1, y1 + 2, x1, y2);
  8677.     if (drawRight)
  8678.         XDrawLine(dpy, win, gc, x2, y1 + 2, x2, y2);
  8679.     if (drawBot)
  8680.         XDrawLine(dpy, win, gc, x1 + loff, y2, x2 - roff, y2);
  8681.     if (drawTop && clipRect->height > 1)
  8682.         XDrawLine(dpy, win, gc, x1, y1 + 1, x2, y1 + 1);
  8683.     if (drawBot && (int)clipRect->height > 1 &&
  8684.         (int)clipRect->width > roff &&
  8685.         (int)clipRect->width > loff)
  8686.         XDrawLine(dpy, win, gc, x1 + loff, y2 - 1, x2 - roff, y2 - 1);
  8687.     if (clipRect->width > 1 && clipRect->height > 2)
  8688.         {
  8689.         if (drawLeft)
  8690.             XDrawLine(dpy, win, gc, x1 + 1, y1 + 2, x1 + 1, y2);
  8691.         if (drawRight)
  8692.             XDrawLine(dpy, win, gc, x2 - 1, y1 + 2, x2 - 1, y2);
  8693.         }
  8694.     }
  8695.  
  8696. /* Only to be called by XmLGridCellAction() */
  8697. void
  8698. _XmLGridCellDrawValue(XmLGridCell cell,
  8699.               Widget w,
  8700.               XRectangle *clipRect,
  8701.               XmLGridDrawStruct *ds)
  8702.     {
  8703.     XmLGridWidget g;
  8704.     Display *dpy;
  8705.     XmLGridCellPixmap *pix;
  8706.     XmLGridCellIcon *icon;
  8707.     XRectangle cellRect;
  8708.     XmLGridCellRefValues *cellValues;
  8709.     int type, horizMargin, vertMargin, xoff;
  8710.  
  8711.     g = (XmLGridWidget)w;
  8712.     cellRect = *ds->cellRect;
  8713.     cellValues = cell->cell.refValues;
  8714.     horizMargin = ds->leftMargin + ds->rightMargin; 
  8715.     vertMargin = ds->topMargin + ds->bottomMargin;
  8716.     if (horizMargin >= (int)cellRect.width ||
  8717.         vertMargin >= (int)cellRect.height)
  8718.         return;
  8719.     type = cellValues->type;
  8720.     cellRect.x += ds->leftMargin;
  8721.     cellRect.y += ds->topMargin;
  8722.     cellRect.width -= horizMargin;
  8723.     cellRect.height -= vertMargin;
  8724.     dpy = XtDisplay(w);
  8725.     if (type == XmSTRING_CELL && XmLGridCellIsValueSet(cell) == True)
  8726.         {
  8727.         if (ds->drawSelected == True)
  8728.             XSetForeground(dpy, ds->gc, ds->selectForeground);
  8729.         else
  8730.             XSetForeground(dpy, ds->gc, ds->foreground);
  8731.         XmLStringDraw(w, (XmString)cell->cell.value, ds->stringDirection,
  8732.             ds->fontList, ds->alignment, ds->gc,
  8733.             &cellRect, clipRect);
  8734.         }
  8735.     if (type == XmPIXMAP_CELL && XmLGridCellIsValueSet(cell) == True)
  8736.         {
  8737.         pix = (XmLGridCellPixmap *)cell->cell.value;
  8738.         XmLPixmapDraw(w, pix->pixmap, pix->pixmask,
  8739.             pix->width, pix->height, ds->alignment,
  8740.             ds->gc, &cellRect, clipRect);
  8741.         }
  8742.     if (type == XmICON_CELL && XmLGridCellIsValueSet(cell) == True)
  8743.         {
  8744.         icon = (XmLGridCellIcon *)cell->cell.value;
  8745.         if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP)
  8746.             {
  8747.             XmLPixmapDraw(w, icon->pix.pixmap, icon->pix.pixmask,
  8748.                 icon->pix.width, icon->pix.height, ds->alignment,
  8749.                 ds->gc, &cellRect, clipRect);
  8750.             xoff = icon->pix.width + g->grid.iconSpacing;
  8751.             cellRect.x += xoff;
  8752.             if (xoff < (int)cellRect.width)
  8753.                 cellRect.width -= xoff;
  8754.             else
  8755.                 cellRect.width = 0;
  8756.             }
  8757.         if (cellRect.width && icon->string)
  8758.             {
  8759.             if (ds->drawSelected == True)
  8760.                 XSetForeground(dpy, ds->gc, ds->selectForeground);
  8761.             else
  8762.                 XSetForeground(dpy, ds->gc, ds->foreground);
  8763.             XmLStringDraw(w, icon->string, ds->stringDirection,
  8764.                 ds->fontList, ds->alignment, ds->gc,
  8765.                 &cellRect, clipRect);
  8766.             }
  8767.         }
  8768.     if (type == XmTOGGLE_CELL)
  8769.         XmLDrawToggle(w, XmLGridCellGetToggle(cell),
  8770.             g->grid.toggleSize, ds->alignment, ds->gc,
  8771.             ds->background, g->grid.toggleTopColor,
  8772.             g->grid.toggleBotColor, ds->foreground,
  8773.             &cellRect, clipRect);
  8774.     }
  8775.  
  8776. /* Only to be called by XmLGridCellAction() */
  8777. static int
  8778. _XmLGridCellConfigureText(XmLGridCell cell, Widget w, XRectangle *rect)
  8779.     {
  8780.     XmLGridWidget g;
  8781.  
  8782.     g = (XmLGridWidget)w;
  8783.     XtConfigureWidget(g->grid.text, rect->x, rect->y,
  8784.         rect->width, rect->height, 0);
  8785.     return(0);
  8786.     }
  8787.  
  8788. /* Only to be called by XmLGridCellAction() */
  8789. static int
  8790. _XmLGridCellBeginTextEdit(XmLGridCell cell,
  8791.               Widget w,
  8792.               XRectangle *clipRect)
  8793.     {
  8794.         XmLGridWidget g = (XmLGridWidget)w;
  8795.     Widget text;
  8796.  
  8797.     if (cell->cell.refValues->type != XmSTRING_CELL ||
  8798.         cell->cell.refValues->editable != True
  8799.         || g->grid.useTextWidget != True)
  8800.         return 0;
  8801.     XtVaGetValues(w,
  8802.         XmNtextWidget, &text,
  8803.         NULL);
  8804.     XtVaSetValues(text,
  8805.         XmNfontList, cell->cell.refValues->fontList,
  8806.         NULL);
  8807.     return 1;
  8808.     }
  8809.  
  8810. /* Only to be called by XmLGridCellAction() */
  8811. static void
  8812. _XmLGridCellCompleteTextEdit(XmLGridCell cell,
  8813.                  Widget w)
  8814.     {
  8815.         XmLGridWidget g = (XmLGridWidget)w;
  8816.     Widget text;
  8817.     char *s;
  8818.     int i, len;
  8819.  
  8820.     if (cell->cell.refValues->type != XmSTRING_CELL ||
  8821.         cell->cell.refValues->editable != True 
  8822.         || g->grid.useTextWidget != True)
  8823.         return;
  8824.     XtVaGetValues(w,
  8825.         XmNtextWidget, &text,
  8826.         NULL);
  8827.     s = XmTextGetString(text);
  8828.     len = strlen(s);
  8829.     for (i = 0; i < len - 1; i++)
  8830.         if (s[i] == '\\' && s[i + 1] == 'n')
  8831.             {
  8832.             s[i] = '\n';
  8833.             strcpy(&s[i + 1], &s[i + 2]);
  8834.             }
  8835.     if (XmLGridCellIsValueSet(cell) == True)
  8836.         XmStringFree((XmString)cell->cell.value);
  8837.     if (strlen(s))
  8838.         {
  8839.         cell->cell.value = (void *)XmStringCreateLtoR(s,
  8840.             XmSTRING_DEFAULT_CHARSET);
  8841.         XmLGridCellSetValueSet(cell, True);
  8842.         }
  8843.     else
  8844.         XmLGridCellSetValueSet(cell, False);
  8845.     XtFree(s);
  8846.     }
  8847.  
  8848. /* Only to be called by XmLGridCellAction() */
  8849. static void
  8850. _XmLGridCellInsertText(XmLGridCell cell,
  8851.                Widget w)
  8852.     {
  8853.         XmLGridWidget g = (XmLGridWidget)w;
  8854.     char *s;
  8855.     Widget text;
  8856.  
  8857.     if (cell->cell.refValues->type != XmSTRING_CELL ||
  8858.         cell->cell.refValues->editable != True
  8859.         || g->grid.useTextWidget != True)
  8860.         return;
  8861.     XtVaGetValues(w,
  8862.         XmNtextWidget, &text,
  8863.         NULL);
  8864.     s = 0;
  8865.     if (XmLGridCellIsValueSet(cell) == True)
  8866.         s = CvtXmStringToStr((XmString)cell->cell.value);
  8867.     if (s)
  8868.         {
  8869.         XmTextSetString(text, s);
  8870.         free(s);
  8871.         }
  8872.     else
  8873.         XmTextSetString(text, "");
  8874.     XmTextSetInsertionPosition(text, XmTextGetLastPosition(text));
  8875.     XmProcessTraversal(text, XmTRAVERSE_CURRENT);
  8876.     }
  8877.  
  8878. /* Only to be called by XmLGridCellAction() */
  8879. static int
  8880. _XmLGridCellGetHeight(XmLGridCell cell,
  8881.                       Widget w,
  8882.                       XmLGridRow row)
  8883.     {
  8884.     XmLGridCellPixmap *pix;
  8885.     XmLGridCellIcon *icon;
  8886.     XmLGridCellRefValues *cellValues;
  8887.     int height, pixHeight;
  8888.  
  8889.     cellValues = cell->cell.refValues;
  8890.     height = -1;
  8891.     if (cellValues->type == XmPIXMAP_CELL)
  8892.         {
  8893.         if (XmLGridCellIsValueSet(cell) == True)
  8894.             {
  8895.             pix = (XmLGridCellPixmap *)cell->cell.value;
  8896.             if (pix->height)
  8897.                 height = 4 + pix->height + cellValues->topMargin +
  8898.                     cellValues->bottomMargin;
  8899.             }
  8900.         }
  8901.     else if (cellValues->type == XmICON_CELL)
  8902.         {
  8903.         pixHeight = 0;
  8904.         if (XmLGridCellIsValueSet(cell) == True)
  8905.             {
  8906.             icon = (XmLGridCellIcon *)cell->cell.value;
  8907.             if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP && icon->pix.height)
  8908.                 pixHeight = 4 + icon->pix.height +
  8909.                     cellValues->topMargin + cellValues->bottomMargin;
  8910.             }
  8911.         height = 4 + row->grid.height * cellValues->fontHeight +
  8912.             cellValues->topMargin + cellValues->bottomMargin;
  8913.         if (pixHeight > height)
  8914.             height = pixHeight;
  8915.         }
  8916.     else if (cellValues->type == XmTOGGLE_CELL)
  8917.         height = 4 + 16 + cellValues->topMargin +
  8918.             cellValues->bottomMargin;
  8919.     else if (cellValues->type == XmSTRING_CELL)
  8920.         {
  8921.         height = 4 + row->grid.height * cellValues->fontHeight +
  8922.             cellValues->topMargin + cellValues->bottomMargin;
  8923.         }
  8924.     if (height < 0 || cellValues->rowSpan)
  8925.         height = 4;
  8926.     return height;
  8927.     }
  8928.  
  8929. /* Only to be called by XmLGridCellAction() */
  8930. static int
  8931. _XmLGridCellGetWidth(XmLGridCell cell,
  8932.                      Widget w,
  8933.                      XmLGridColumn col)
  8934.     {
  8935.     XmLGridWidget g = (XmLGridWidget)w;
  8936.     XmLGridCellPixmap *pix;
  8937.     XmLGridCellIcon *icon;
  8938.     XmLGridCellRefValues *cellValues;
  8939.     int width;
  8940.  
  8941.     cellValues = cell->cell.refValues;
  8942.     width = -1;
  8943.     if (cellValues->type == XmPIXMAP_CELL)
  8944.         {
  8945.         if (XmLGridCellIsValueSet(cell) == True)
  8946.             {
  8947.             pix = (XmLGridCellPixmap *)cell->cell.value;
  8948.             if (pix->width)
  8949.                 width = 4 + pix->width + cellValues->leftMargin +
  8950.                     cellValues->rightMargin;
  8951.             }
  8952.         }
  8953.     else if (cellValues->type == XmICON_CELL)
  8954.         {
  8955.         width = 4 + col->grid.width * cellValues->fontWidth +
  8956.             cellValues->leftMargin + cellValues->rightMargin;
  8957.         if (XmLGridCellIsValueSet(cell) == True)
  8958.             {
  8959.             icon = (XmLGridCellIcon *)cell->cell.value;
  8960.             if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP && icon->pix.width)
  8961.                 width += icon->pix.width + g->grid.iconSpacing;
  8962.             }
  8963.         }
  8964.     else if (cellValues->type == XmTOGGLE_CELL)
  8965.         width = 4 + 16 + cellValues->leftMargin +
  8966.             cellValues->rightMargin;
  8967.     else if (cellValues->type == XmSTRING_CELL)
  8968.         width = 4 + col->grid.width * cellValues->fontWidth +
  8969.             cellValues->leftMargin + cellValues->rightMargin;
  8970.     if (width < 0 || cellValues->columnSpan)
  8971.         width = 4;
  8972.     return width;
  8973.     }
  8974.  
  8975. /* Only to be called by XmLGridCellAction() */
  8976. static void
  8977. _XmLGridCellFreeValue(XmLGridCell cell)
  8978.     {
  8979.     int type;
  8980.     XmLGridCellIcon *icon;
  8981.  
  8982.     if (XmLGridCellIsValueSet(cell) == False)
  8983.         return;
  8984.     type = cell->cell.refValues->type;
  8985.     if (type == XmSTRING_CELL)
  8986.         XmStringFree((XmString)cell->cell.value);
  8987.     else if (type == XmPIXMAP_CELL)
  8988.         free((char *)cell->cell.value);
  8989.     else if (type == XmICON_CELL)
  8990.         {
  8991.         icon = (XmLGridCellIcon *)cell->cell.value;
  8992.         if (icon->string)
  8993.             XmStringFree(icon->string);
  8994.         free((char *)icon);
  8995.         }
  8996.     XmLGridCellSetValueSet(cell, False);
  8997.     }
  8998.  
  8999. /*
  9000.    Public Functions
  9001. */
  9002.  
  9003. Widget
  9004. XmLCreateGrid(Widget parent,
  9005.           char *name,
  9006.           ArgList arglist,
  9007.           Cardinal argcount)
  9008.     {
  9009.     return XtCreateWidget(name, xmlGridWidgetClass, parent,
  9010.         arglist, argcount);
  9011.     }
  9012.  
  9013. void
  9014. XmLGridAddColumns(Widget w,
  9015.           unsigned char type,
  9016.           int position,
  9017.           int count)
  9018.     {
  9019.     XmLGridWidget g;
  9020.     XmLGridColumn col;
  9021.     XmLGridRow row;
  9022.     XmLGridCell cell;
  9023.     XmLGridCallbackStruct cbs;
  9024.     int i, j, rowCount, hasAddCB, redraw;
  9025.  
  9026.     g = WidgetToGrid(w, "AddColumns()");
  9027.     if (!g)
  9028.         return;
  9029.     if (count <= 0)
  9030.         return;
  9031.     redraw = 0;
  9032.     position = ColTypePosToPos(g, type, position, 1);
  9033.     if (position < 0)
  9034.         position = ColTypePosToPos(g, type, -1, 1);
  9035.     /* adjust count */
  9036.     if (type == XmHEADING)
  9037.         {
  9038.         g->grid.headingColCount += count;
  9039.         g->grid.leftFixedCount += count;
  9040.         redraw = 1;
  9041.         }
  9042.     else if (type == XmFOOTER)
  9043.         {
  9044.         g->grid.footerColCount += count;
  9045.         g->grid.rightFixedCount += count;
  9046.         redraw = 1;
  9047.         }
  9048.     else /* XmCONTENT */
  9049.         g->grid.colCount += count;
  9050.  
  9051.     hasAddCB = 0;
  9052.     if (XtHasCallbacks(w, XmNaddCallback) == XtCallbackHasSome)
  9053.         hasAddCB = 1;
  9054.     /* add columns */
  9055.     XmLArrayAdd(g->grid.colArray, position, count);
  9056.     for (i = 0; i < count; i++)
  9057.         {
  9058.         col = 0;
  9059.         if (hasAddCB)
  9060.             {
  9061.             cbs.reason = XmCR_ADD_COLUMN;
  9062.             cbs.columnType = type;
  9063.             cbs.object = 0;
  9064.             XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs);
  9065.             col = (XmLGridColumn)cbs.object;
  9066.             }
  9067.         if (!col)
  9068.             col = XmLGridColumnNew(w);
  9069.         XmLArraySet(g->grid.colArray, position + i, col);
  9070.         }
  9071.     /* add cells */
  9072.     rowCount = XmLArrayGetCount(g->grid.rowArray);
  9073.     for (j = 0; j < rowCount; j++)
  9074.         {
  9075.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, j);
  9076.         XmLArrayAdd(XmLGridRowCells(row), position, count);
  9077.         for (i = position; i < position + count; i++)
  9078.             {
  9079.             cell = 0;
  9080.             if (hasAddCB)
  9081.                 {
  9082.                 cbs.reason = XmCR_ADD_CELL;
  9083.                 cbs.rowType = RowPosToType(g, j);
  9084.                 cbs.columnType = type;
  9085.                 cbs.object = 0;
  9086.                 XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs);
  9087.                 cell = (XmLGridCell)cbs.object;
  9088.                 }
  9089.             if (!cell)
  9090.                 cell = XmLGridCellNew();
  9091.             col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  9092.             if (col->grid.defCellValues)
  9093.                 XmLGridCellSetRefValues(cell, col->grid.defCellValues);
  9094.             else
  9095.                 XmLGridCellSetRefValues(cell, g->grid.defCellValues);
  9096.             XmLArraySet(XmLGridRowCells(row), i, cell);
  9097.             }
  9098.         XmLGridRowHeightChanged(row);
  9099.         }
  9100.     for (i = position; i < position + count; i++)
  9101.         {
  9102.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  9103.         XmLGridColumnWidthChanged(col);
  9104.         }
  9105.     /* sanity check */
  9106.     if (XmLArrayGetCount(g->grid.colArray) != g->grid.headingColCount +
  9107.         g->grid.colCount + g->grid.footerColCount)
  9108.             XmLWarning(w, "AddColumns() - count sanity check failed");
  9109.  
  9110.     /* maintain scroll and focus position */
  9111.     if (g->grid.hsPolicy == XmCONSTANT)
  9112.         {
  9113.         if (type == XmCONTENT && g->grid.colCount == count)
  9114.             g->grid.scrollCol = 0;
  9115.         else if (position <= g->grid.scrollCol)
  9116.             g->grid.scrollCol += count;
  9117.         }
  9118.     if (position <= g->grid.focusCol)
  9119.         g->grid.focusCol += count;
  9120.     VisPosChanged(g, 0);
  9121.     HorizLayout(g, 1);
  9122.     VertLayout(g, 1);
  9123.     if (g->grid.focusCol == -1 && type == XmCONTENT)
  9124.         {
  9125.         if (g->grid.focusRow != -1)
  9126.             SetFocus(g, g->grid.focusRow, position, 0, 0);
  9127.         else
  9128.             g->grid.focusCol = position;
  9129.         }    
  9130.     for (i = position; i < position + count; i++)
  9131.         redraw |= ColIsVisible(g, i);
  9132.     if (redraw)
  9133.         DrawArea(g, DrawAll, 0, 0);
  9134.     }
  9135.  
  9136. void
  9137. XmLGridAddRows(Widget w,
  9138.            unsigned char type,
  9139.            int position,
  9140.            int count)
  9141.     {
  9142.     XmLGridWidget g;
  9143.     XmLGridRow row;
  9144.     XmLGridColumn col;
  9145.     XmLGridCell cell;
  9146.     XmLGridCallbackStruct cbs;
  9147.     int i, j, hasAddCB, redraw, colCount;
  9148.  
  9149.     g = WidgetToGrid(w, "AddRows()");
  9150.     if (!g)
  9151.         return;
  9152.     if (count <= 0)
  9153.         return;
  9154.     redraw = 0;
  9155.     position = RowTypePosToPos(g, type, position, 1);
  9156.     if (position < 0)
  9157.         position = RowTypePosToPos(g, type, -1, 1);
  9158.     /* adjust count */
  9159.     if (type == XmHEADING)
  9160.         {
  9161.         g->grid.headingRowCount += count;
  9162.         g->grid.topFixedCount += count;
  9163.         redraw = 1;
  9164.         }
  9165.     else if (type == XmFOOTER)
  9166.         {
  9167.         g->grid.footerRowCount += count;
  9168.         g->grid.bottomFixedCount += count;
  9169.         redraw = 1;
  9170.         }
  9171.     else /* XmCONTENT */
  9172.         g->grid.rowCount += count;
  9173.  
  9174.     /* add rows and cells */
  9175.     XmLArrayAdd(g->grid.rowArray, position, count);
  9176.     colCount = XmLArrayGetCount(g->grid.colArray);
  9177.     hasAddCB = 0;
  9178.     if (XtHasCallbacks(w, XmNaddCallback) == XtCallbackHasSome)
  9179.         hasAddCB = 1;
  9180.     for (i = 0; i < count; i++)
  9181.         {
  9182.         row = 0;
  9183.         if (hasAddCB)
  9184.             {
  9185.             cbs.reason = XmCR_ADD_ROW;
  9186.             cbs.rowType = type;
  9187.             cbs.object = 0;
  9188.             XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs);
  9189.             row = (XmLGridRow)cbs.object;
  9190.             }
  9191.         if (!row)
  9192.             row = XmLGridRowNew(w);
  9193.         XmLArraySet(g->grid.rowArray, position + i, row);
  9194.         XmLArrayAdd(XmLGridRowCells(row), 0, colCount);
  9195.         for (j = 0; j < colCount; j++)
  9196.             {
  9197.             cell = 0;
  9198.             if (hasAddCB)
  9199.                 {
  9200.                 cbs.reason = XmCR_ADD_CELL;
  9201.                 cbs.rowType = type;
  9202.                 cbs.columnType = ColPosToType(g, j);
  9203.                 cbs.object = 0;
  9204.                 XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs);
  9205.                 cell = (XmLGridCell)cbs.object;
  9206.                 }
  9207.             if (!cell)
  9208.                 cell = XmLGridCellNew();
  9209.             col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, j);
  9210.             if (col->grid.defCellValues)
  9211.                 XmLGridCellSetRefValues(cell, col->grid.defCellValues);
  9212.             else
  9213.                 XmLGridCellSetRefValues(cell, g->grid.defCellValues);
  9214.             XmLArraySet(XmLGridRowCells(row), j, cell);
  9215.             }
  9216.         XmLGridRowHeightChanged(row);
  9217.         }
  9218.     for (j = 0; j < colCount; j++)
  9219.         {
  9220.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, j);
  9221.         XmLGridColumnWidthChanged(col);
  9222.         }
  9223.     /* sanity check */
  9224.     if (XmLArrayGetCount(g->grid.rowArray) != g->grid.headingRowCount +
  9225.         g->grid.rowCount + g->grid.footerRowCount)
  9226.             XmLWarning(w, "AddRows() - count sanity check failed");
  9227.  
  9228.     /* maintain scroll and focus position */
  9229.     if (g->grid.vsPolicy == XmCONSTANT)
  9230.         {
  9231.         if (type == XmCONTENT && g->grid.rowCount == count)
  9232.             g->grid.scrollRow = 0;
  9233.         else if (position <= g->grid.scrollRow)
  9234.             g->grid.scrollRow += count;
  9235.         }
  9236.     if (position <= g->grid.focusRow)
  9237.         g->grid.focusRow += count;
  9238.     VisPosChanged(g, 1);
  9239.     HorizLayout(g, 1);
  9240.     VertLayout(g, 1);
  9241.     if (g->grid.focusRow == -1 && type == XmCONTENT)
  9242.         {
  9243.         if (g->grid.focusCol != -1)
  9244.             SetFocus(g, position, g->grid.focusCol, 0, 0);
  9245.         else
  9246.             g->grid.focusRow = position;
  9247.         }
  9248.     for (i = position; i < position + count; i++)
  9249.         redraw |= RowIsVisible(g, i);
  9250.     if (redraw)
  9251.         DrawArea(g, DrawAll, 0, 0);
  9252.  
  9253. #ifdef XmLEVAL
  9254.     if (g->grid.rowCount > 100)
  9255.         {
  9256.         fprintf(stderr, "XmL: evaluation version only supports <= 100 rows\n");
  9257.         exit(0);
  9258.         }
  9259. #endif
  9260.     }
  9261.  
  9262. void
  9263. XmLGridDeleteAllColumns(Widget w,
  9264.             unsigned char type)
  9265.     {
  9266.     XmLGridWidget g;
  9267.     int n;
  9268.  
  9269.     g = WidgetToGrid(w, "DeleteAllColumns()");
  9270.     if (!g)
  9271.         return;
  9272.     if (type == XmHEADING)
  9273.         n = g->grid.headingColCount;
  9274.     else if (type == XmCONTENT)
  9275.         n = g->grid.colCount;
  9276.     else if (type == XmFOOTER)
  9277.         n = g->grid.footerColCount;
  9278.     else
  9279.         {
  9280.         XmLWarning(w, "DeleteAllColumns() - invalid type");
  9281.         return;
  9282.         }
  9283.     if (!n)
  9284.         return;
  9285.     XmLGridDeleteColumns(w, type, 0, n);
  9286.     }
  9287.  
  9288. void
  9289. XmLGridDeleteAllRows(Widget w,
  9290.              unsigned char type)
  9291.     {
  9292.     XmLGridWidget g;
  9293.     int n;
  9294.  
  9295.     g = WidgetToGrid(w, "DeleteAllRows()");
  9296.     if (!g)
  9297.         return;
  9298.     if (type == XmHEADING)
  9299.         n = g->grid.headingRowCount;
  9300.     else if (type == XmCONTENT)
  9301.         n = g->grid.rowCount;
  9302.     else if (type == XmFOOTER)
  9303.         n = g->grid.footerRowCount;
  9304.     else
  9305.         {
  9306.         XmLWarning(w, "DeleteAllRows() - invalid type");
  9307.         return;
  9308.         }
  9309.     if (!n)
  9310.         return;
  9311.     XmLGridDeleteRows(w, type, 0, n);
  9312.     }
  9313.  
  9314. void
  9315. XmLGridDeselectAllRows(Widget w,
  9316.                Boolean notify)
  9317.     {
  9318.     XmLGridWidget g;
  9319.  
  9320.     g = WidgetToGrid(w, "DeselectAllRows()");
  9321.     if (!g)
  9322.         return;
  9323.     SelectTypeArea(g, SelectRow, (XEvent *)0, -1, 0, False, notify);
  9324.     }
  9325.  
  9326. void
  9327. XmLGridDeselectAllColumns(Widget w,
  9328.               Boolean notify)
  9329.     {
  9330.     XmLGridWidget g;
  9331.  
  9332.     g = WidgetToGrid(w, "DeselectAllColumns()");
  9333.     if (!g)
  9334.         return;
  9335.     SelectTypeArea(g, SelectCol, (XEvent *)0, 0, -1, False, notify);
  9336.     }
  9337.  
  9338. void
  9339. XmLGridDeselectAllCells(Widget w,
  9340.             Boolean notify)
  9341.     {
  9342.     XmLGridWidget g;
  9343.  
  9344.     g = WidgetToGrid(w, "DeselectAllCells()");
  9345.     if (!g)
  9346.         return;
  9347.     SelectTypeArea(g, SelectCell, (XEvent *)0, -1, -1, False, notify);
  9348.     }
  9349.  
  9350. void
  9351. XmLGridDeselectCell(Widget w,
  9352.             int row,
  9353.             int column,
  9354.             Boolean notify)
  9355.     {
  9356.     XmLGridWidget g;
  9357.  
  9358.     g = WidgetToGrid(w, "DeselectCell()");
  9359.     if (!g)
  9360.         return;
  9361.     SelectTypeArea(g, SelectCell, (XEvent *)0, row, column, False, notify);
  9362.     }
  9363.  
  9364. void
  9365. XmLGridDeselectColumn(Widget w,
  9366.               int column,
  9367.               Boolean notify)
  9368.     {
  9369.     XmLGridWidget g;
  9370.  
  9371.     g = WidgetToGrid(w, "DeselectColumn()");
  9372.     if (!g)
  9373.         return;
  9374.     SelectTypeArea(g, SelectCol, (XEvent *)0, 0, column, False, notify);
  9375.     }
  9376.  
  9377. void
  9378. XmLGridDeselectRow(Widget w,
  9379.            int row,
  9380.            Boolean notify)
  9381.     {
  9382.     XmLGridWidget g;
  9383.  
  9384.     g = WidgetToGrid(w, "DeselectRow()");
  9385.     if (!g)
  9386.         return;
  9387.     SelectTypeArea(g, SelectRow, (XEvent *)0, row, 0, False, notify);
  9388.     }
  9389.  
  9390. void
  9391. XmLGridDeleteColumns(Widget w,
  9392.              unsigned char type,
  9393.              int position,
  9394.              int count)
  9395.     {
  9396.     XmLGridWidget g;
  9397.     XmLGridRow row;
  9398.     XmLGridColumn col;
  9399.     XmLGridCallbackStruct cbs;
  9400.     int changeFocus, i, j, rowCount, lastPos, redraw;
  9401.  
  9402.     g = WidgetToGrid(w, "DeleteColumns()");
  9403.     if (!g)
  9404.         return;
  9405.     if (count <= 0)
  9406.         return;
  9407.     lastPos = ColTypePosToPos(g, type, position + count - 1, 0);
  9408.     position = ColTypePosToPos(g, type, position, 0);
  9409.     if (position < 0 || lastPos < 0)
  9410.         {
  9411.         XmLWarning(w, "DeleteColumns() - invalid position");
  9412.         return;
  9413.         }
  9414.     changeFocus = 0;
  9415.     if (position <= g->grid.focusCol && lastPos >= g->grid.focusCol)
  9416.         {
  9417.         /* deleting focus col */
  9418.         TextAction(g, TEXT_EDIT_CANCEL);
  9419.         ChangeFocus(g, g->grid.focusRow, -1);
  9420.         changeFocus = 1;
  9421.         }
  9422.     redraw = 0;
  9423.  
  9424.     /* adjust count */
  9425.     if (type == XmHEADING)
  9426.         {
  9427.         g->grid.headingColCount -= count;
  9428.         g->grid.leftFixedCount -= count;
  9429.         redraw = 1;
  9430.         }
  9431.     else if (type == XmFOOTER)
  9432.         {
  9433.         g->grid.footerColCount -= count;
  9434.         g->grid.rightFixedCount -= count;
  9435.         redraw = 1;
  9436.         }
  9437.     else /* XmCONTENT */
  9438.         g->grid.colCount -= count;
  9439.  
  9440.     for (i = position; i < position + count; i++)
  9441.         {
  9442.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  9443.         if (XmLGridColumnIsHidden(col) == True)
  9444.             g->grid.hiddenColCount--;
  9445.         redraw |= ColIsVisible(g, i);
  9446.         }
  9447.     if (XtHasCallbacks(w, XmNdeleteCallback) == XtCallbackHasSome)
  9448.         for (i = position; i < position + count; i++)
  9449.             {
  9450.             rowCount = XmLArrayGetCount(g->grid.rowArray);
  9451.             for (j = 0; j < rowCount; j++)
  9452.                 {
  9453.                 row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, j);
  9454.                 cbs.reason = XmCR_DELETE_CELL;
  9455.                 cbs.rowType = RowPosToType(g, j);
  9456.                 cbs.columnType = type;
  9457.                 cbs.object = XmLArrayGet(XmLGridRowCells(row), i);
  9458.                 XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs);
  9459.                 }
  9460.             cbs.reason = XmCR_DELETE_COLUMN;
  9461.             cbs.columnType = type;
  9462.             cbs.object = XmLArrayGet(g->grid.colArray, i);
  9463.             XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs);
  9464.             }
  9465.     /* delete columns */
  9466.     for (i = position; i < position + count; i++)
  9467.         {
  9468.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  9469.         XmLGridColumnFree(w, col);
  9470.         }
  9471.     XmLArrayDel(g->grid.colArray, position, count);
  9472.     /* delete cells */
  9473.     rowCount = XmLArrayGetCount(g->grid.rowArray);
  9474.     for (i = 0; i < rowCount; i++)
  9475.         {
  9476.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i);
  9477.         for (j = position; j < position + count; j++)
  9478.             XmLGridCellFree(w,
  9479.                 (XmLGridCell)XmLArrayGet(XmLGridRowCells(row), j));
  9480.         XmLArrayDel(XmLGridRowCells(row), position, count);
  9481.         XmLGridRowHeightChanged(row);
  9482.         }
  9483.     /* sanity check */
  9484.     if (XmLArrayGetCount(g->grid.colArray) != g->grid.headingColCount +
  9485.         g->grid.colCount + g->grid.footerColCount)
  9486.             XmLWarning(w, "DeleteColumns() - count sanity check failed");
  9487.  
  9488.     /* maintain scroll and focus position */
  9489.     if (g->grid.hsPolicy == XmCONSTANT)
  9490.         {
  9491.         if (lastPos < g->grid.scrollCol)
  9492.             g->grid.scrollCol -= count;
  9493.         else if (position <= g->grid.scrollCol)
  9494.             g->grid.scrollCol = position;
  9495.         }
  9496.     if (lastPos < g->grid.focusCol)
  9497.         g->grid.focusCol -= count;
  9498.     VisPosChanged(g, 0);
  9499.     HorizLayout(g, 1);
  9500.     VertLayout(g, 1);
  9501.     if (changeFocus)
  9502.         {
  9503.         SetFocus(g, g->grid.focusRow, position, 0, 1);
  9504.         if (g->grid.focusCol == -1)
  9505.             SetFocus(g, g->grid.focusRow, position, 0, -1);
  9506.         }
  9507.     if (redraw)
  9508.         DrawArea(g, DrawAll, 0, 0);
  9509.     }
  9510.  
  9511. void
  9512. XmLGridDeleteRows(Widget w,
  9513.           unsigned char type,
  9514.           int position,
  9515.           int count)
  9516.     {
  9517.     XmLGridWidget g;
  9518.     XmLGridRow row;
  9519.     XmLGridColumn col;
  9520.     XmLGridCallbackStruct cbs;
  9521.     int changeFocus, i, j, colCount, lastPos, redraw;
  9522.  
  9523.     g = WidgetToGrid(w, "DeleteRows()");
  9524.     if (!g)
  9525.         return;
  9526.     if (count <= 0)
  9527.         return;
  9528.     lastPos = RowTypePosToPos(g, type, position + count - 1, 0);
  9529.     position = RowTypePosToPos(g, type, position, 0);
  9530.     if (position < 0 || lastPos < 0)
  9531.         {
  9532.         XmLWarning(w, "DeleteRows() - invalid position");
  9533.         return;
  9534.         }
  9535.     changeFocus = 0;
  9536.     if (position <= g->grid.focusRow && lastPos >= g->grid.focusRow)
  9537.         {
  9538.         /* deleting focus row */
  9539.         TextAction(g, TEXT_EDIT_CANCEL);
  9540.         ChangeFocus(g, -1, g->grid.focusCol);
  9541.         changeFocus = 1;
  9542.         }
  9543.     redraw = 0;
  9544.  
  9545.     /* adjust count */
  9546.     if (type == XmHEADING)
  9547.         {
  9548.         g->grid.headingRowCount -= count;
  9549.         g->grid.topFixedCount -= count;
  9550.         redraw = 1;
  9551.         }
  9552.     else if (type == XmFOOTER)
  9553.         {
  9554.         g->grid.footerRowCount -= count;
  9555.         g->grid.bottomFixedCount -= count;
  9556.         redraw = 1;
  9557.         }
  9558.     else /* XmCONTENT */
  9559.         g->grid.rowCount -= count;
  9560.  
  9561.     for (i = position; i < position + count; i++)
  9562.         {
  9563.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i);
  9564.         if (XmLGridRowIsHidden(row) == True)
  9565.             g->grid.hiddenRowCount--;
  9566.         redraw |= RowIsVisible(g, i);
  9567.         }
  9568.     if (XtHasCallbacks(w, XmNdeleteCallback) == XtCallbackHasSome)
  9569.         for (i = position; i < position + count; i++)
  9570.             {
  9571.             row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i);
  9572.             colCount = XmLArrayGetCount(g->grid.colArray);
  9573.             for (j = 0; j < colCount; j++)
  9574.                 {
  9575.                 cbs.reason = XmCR_DELETE_CELL;
  9576.                 cbs.rowType = type;
  9577.                 cbs.columnType = ColPosToType(g, j);
  9578.                 cbs.object = XmLArrayGet(XmLGridRowCells(row), j);
  9579.                 XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs);
  9580.                 }
  9581.             cbs.reason = XmCR_DELETE_ROW;
  9582.             cbs.rowType = type;
  9583.             cbs.object = (void *)row;
  9584.             XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs);
  9585.             }
  9586.     /* delete rows and cells */
  9587.     for (i = position; i < position + count; i++)
  9588.         {
  9589.         row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i);
  9590.         XmLGridRowFree(w, row);
  9591.         }
  9592.     XmLArrayDel(g->grid.rowArray, position, count);
  9593.     colCount = XmLArrayGetCount(g->grid.colArray);
  9594.     for (i = 0; i < colCount; i++)
  9595.         {
  9596.         col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i);
  9597.         XmLGridColumnWidthChanged(col);
  9598.         }
  9599.     /* sanity check */
  9600.     if (XmLArrayGetCount(g->grid.rowArray) != g->grid.headingRowCount +
  9601.         g->grid.rowCount + g->grid.footerRowCount)
  9602.             XmLWarning(w, "DeleteRows() - count sanity check failed");
  9603.  
  9604.     /* maintain scroll and focus position */
  9605.     if (g->grid.vsPolicy == XmCONSTANT)
  9606.         {
  9607.         if (lastPos < g->grid.scrollRow)
  9608.             g->grid.scrollRow -= count;
  9609.         else if (position <= g->grid.scrollRow)
  9610.             g->grid.scrollRow = position;
  9611.         }
  9612.     if (lastPos < g->grid.focusRow)
  9613.         g->grid.focusRow -= count;
  9614.     VisPosChanged(g, 1);
  9615.     HorizLayout(g, 1);
  9616.     VertLayout(g, 1);
  9617.     if (changeFocus)
  9618.         {
  9619.         SetFocus(g, position, g->grid.focusCol, 1, 0);
  9620.         if (g->grid.focusRow == -1)
  9621.             SetFocus(g, position, g->grid.focusCol, -1, 0);
  9622.         }
  9623.     if (redraw)
  9624.         DrawArea(g, DrawAll, 0, 0);
  9625.     }
  9626.  
  9627. void
  9628. XmLGridGetFocus(Widget w,
  9629.         int *row,
  9630.         int *column,
  9631.         Boolean *focusIn)
  9632.     {
  9633.     XmLGridWidget g;
  9634.     unsigned char rowType, colType;
  9635.  
  9636.     g = WidgetToGrid(w, "GetFocus()");
  9637.     if (!g)
  9638.         return;
  9639.     if (g->grid.focusIn)
  9640.         *focusIn = True;
  9641.     else
  9642.         *focusIn = False;
  9643.     if (g->grid.focusRow < 0 || g->grid.focusCol < 0)
  9644.         {
  9645.         *row = -1;
  9646.         *column = -1;
  9647.         return;
  9648.         }
  9649.     rowType = RowPosToType(g, g->grid.focusRow);
  9650.     colType = ColPosToType(g, g->grid.focusCol);
  9651.     if (rowType != XmCONTENT || colType != XmCONTENT)
  9652.         {
  9653.         *row = -1;
  9654.         *column = -1;
  9655.         XmLWarning(w, "GetFocus() - focus row/column invalid\n");
  9656.         return;
  9657.         }
  9658.     *row = RowPosToTypePos(g, XmCONTENT, g->grid.focusRow);
  9659.     *column = ColPosToTypePos(g, XmCONTENT, g->grid.focusCol);
  9660.     }
  9661.  
  9662. XmLGridRow
  9663. XmLGridGetRow(Widget w,
  9664.           unsigned char rowType,
  9665.           int row)
  9666.  
  9667.     {
  9668.     XmLGridWidget g;
  9669.     XmLGridRow r;
  9670.     int pos;
  9671.  
  9672.     g = WidgetToGrid(w, "GetRow()");
  9673.     if (!g)
  9674.         return 0;
  9675.     pos = RowTypePosToPos(g, rowType, row, 0);
  9676.     r = (XmLGridRow)XmLArrayGet(g->grid.rowArray, pos);
  9677.     if (!r)
  9678.         XmLWarning(w, "GetRow() - invalid row");
  9679.     return r;
  9680.     }
  9681.  
  9682. int
  9683. XmLGridEditBegin(Widget w,
  9684.          Boolean insert,
  9685.          int row,
  9686.          int column)
  9687.     {
  9688.     XmLGridWidget g;
  9689.     int r, c;
  9690.     XRectangle rect;
  9691.  
  9692.     g = WidgetToGrid(w, "EditBegin()");
  9693.     if (!g)
  9694.         return -1;
  9695.     if (column < 0 || column >= g->grid.colCount) 
  9696.         {
  9697.         XmLWarning(w, "EditBegin() - invalid column");
  9698.         return -1;
  9699.         }
  9700.     if (row < 0 || row >= g->grid.rowCount) 
  9701.         {
  9702.         XmLWarning(w, "EditBegin() - invalid row");
  9703.         return -1;
  9704.         }
  9705.     r = RowTypePosToPos(g, XmCONTENT, row, 0);
  9706.     c = ColTypePosToPos(g, XmCONTENT, column, 0);
  9707.     if (RowColToXY(g, r, c, True, &rect) == -1)
  9708.         {
  9709.         XmLWarning(w, "EditBegin() - cell must be visible to begin edit");
  9710.         return -1;
  9711.         }
  9712.     if (SetFocus(g, r, c, 0, 0) == -1)
  9713.         {
  9714.         XmLWarning(w, "EditBegin() - can't set focus to cell");
  9715.         return -1;
  9716.         }
  9717.     if (insert == False)
  9718.         TextAction(g, TEXT_EDIT);
  9719.     else 
  9720.         TextAction(g, TEXT_EDIT_INSERT);
  9721.     return 0;
  9722.     }
  9723.  
  9724. void
  9725. XmLGridEditCancel(Widget w)
  9726.     {
  9727.     XmLGridWidget g;
  9728.  
  9729.     g = WidgetToGrid(w, "EditCancel()");
  9730.     if (!g)
  9731.         return;
  9732.     TextAction(g, TEXT_EDIT_CANCEL);
  9733.     }
  9734.  
  9735. void
  9736. XmLGridEditComplete(Widget w)
  9737.     {
  9738.     XmLGridWidget g;
  9739.  
  9740.     g = WidgetToGrid(w, "EditComplete()");
  9741.     if (!g)
  9742.         return;
  9743.     TextAction(g, TEXT_EDIT_COMPLETE);
  9744.     }
  9745.  
  9746. XmLGridColumn
  9747. XmLGridGetColumn(Widget w,
  9748.          unsigned char columnType,
  9749.          int column)
  9750.     {
  9751.     XmLGridWidget g;
  9752.     XmLGridColumn c;
  9753.     int pos;
  9754.  
  9755.     g = WidgetToGrid(w, "GetColumn()");
  9756.     if (!g)
  9757.         return 0;
  9758.     pos = ColTypePosToPos(g, columnType, column, 0);
  9759.     c = (XmLGridColumn)XmLArrayGet(g->grid.colArray, pos);
  9760.     if (!c)
  9761.         XmLWarning(w, "GetColumn() - invalid column");
  9762.     return c;
  9763.     }
  9764.  
  9765. int
  9766. XmLGridGetSelectedCellCount(Widget w)
  9767.     {
  9768.     XmLGridWidget g;
  9769.  
  9770.     g = WidgetToGrid(w, "GetSelectedCellCount()");
  9771.     if (!g)
  9772.         return -1;
  9773.     return GetSelectedArea(g, SelectCell, 0, 0, 0);
  9774.     }
  9775.  
  9776. int
  9777. XmLGridGetSelectedCells(Widget w,
  9778.             int *rowPositions,
  9779.             int *columnPositions,
  9780.             int count)
  9781.     {
  9782.     XmLGridWidget g;
  9783.     int n;
  9784.  
  9785.     g = WidgetToGrid(w, "GetSelectedCells()");
  9786.     if (!g)
  9787.         return -1;
  9788.     n = GetSelectedArea(g, SelectCell, rowPositions, columnPositions, count);
  9789.     if (count != n)
  9790.         {
  9791.         XmLWarning(w, "GetSelectedCells() - count is incorrect");
  9792.         return -1;
  9793.         }
  9794.     return 0;
  9795.     }
  9796.  
  9797. int
  9798. XmLGridGetSelectedColumnCount(Widget w)
  9799.     {
  9800.     XmLGridWidget g;
  9801.  
  9802.     g = WidgetToGrid(w, "GetSelectedColumnCount()");
  9803.     if (!g)
  9804.         return -1;
  9805.     return GetSelectedArea(g, SelectCol, 0, 0, 0);
  9806.     }
  9807.  
  9808. int
  9809. XmLGridGetSelectedColumns(Widget w,
  9810.               int *positions,
  9811.               int count)
  9812.     {
  9813.     XmLGridWidget g;
  9814.     int n;
  9815.  
  9816.     g = WidgetToGrid(w, "GetSelectedColumns()");
  9817.     if (!g)
  9818.         return -1;
  9819.     n = GetSelectedArea(g, SelectCol, 0, positions, count);
  9820.     if (count != n)
  9821.         {
  9822.         XmLWarning(w, "GetSelectedColumns() - count is incorrect");
  9823.         return -1;
  9824.         }
  9825.     return 0;
  9826.     }
  9827.  
  9828. int
  9829. XmLGridGetSelectedRow(Widget w)
  9830.     {
  9831.     XmLGridWidget g;
  9832.     int n, pos;
  9833.  
  9834.     g = WidgetToGrid(w, "GetSelectedRow()");
  9835.     if (!g)
  9836.         return -1;
  9837.     n = GetSelectedArea(g, SelectRow, &pos, 0, 1);
  9838.     if (n != 1)
  9839.         return -1;
  9840.     return pos;
  9841.     }
  9842.  
  9843. int
  9844. XmLGridGetSelectedRowCount(Widget w)
  9845.     {
  9846.     XmLGridWidget g;
  9847.  
  9848.     g = WidgetToGrid(w, "GetSelectedRowCount()");
  9849.     if (!g)
  9850.         return -1;
  9851.     return GetSelectedArea(g, SelectRow, 0, 0, 0);
  9852.     }
  9853.  
  9854. int
  9855. XmLGridGetSelectedRows(Widget w,
  9856.                int *positions,
  9857.                int count)
  9858.     {
  9859.     XmLGridWidget g;
  9860.     int n;
  9861.  
  9862.     g = WidgetToGrid(w, "GetSelectedRows()");
  9863.     if (!g)
  9864.         return -1;
  9865.     n = GetSelectedArea(g, SelectRow, positions, 0, count);
  9866.     if (count != n)
  9867.         {
  9868.         XmLWarning(w, "GetSelectedRows() - count is incorrect");
  9869.         return -1;
  9870.         }
  9871.     return 0;
  9872.     }
  9873.  
  9874. Boolean
  9875. XmLGridColumnIsVisible(Widget w,
  9876.                int col)
  9877.     {
  9878.     XmLGridWidget g;
  9879.  
  9880.     g = WidgetToGrid(w, "ColumnIsVisible()");
  9881.     if (!g)
  9882.         return -1;
  9883.     if (!ColIsVisible(g, g->grid.headingColCount + col))
  9884.         return False;
  9885.     return True;
  9886.     }
  9887.  
  9888. void
  9889. XmLGridMoveColumns(Widget w,
  9890.            int newPosition,
  9891.            int position,
  9892.            int count)
  9893.     {
  9894.     XmLGridWidget g;
  9895.     XmLGridRow row;
  9896.     int i, np, p, rowCount;
  9897.  
  9898.     g = WidgetToGrid(w, "MoveColumns()");
  9899.     if (!g)
  9900.         return;
  9901.     np = ColTypePosToPos(g, XmCONTENT, newPosition, 0);
  9902.     p = ColTypePosToPos(g, XmCONTENT, position, 0);
  9903.     if (XmLArrayMove(g->grid.colArray, np, p, count) == -1)
  9904.         {
  9905.         XmLWarning(w, "MoveColumns() - invalid position");
  9906.         return;
  9907.         }
  9908.     rowCount = XmLArrayGetCount(g->grid.rowArray);
  9909.     for (i = 0; i < rowCount; i++)
  9910.         {
  9911.         row = XmLArrayGet(g->grid.rowArray, i);
  9912.         XmLArrayMove(XmLGridRowCells(row), np, p, count);
  9913.         }
  9914.     VisPosChanged(g, 0);
  9915.     HorizLayout(g, 1);
  9916.     DrawArea(g, DrawAll, 0, 0);
  9917.     }
  9918.  
  9919. void
  9920. XmLGridMoveRows(Widget w,
  9921.         int newPosition,
  9922.         int position,
  9923.         int count)
  9924.     {
  9925.     XmLGridWidget g;
  9926.     int np, p;
  9927.  
  9928.     g = WidgetToGrid(w, "MoveRows()");
  9929.     if (!g)
  9930.         return;
  9931.     np = RowTypePosToPos(g, XmCONTENT, newPosition, 0);
  9932.     p = RowTypePosToPos(g, XmCONTENT, position, 0);
  9933.     if (XmLArrayMove(g->grid.rowArray, np, p, count) == -1)
  9934.         {
  9935.         XmLWarning(w, "MoveRows() - invalid position/count");
  9936.         return;
  9937.         }
  9938.     VisPosChanged(g, 1);
  9939.     VertLayout(g, 1);
  9940.     DrawArea(g, DrawAll, 0, 0);
  9941.     }
  9942.  
  9943. void
  9944. XmLGridReorderColumns(Widget w,
  9945.               int *newPositions,
  9946.               int position,
  9947.               int count)
  9948.     {
  9949.     XmLGridWidget g;
  9950.     XmLGridRow row;
  9951.     int i, *np, p, rowCount, status;
  9952.  
  9953.     g = WidgetToGrid(w, "ReorderColumns()");
  9954.     if (!g)
  9955.         return;
  9956.     if (count <= 0)
  9957.         return;
  9958.     p = ColTypePosToPos(g, XmCONTENT, position, 0);
  9959.     np = (int *)malloc(sizeof(int) * count);
  9960.     for (i = 0; i < count; i++)
  9961.         np[i] = ColTypePosToPos(g, XmCONTENT, newPositions[i], 0);
  9962.     status = XmLArrayReorder(g->grid.colArray, np, p, count);
  9963.     if (status < 0)
  9964.         {
  9965.         free((char *)np);
  9966.         XmLWarning(w, "ReorderColumns() - invalid position/count");
  9967.         return;
  9968.         }
  9969.     rowCount = XmLArrayGetCount(g->grid.rowArray);
  9970.     for (i = 0; i < rowCount; i++)
  9971.         {
  9972.         row = XmLArrayGet(g->grid.rowArray, i);
  9973.         XmLArrayReorder(XmLGridRowCells(row), np, p, count);
  9974.         }
  9975.     free((char *)np);
  9976.     VisPosChanged(g, 0);
  9977.     HorizLayout(g, 1);
  9978.     DrawArea(g, DrawAll, 0, 0);
  9979.     }
  9980.  
  9981. void
  9982. XmLGridReorderRows(Widget w,
  9983.            int *newPositions,
  9984.            int position,
  9985.            int count)
  9986.     {
  9987.     XmLGridWidget g;
  9988.     int i, *np, p, status;
  9989.  
  9990.     g = WidgetToGrid(w, "ReorderRows()");
  9991.     if (!g)
  9992.         return;
  9993.     if (count <= 0)
  9994.         return;
  9995.     p = RowTypePosToPos(g, XmCONTENT, position, 0);
  9996.     np = (int *)malloc(sizeof(int) * count);
  9997.     for (i = 0; i < count; i++)
  9998.         np[i] = RowTypePosToPos(g, XmCONTENT, newPositions[i], 0);
  9999.     status = XmLArrayReorder(g->grid.rowArray, np, p, count);
  10000.     free((char *)np);
  10001.     if (status == -1)
  10002.         {
  10003.         XmLWarning(w, "ReorderRows() - invalid position/count");
  10004.         return;
  10005.         }
  10006.     VisPosChanged(g, 1);
  10007.     VertLayout(g, 1);
  10008.     DrawArea(g, DrawAll, 0, 0);
  10009.     }
  10010.  
  10011. int
  10012. XmLGridRowColumnToXY(Widget w,
  10013.              unsigned char rowType,
  10014.              int row,
  10015.              unsigned char columnType,
  10016.              int column,
  10017.              Boolean clipped,
  10018.              XRectangle *rect)
  10019.     {
  10020.     XmLGridWidget g;
  10021.     int r, c;
  10022.  
  10023.     g = WidgetToGrid(w, "RowColumnToXY()");
  10024.     if (!g)
  10025.         return -1;
  10026.     r = RowTypePosToPos(g, rowType, row, 0);
  10027.     c = ColTypePosToPos(g, columnType, column, 0);
  10028.     if (r < 0 || r >= XmLArrayGetCount(g->grid.rowArray) ||
  10029.         c < 0 || c >= XmLArrayGetCount(g->grid.colArray))
  10030.         {
  10031. /*        XmLWarning(w, "RowColumnToXY() - invalid position");*/
  10032.         return -1;
  10033.         }
  10034.     return RowColToXY(g, r, c, clipped, rect);
  10035.     }
  10036.  
  10037. Boolean
  10038. XmLGridRowIsVisible(Widget w, int row)
  10039.     {
  10040.     XmLGridWidget g;
  10041.  
  10042.     g = WidgetToGrid(w, "RowIsVisible()");
  10043.     if (!g)
  10044.         return -1;
  10045.     if (!RowIsVisible(g, g->grid.headingRowCount + row))
  10046.         return False;
  10047.     return True;
  10048.     }
  10049.  
  10050. void
  10051. XmLGridSelectAllRows(Widget w,
  10052.              Boolean notify)
  10053.     {
  10054.     XmLGridWidget g;
  10055.  
  10056.     g = WidgetToGrid(w, "SelectAllRows()");
  10057.     if (!g)
  10058.         return;
  10059.     SelectTypeArea(g, SelectRow, (XEvent *)0, -1, 0, True, notify);
  10060.     }
  10061.  
  10062. void
  10063. XmLGridSelectAllColumns(Widget w,
  10064.             Boolean notify)
  10065.     {
  10066.     XmLGridWidget g;
  10067.  
  10068.     g = WidgetToGrid(w, "SelectAllColumns()");
  10069.     if (!g)
  10070.         return;
  10071.     SelectTypeArea(g, SelectCol, (XEvent *)0, 0, -1, True, notify);
  10072.     }
  10073.  
  10074. void
  10075. XmLGridSelectAllCells(Widget w,
  10076.               Boolean notify)
  10077.     {
  10078.     XmLGridWidget g;
  10079.  
  10080.     g = WidgetToGrid(w, "SelectAllCells()");
  10081.     if (!g)
  10082.         return;
  10083.     SelectTypeArea(g, SelectCell, (XEvent *)0, -1, -1, True, notify);
  10084.     }
  10085.  
  10086. void
  10087. XmLGridSelectCell(Widget w,
  10088.           int row,
  10089.           int column,
  10090.           Boolean notify)
  10091.     {
  10092.     XmLGridWidget g;
  10093.  
  10094.     g = WidgetToGrid(w, "SelectCell()");
  10095.     if (!g)
  10096.         return;
  10097.     SelectTypeArea(g, SelectCell, (XEvent *)0, row, column, True, notify);
  10098.     }
  10099.  
  10100. void
  10101. XmLGridSelectColumn(Widget w,
  10102.             int column,
  10103.             Boolean notify)
  10104.     {
  10105.     XmLGridWidget g;
  10106.  
  10107.     g = WidgetToGrid(w, "SelectColumn()");
  10108.     if (!g)
  10109.         return;
  10110.     SelectTypeArea(g, SelectCol, (XEvent *)0, 0, column, True, notify);
  10111.     }
  10112.  
  10113. void
  10114. XmLGridSelectRow(Widget w,
  10115.          int row,
  10116.          Boolean notify)
  10117.     {
  10118.     XmLGridWidget g;
  10119.  
  10120.     g = WidgetToGrid(w, "SelectRow()");
  10121.     if (!g)
  10122.         return;
  10123.     SelectTypeArea(g, SelectRow, (XEvent *)0, row, 0, True, notify);
  10124.     }
  10125.  
  10126. int
  10127. XmLGridSetFocus(Widget w,
  10128.         int row,
  10129.         int column)
  10130.     {
  10131.     XmLGridWidget g;
  10132.     int r, c;
  10133.  
  10134.     g = WidgetToGrid(w, "SetFocus()");
  10135.     if (!g)
  10136.         return -1;
  10137.     if (row < 0 || row >= g->grid.rowCount)
  10138.         {
  10139.         XmLWarning(w, "SetFocus() - invalid row");
  10140.         return -1;
  10141.         }
  10142.     if (column < 0 || column >= g->grid.colCount)
  10143.         {
  10144.         XmLWarning(w, "SetFocus() - invalid column");
  10145.         return -1;
  10146.         }
  10147.     r = RowTypePosToPos(g, XmCONTENT, row, 0);
  10148.     c = ColTypePosToPos(g, XmCONTENT, column, 0);
  10149.     return SetFocus(g, r, c, 0, 0);
  10150.     }
  10151.  
  10152. int
  10153. XmLGridXYToRowColumn(Widget w,
  10154.              int x,
  10155.              int y,
  10156.              unsigned char *rowType,
  10157.              int *row,
  10158.              unsigned char *columnType,
  10159.              int *column)
  10160.     {
  10161.     XmLGridWidget g;
  10162.     int r, c;
  10163.  
  10164.     g = WidgetToGrid(w, "XYToRowColumn()");
  10165.     if (!g)
  10166.         return -1;
  10167.     if (XYToRowCol(g, x, y, &r, &c) == -1)
  10168.         return -1;
  10169.     *rowType = RowPosToType(g, r);
  10170.     *row = RowPosToTypePos(g, *rowType, r);
  10171.     *columnType = ColPosToType(g, c);
  10172.     *column = ColPosToTypePos(g, *columnType, c);
  10173.     return 0;
  10174.     }
  10175.  
  10176. void
  10177. XmLGridRedrawAll(Widget w)
  10178.     {
  10179.     XmLGridWidget g;
  10180.  
  10181.     g = WidgetToGrid(w, "RedrawAll()");
  10182.     if (!g)
  10183.         return;
  10184.     DrawArea(g, DrawAll, 0, 0);
  10185.     }
  10186.  
  10187. void
  10188. XmLGridRedrawCell(Widget w,
  10189.           unsigned char rowType,
  10190.           int row,
  10191.           unsigned char columnType,
  10192.           int column)
  10193.     {
  10194.     XmLGridWidget g;
  10195.     int r, c;
  10196.  
  10197.     g = WidgetToGrid(w, "RedrawCell()");
  10198.     if (!g)
  10199.         return;
  10200.     r = RowTypePosToPos(g, rowType, row, 0);
  10201.     c = ColTypePosToPos(g, columnType, column, 0);
  10202.     DrawArea(g, DrawCell, r, c);
  10203.     }
  10204.  
  10205. void
  10206. XmLGridRedrawColumn(Widget w,
  10207.             unsigned char type,
  10208.             int column)
  10209.     {
  10210.     XmLGridWidget g;
  10211.     int c;
  10212.  
  10213.     g = WidgetToGrid(w, "RedrawColumn()");
  10214.     if (!g)
  10215.         return;
  10216.     c = ColTypePosToPos(g, type, column, 0);
  10217.     DrawArea(g, DrawCol, 0, c);
  10218.     }
  10219.  
  10220. void
  10221. XmLGridRedrawRow(Widget w,
  10222.          unsigned char type,
  10223.          int row)
  10224.     {
  10225.     XmLGridWidget g;
  10226.     int r;
  10227.  
  10228.     g = WidgetToGrid(w, "RedrawRow()");
  10229.     if (!g)
  10230.         return;
  10231.     r = RowTypePosToPos(g, type, row, 0);
  10232.     DrawArea(g, DrawRow, r, 0);
  10233.     }
  10234.  
  10235. int
  10236. XmLGridRead(Widget w,
  10237.         FILE *file,
  10238.         int format,
  10239.         char delimiter)
  10240.     {
  10241.     XmLGridWidget g;
  10242.     char *data;
  10243.     int n;
  10244.  
  10245.     g = WidgetToGrid(w, "Read()");
  10246.     if (!g)
  10247.         return 0;
  10248.     if (!file)
  10249.         {
  10250.         XmLWarning(w, "Read() - file is NULL");
  10251.         return 0;
  10252.         }
  10253.     data = FileToString(file);
  10254.     if (!data)
  10255.         {
  10256.         XmLWarning(w, "Read() - error loading file");
  10257.         return 0;
  10258.         }
  10259.     n = Read(g, format, delimiter, 0, 0, data);
  10260.     free((char *)data);
  10261.     return n;
  10262.     }
  10263.  
  10264. int
  10265. XmLGridReadPos(Widget w,
  10266.            FILE *file,
  10267.            int format,
  10268.            char delimiter,
  10269.            unsigned char rowType,
  10270.            int row,
  10271.            unsigned char columnType,
  10272.            int column)
  10273.     {
  10274.     XmLGridWidget g;
  10275.     char *data;
  10276.     int r, c, n;
  10277.  
  10278.     g = WidgetToGrid(w, "ReadPos()");
  10279.     if (!g)
  10280.         return 0;
  10281.     if (!file)
  10282.         {
  10283.         XmLWarning(w, "ReadPos() - file is NULL");
  10284.         return 0;
  10285.         }
  10286.     data = FileToString(file);
  10287.     if (!data)
  10288.         {
  10289.         XmLWarning(w, "ReadPos() - error loading file");
  10290.         return 0;
  10291.         }
  10292.     r = RowTypePosToPos(g, rowType, row, 0);
  10293.     c = ColTypePosToPos(g, columnType, column, 0);
  10294.     n = Read(g, format, delimiter, r, c, data);
  10295.     free((char *)data);
  10296.     return n;
  10297.     }
  10298.  
  10299. int
  10300. XmLGridSetStrings(Widget w,
  10301.           char *data)
  10302.     {
  10303.     XmLGridWidget g;
  10304.  
  10305.     g = WidgetToGrid(w, "SetStrings()");
  10306.     if (!g)
  10307.         return 0;
  10308.     return Read(g, XmFORMAT_DELIMITED, '|', 0, 0, data);
  10309.     }
  10310.  
  10311. int
  10312. XmLGridSetStringsPos(Widget w,
  10313.              unsigned char rowType,
  10314.              int row,
  10315.              unsigned char columnType,
  10316.              int column,
  10317.              char *data)
  10318.     {
  10319.     XmLGridWidget g;
  10320.     int r, c;
  10321.  
  10322.     g = WidgetToGrid(w, "SetStringsPos()");
  10323.     if (!g)
  10324.         return 0;
  10325.     r = RowTypePosToPos(g, rowType, row, 0);
  10326.     c = ColTypePosToPos(g, columnType, column, 0);
  10327.     return Read(g, XmFORMAT_DELIMITED, '|', r, c, data);
  10328.     }
  10329.  
  10330. int
  10331. XmLGridWrite(Widget w,
  10332.          FILE *file,
  10333.          int format,
  10334.          char delimiter,
  10335.          Boolean skipHidden)
  10336.     {
  10337.     XmLGridWidget g;
  10338.     int nrow, ncol;
  10339.  
  10340.     g = WidgetToGrid(w, "Write()");
  10341.     if (!g)
  10342.         return 0;
  10343.     nrow = XmLArrayGetCount(g->grid.rowArray);
  10344.     ncol = XmLArrayGetCount(g->grid.colArray);
  10345.     Write(g, file, format, delimiter, skipHidden, 0, 0, nrow, ncol);
  10346.     return 0;
  10347.     }
  10348.  
  10349. int
  10350. XmLGridWritePos(Widget w,
  10351.         FILE *file,
  10352.         int format,
  10353.         char delimiter,
  10354.         Boolean skipHidden,
  10355.         unsigned char rowType,
  10356.         int row,
  10357.         unsigned char columnType,
  10358.         int column,
  10359.         int nrow,
  10360.         int ncolumn)
  10361.     {
  10362.     XmLGridWidget g;
  10363.     int r, c;
  10364.  
  10365.     g = WidgetToGrid(w, "WritePos()");
  10366.     if (!g)
  10367.         return 0;
  10368.     r = RowTypePosToPos(g, rowType, row, 0);
  10369.     c = ColTypePosToPos(g, columnType, column, 0);
  10370.     Write(g, file, format, delimiter, skipHidden, r, c, nrow, ncolumn);
  10371.     return 0;
  10372.     }
  10373.  
  10374. Boolean
  10375. XmLGridCopyPos(Widget w,
  10376.            Time time,
  10377.            unsigned char rowType,
  10378.            int row,
  10379.            unsigned char columnType,
  10380.            int column,
  10381.            int nrow,
  10382.            int ncolumn)
  10383.     {
  10384.     XmLGridWidget g;
  10385.     int r, c;
  10386.  
  10387.     g = WidgetToGrid(w, "CopyPos()");
  10388.     if (!g)
  10389.         return False;
  10390.     r = RowTypePosToPos(g, rowType, row, 0);
  10391.     c = ColTypePosToPos(g, columnType, column, 0);
  10392.     return Copy(g, time, 0, r, c, nrow, ncolumn);
  10393.     }
  10394.  
  10395. Boolean
  10396. XmLGridCopySelected(Widget w,
  10397.             Time time)
  10398.     {
  10399.     XmLGridWidget g;
  10400.  
  10401.     g = WidgetToGrid(w, "CopySelected()");
  10402.     if (!g)
  10403.         return False;
  10404.     return Copy(g, time, 1, 0, 0, 0, 0);
  10405.     }
  10406.  
  10407. Boolean
  10408. XmLGridPaste(Widget w)
  10409.     {
  10410.     XmLGridWidget g;
  10411.     int r, c;
  10412.  
  10413.     g = WidgetToGrid(w, "Paste()");
  10414.     if (!g)
  10415.         return False;
  10416.     r = g->grid.focusRow;
  10417.     c = g->grid.focusCol;
  10418.     if (r < 0 || c < 0)
  10419.         {
  10420.         XmLWarning(w, "Paste() - no cell has focus");
  10421.         return False;
  10422.         }
  10423.     return Paste(g, r, c);
  10424.     }
  10425.  
  10426. Boolean
  10427. XmLGridPastePos(Widget w,
  10428.         unsigned char rowType,
  10429.         int row,
  10430.         unsigned char columnType,
  10431.         int column)
  10432.     {
  10433.     XmLGridWidget g;
  10434.     int r, c;
  10435.  
  10436.     g = WidgetToGrid(w, "PastePos()");
  10437.     if (!g)
  10438.         return False;
  10439.     r = RowTypePosToPos(g, rowType, row, 0);
  10440.     c = ColTypePosToPos(g, columnType, column, 0);
  10441.     return Paste(g, r, c);
  10442.     }
  10443.  
  10444. /* XFE Additions below here */
  10445. void
  10446. XmLGridInstallHideButtonTranslations(Widget w)
  10447. {
  10448.   XmLGridWidget g = (XmLGridWidget)w;
  10449.   Widget hideButton = g->grid.hideButton;
  10450.  
  10451.   if (g->grid.showHideButton == False
  10452.       || hideButton == NULL)
  10453.     return;
  10454.  
  10455.   /*  XtOverrideTranslations(hideButton, g->grid.hideButtonTrans);*/
  10456. }
  10457.  
  10458. static void 
  10459. HideColumn(Widget w, 
  10460.        XEvent *event, 
  10461.        String *params, 
  10462.        Cardinal *num_params)
  10463. {
  10464.     XmLGridWidget g = (XmLGridWidget)w;
  10465.  
  10466.     if (g->grid.colCount == 1 || g->grid.colCount == 0) {
  10467.     /* if there's only one column left, don't let them
  10468.        hide it.  Also, if there are no columns at all,
  10469.        they can't hide any. */
  10470.  
  10471.     return;
  10472.     }
  10473.     else {
  10474.     
  10475.     if (g->grid.realColCount == -1) {
  10476.         /* nothing's been hidden yet, so we save off the
  10477.            actual column count before mucking with it. */
  10478.         g->grid.realColCount = g->grid.colCount;
  10479.     }
  10480.  
  10481.     g->grid.colCount--;
  10482.     
  10483.     HorizLayout(g, 1);
  10484.     DrawArea(g, DrawAll, 0, 0);
  10485.     }
  10486. }
  10487.  
  10488. void
  10489. XmLGridSetVisibleColumnCount(Widget w,
  10490.                  int num_visible)
  10491. {
  10492.   XmLGridWidget g = (XmLGridWidget)w;
  10493.   int real_count;
  10494.  
  10495.   if (g->grid.realColCount == -1)
  10496.     real_count = g->grid.colCount;
  10497.   else
  10498.     real_count = g->grid.realColCount;
  10499.  
  10500.   if (num_visible > real_count)
  10501.     return; /* should really be an error... */
  10502.  
  10503.   if (g->grid.realColCount == -1)
  10504.     g->grid.realColCount = g->grid.colCount;
  10505.  
  10506.   g->grid.colCount = num_visible;
  10507. }
  10508.  
  10509. static void 
  10510. UnhideColumn(Widget w, 
  10511.          XEvent *event, 
  10512.          String *params, 
  10513.          Cardinal *num_params)
  10514. {
  10515.     XmLGridWidget g = (XmLGridWidget)w;
  10516.  
  10517.     if (g->grid.realColCount == -1) {
  10518.     /* there is nothing hidden, so we can't unhide it */
  10519.     return;
  10520.     }
  10521.     else {
  10522.  
  10523.     g->grid.colCount++;
  10524.  
  10525.     HorizLayout(g, 1);
  10526.     DrawArea(g, DrawAll, 0, 0);
  10527.  
  10528.     if (g->grid.colCount == g->grid.realColCount) {
  10529.         /* there's nothing hidden anymore, so we reinitialize
  10530.            the realColCount to -1, as some functions (like this
  10531.            one) might want to use this value */
  10532.         g->grid.realColCount = -1;
  10533.     }
  10534.     }
  10535. }
  10536.  
  10537. static void 
  10538. MenuArm(Widget w, 
  10539.     XEvent *event, 
  10540.     String *params, 
  10541.     Cardinal *num_params)
  10542. {
  10543.     XmLGridWidget g = (XmLGridWidget)w;
  10544.  
  10545.     SelectTypeArea(g, SelectRow, (XEvent *)0, g->grid.lastSelectRow, 0, False, False);
  10546.  
  10547.     g->grid.inMode = InSelect;
  10548. }
  10549.  
  10550. static void 
  10551. MenuDisarm(Widget w, 
  10552.        XEvent *event, 
  10553.        String *params, 
  10554.        Cardinal *num_params)
  10555. {
  10556.     XmLGridWidget g = (XmLGridWidget)w;
  10557.  
  10558.     g->grid.inMode = InNormal;
  10559. }
  10560.  
  10561.  
  10562.  
  10563.