/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* * The following source code is part of the Microline Widget Library. * The Microline widget library is made available to Mozilla developers * under the Netscape Public License (NPL) by Neuron Data. To learn * more about Neuron Data, please visit the Neuron Data Home Page at * http://www.neurondata.com. */ #include "GridP.h" #include #include #include #include #ifndef MOTIF11 #include #endif #include #include #include #include #ifdef SUNOS4 int fprintf(FILE *, char *, ...); int fseek(FILE *, long, int); int fread(char *, int, int, FILE *); #endif /* Create and Destroy */ static void ClassInitialize(void); static void ClassPartInitialize(WidgetClass wc); static void Initialize(Widget req, Widget newW, ArgList args, Cardinal *nargs); static void Destroy(Widget w); /* Geometry, Drawing, Entry and Picking */ static void Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attr); static void Redisplay(Widget w, XExposeEvent *event, Region region); static void DrawResizeLine(XmLGridWidget g, int xy, int erase); static void DrawXORRect(XmLGridWidget g, int xy, int size, int isVert, int erase); static void DefineCursor(XmLGridWidget g, char defineCursor); static void DrawArea(XmLGridWidget g, int type, int row, int col); static void ExtendSelectRange(XmLGridWidget g, int *type, int *fr, int *lr, int *fc, int *lc); static void ExtendSelect(XmLGridWidget g, XEvent *event, Boolean set, int row, int col); static void SelectTypeArea(XmLGridWidget g, int type, XEvent *event, int row, int col, Boolean select, Boolean notify); static int GetSelectedArea(XmLGridWidget g, int type, int *rowPos, int *colPos, int count); static void ChangeManaged(Widget w); static void Resize(Widget w); static void PlaceScrollbars(XmLGridWidget w); static void VertLayout(XmLGridWidget g, int resizeIfNeeded); static void HorizLayout(XmLGridWidget g, int resizeIfNeeded); static void ApplyVisibleRows(XmLGridWidget g); static void ApplyVisibleCols(XmLGridWidget g); static void VisPosChanged(XmLGridWidget g, int isVert); static void RecalcVisPos(XmLGridWidget g, int isVert); static int PosToVisPos(XmLGridWidget g, int pos, int isVert); static int VisPosToPos(XmLGridWidget g, int visPos, int isVert); static unsigned char ColPosToType(XmLGridWidget g, int pos); static int ColPosToTypePos(XmLGridWidget g, unsigned char type, int pos); static unsigned char RowPosToType(XmLGridWidget g, int pos); static int RowPosToTypePos(XmLGridWidget g, unsigned char type, int pos); static int ColTypePosToPos(XmLGridWidget g, unsigned char type, int pos, int allowNeg); static int RowTypePosToPos(XmLGridWidget g, unsigned char type, int pos, int allowNeg); static int ScrollRowBottomPos(XmLGridWidget g, int row); static int ScrollColRightPos(XmLGridWidget g, int col); static int PosIsResize(XmLGridWidget g, int x, int y, int *row, int *col, int *isVert); static int XYToRowCol(XmLGridWidget g, int x, int y, int *row, int *col); static int RowColToXY(XmLGridWidget g, int row, int col, Boolean clipped, XRectangle *rect); static int RowColFirstSpan(XmLGridWidget g, int row, int col, int *spanRow, int *spanCol, XRectangle *rect, Boolean lookLeft, Boolean lookUp); static void RowColSpanRect(XmLGridWidget g, int row, int col, XRectangle *rect); static XmLGridCell GetCell(XmLGridWidget g, int row, int col); static int GetColWidth(XmLGridWidget g, int col); static int GetRowHeight(XmLGridWidget g, int row); static int ColIsVisible(XmLGridWidget g, int col); static int RowIsVisible(XmLGridWidget g, int row); static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *); static void ScrollCB(Widget w, XtPointer, XtPointer); static int FindNextFocus(XmLGridWidget g, int row, int col, int rowDir, int colDir, int *nextRow, int *nextCol); static int SetFocus(XmLGridWidget g, int row, int col, int rowDir, int colDir); static void ChangeFocus(XmLGridWidget g, int row, int col); static void MakeColVisible(XmLGridWidget g, int col); static void MakeRowVisible(XmLGridWidget g, int row); static void TextAction(XmLGridWidget g, int action); /* Getting and Setting Values */ static void GetSubValues(Widget w, ArgList args, Cardinal *nargs); static void SetSubValues(Widget w, ArgList args, Cardinal *nargs); static Boolean SetValues(Widget curW, Widget, Widget newW, ArgList args, Cardinal *nargs); static void CopyFontList(XmLGridWidget g); static Boolean CvtStringToSizePolicy(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToSelectionPolicy(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToRowColType(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToCellAlignment(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToCellType(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static Boolean CvtStringToCellBorderType(Display *dpy, XrmValuePtr args, Cardinal *numArgs, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data); static void SetSimpleHeadings(XmLGridWidget g, char *data); static void SetSimpleWidths(XmLGridWidget g, char *data); /* Getting and Setting Row Values */ static void GetRowValueMask(XmLGridWidget g, char *s, long *mask); static void _GetRowValueMask(XmLGridWidget g, char *s, long *mask); static void GetRowValue(XmLGridWidget g, XmLGridRow row, XtArgVal value, long mask); static void _GetRowValue(XmLGridWidget g, XmLGridRow row, XtArgVal value, long mask); static int SetRowValues(XmLGridWidget g, XmLGridRow row, long mask); static int _SetRowValues(XmLGridWidget g, XmLGridRow row, long mask); /* Getting and Setting Column Values */ static void GetColumnValueMask(XmLGridWidget g, char *s, long *mask); static void _GetColumnValueMask(XmLGridWidget g, char *s, long *mask); static void GetColumnValue(XmLGridWidget g, XmLGridColumn col, XtArgVal value, long mask); static void _GetColumnValue(XmLGridWidget g, XmLGridColumn col, XtArgVal value, long mask); static int SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask); static int _SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask); /* Getting and Setting Cell Values */ static void CellValueGetMask(char *s, long *mask); static void GetCellValue(XmLGridCell cell, XtArgVal value, long mask); static XmLGridCellRefValues *CellRefValuesCreate(XmLGridWidget g, XmLGridCellRefValues *copy); static void SetCellValuesPreprocess(XmLGridWidget g, long mask); static int SetCellHasRefValues(long mask); static int SetCellValuesResize(XmLGridWidget g, XmLGridRow row, XmLGridColumn col, XmLGridCell cell, long mask); static int _SetCellValuesResize(XmLGridWidget g, XmLGridRow row, XmLGridColumn col, XmLGridCell cell, long mask); static void SetCellValues(XmLGridWidget g, XmLGridCell cell, long mask); static void SetCellRefValues(XmLGridWidget g, XmLGridCellRefValues *values, long mask); static int SetCellRefValuesCompare(void *, void **, void **); static void SetCellRefValuesPreprocess(XmLGridWidget g, int row, int col, XmLGridCell cell, long mask); /* Read, Write, Copy, Paste */ static int Read(XmLGridWidget g, int format, char delimiter, int row, int col, char *data); static void Write(XmLGridWidget g, FILE *file, int format, char delimiter, Boolean skipHidden, int row, int col, int nrow, int ncol); static char *CopyDataCreate(XmLGridWidget g, int selected, int row, int col, int nrow, int ncol); static Boolean Copy(XmLGridWidget g, Time time, int selected, int row, int col, int nrow, int ncol); static Boolean Paste(XmLGridWidget g, int row, int col); /* Utility */ static void GetCoreBackground(Widget w, int, XrmValue *value); static void GetManagerForeground(Widget w, int, XrmValue *value); static void ClipRectToReg(XmLGridWidget g, XRectangle *rect, GridReg *reg); static char *FileToString(FILE *file); static char *CvtXmStringToStr(XmString str); static XmLGridWidget WidgetToGrid(Widget w, char *funcname); /* Actions, Callbacks and Handlers */ static void ButtonMotion(Widget w, XEvent *event, String *, Cardinal *); static void DragTimer(XtPointer, XtIntervalId *); static void CursorMotion(Widget w, XEvent *event, String *, Cardinal *); static void Edit(Widget w, XEvent *event, String *, Cardinal *); static void EditCancel(Widget w, XEvent *event, String *, Cardinal *); static void EditComplete(Widget w, XEvent *event, String *, Cardinal *); static void DragStart(Widget w, XEvent *event, String *, Cardinal *); static Boolean DragConvert(Widget w, Atom *selection, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format); static void DragFinish(Widget w, XtPointer clientData, XtPointer callData); static void DropRegister(XmLGridWidget g, Boolean set); static void DropStart(Widget w, XtPointer clientData, XtPointer callData); static void DropTransfer(Widget w, XtPointer clientData, Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format); static void Select(Widget w, XEvent *event, String *, Cardinal *); static void PopupSelect(Widget w, XEvent *event, String *, Cardinal *); static void TextActivate(Widget w, XtPointer clientData, XtPointer callData); static void TextFocus(Widget w, XtPointer clientData, XtPointer callData); static void TextMapped(Widget w, XtPointer closure, XEvent *event, Boolean *ctd); static void TextModifyVerify(Widget w, XtPointer clientData, XtPointer callData); static void Traverse(Widget w, XEvent *event, String *, Cardinal *); /* XFE Additions */ static void EditTimer(XtPointer, XtIntervalId *); static void CreateHideUnhideButtons(XmLGridWidget g); static void HideAction(Widget w, XEvent *event, String *, Cardinal *); static void UnhideAction(Widget w, XEvent *event, String *, Cardinal *); static void setHideUnhideSensitivity(Widget w); static void MenuArm(Widget w, XEvent *event, String *, Cardinal *); static void MenuDisarm(Widget w, XEvent *event, String *, Cardinal *); static int SizeColumnsToFit(XmLGridWidget g, int start_at); static void GridCrossingEH(Widget w, XtPointer closure, XEvent *event, Boolean *ctd); static void GridInvokeCellCrossingCallbacks(Widget w,XtCallbackList list, int reason,XEvent * event, int row,int col); static void GridCrossingEH(Widget w,XtPointer closure,XEvent * event, Boolean * ctd); /* XmLGridRow */ static XmLGridRow XmLGridRowNew(Widget grid); static void XmLGridRowFree(Widget grid, XmLGridRow row); static XmLGridRow _GridRowNew(Widget grid); static void _GridRowFree(XmLGridRow row); static XmLArray XmLGridRowCells(XmLGridRow row); static int XmLGridRowGetPos(XmLGridRow row); static int XmLGridRowGetVisPos(XmLGridRow row); static Boolean XmLGridRowIsHidden(XmLGridRow row); static Boolean XmLGridRowIsSelected(XmLGridRow row); static void XmLGridRowSetSelected(XmLGridRow row, Boolean selected); static void XmLGridRowSetVisPos(XmLGridRow row, int visPos); static int XmLGridRowHeightInPixels(XmLGridRow row); static void XmLGridRowHeightChanged(XmLGridRow row); /* XmLGridColumn */ static XmLGridColumn XmLGridColumnNew(Widget grid); static void XmLGridColumnFree(Widget grid, XmLGridColumn column); static XmLGridColumn _GridColumnNew(Widget grid); static void _GridColumnFree(XmLGridColumn column); static int XmLGridColumnGetPos(XmLGridColumn column); static int XmLGridColumnGetVisPos(XmLGridColumn column); static Boolean XmLGridColumnIsHidden(XmLGridColumn column); static Boolean XmLGridColumnIsSelected(XmLGridColumn column); static void XmLGridColumnSetSelected(XmLGridColumn column, Boolean selected); static void XmLGridColumnSetVisPos(XmLGridColumn column, int visPos); static int XmLGridColumnWidthInPixels(XmLGridColumn column); static void XmLGridColumnWidthChanged(XmLGridColumn column); /* XmLGridCell */ static XmLGridCell XmLGridCellNew(); static void XmLGridCellFree(Widget grid, XmLGridCell cell); static int XmLGridCellAction(XmLGridCell cell, Widget w, XmLGridCallbackStruct *cbs); static int _GridCellAction(XmLGridCell cell, Widget w, XmLGridCallbackStruct *cbs); static XmLGridCellRefValues *XmLGridCellGetRefValues(XmLGridCell cell); static void XmLGridCellSetRefValues(XmLGridCell cell, XmLGridCellRefValues *values); static void XmLGridCellDerefValues(XmLGridCellRefValues *values); static Boolean XmLGridCellInRowSpan(XmLGridCell cell); static Boolean XmLGridCellInColumnSpan(XmLGridCell cell); static Boolean XmLGridCellIsSelected(XmLGridCell cell); static Boolean XmLGridCellIsValueSet(XmLGridCell cell); static void XmLGridCellSetValueSet(XmLGridCell cell, Boolean set); static void XmLGridCellSetInRowSpan(XmLGridCell cell, Boolean set); static void XmLGridCellSetInColumnSpan(XmLGridCell cell, Boolean set); static void XmLGridCellSetSelected(XmLGridCell cell, Boolean selected); static void XmLGridCellAllocIcon(XmLGridCell cell); static void XmLGridCellAllocPixmap(XmLGridCell cell); static void XmLGridCellSetString(XmLGridCell cell, XmString string, Boolean copy); static XmString XmLGridCellGetString(XmLGridCell cell); static void XmLGridCellSetToggle(XmLGridCell cell, Boolean state); static Boolean XmLGridCellGetToggle(XmLGridCell cell); static void XmLGridCellSetPixmap(XmLGridCell cell, Pixmap pixmap, Dimension width, Dimension height); static void XmLGridCellSetPixmask(XmLGridCell cell, Pixmap pixmask); static XmLGridCellPixmap *XmLGridCellGetPixmap(XmLGridCell cell); /* static void XmLGridCellClearTextString(XmLGridCell cell, Widget w); */ static int _XmLGridCellConfigureText(XmLGridCell cell, Widget w, XRectangle *rect); static int _XmLGridCellBeginTextEdit(XmLGridCell cell, Widget w, XRectangle *clipRect); static void _XmLGridCellCompleteTextEdit(XmLGridCell cell, Widget w); static void _XmLGridCellInsertText(XmLGridCell cell, Widget w); static int _XmLGridCellGetHeight(XmLGridCell cell, Widget w,XmLGridRow row); static int _XmLGridCellGetWidth(XmLGridCell cell, Widget w,XmLGridColumn col); static void _XmLGridCellFreeValue(XmLGridCell cell); static XtActionsRec actions[] = { { "XmLGridEditComplete", EditComplete }, { "XmLGridButtonMotion", ButtonMotion }, { "XmLGridCursorMotion", CursorMotion }, { "XmLGridEditCancel", EditCancel }, { "XmLGridEdit", Edit }, { "XmLGridSelect", Select }, { "XmLGridPopupSelect", PopupSelect }, { "XmLGridDragStart", DragStart }, { "XmLGridTraverse", Traverse }, /* XFE Additions */ { "XmLGridHideColumn", HideAction }, { "XmLGridUnhideColumn", UnhideAction }, { "MenuArm", MenuArm }, { "MenuDisarm", MenuDisarm }, }; #define TEXT_HIDE 1 #define TEXT_SHOW 2 #define TEXT_EDIT 3 #define TEXT_EDIT_CANCEL 4 #define TEXT_EDIT_COMPLETE 5 #define TEXT_EDIT_INSERT 6 /* future defines */ #define XmTOGGLE_CELL 240 /* backwards compatibility defines */ #define XmTEXT_CELL 250 #define XmLABEL_CELL 251 /* Cursors */ #define horizp_width 19 #define horizp_height 13 static unsigned char horizp_bits[] = { 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xff, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x20, 0x46, 0x00, 0x30, 0xc6, 0x00, 0x38, 0xc6, 0x01, 0xfc, 0xff, 0x03, 0x38, 0xc6, 0x01, 0x30, 0xc6, 0x00, 0x20, 0x46, 0x00, 0x00, 0x06, 0x00 }; #define horizm_width 19 #define horizm_height 13 static unsigned char horizm_bits[] = { 0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00, 0xff, 0x0f, 0x00, 0x60, 0x6f, 0x00, 0x70, 0xef, 0x00, 0x78, 0xef, 0x01, 0xfc, 0xff, 0x03, 0xfe, 0xff, 0x07, 0xfc, 0xff, 0x03, 0x78, 0xef, 0x01, 0x70, 0xef, 0x00, 0x60, 0x6f, 0x00 }; #define vertp_width 13 #define vertp_height 19 static unsigned char vertp_bits[] = { 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x03, 0xc6, 0x07, 0xe6, 0x0f, 0x06, 0x01, 0x06, 0x01, 0x06, 0x01, 0xfe, 0x1f, 0xfe, 0x1f, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 0x00, 0x01, 0x00, 0x00}; #define vertm_width 13 #define vertm_height 19 static unsigned char vertm_bits[] = { 0x0f, 0x00, 0x0f, 0x01, 0x8f, 0x03, 0xcf, 0x07, 0xef, 0x0f, 0xff, 0x1f, 0xff, 0x1f, 0x8f, 0x03, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0xff, 0x1f, 0x80, 0x03, 0xf0, 0x1f, 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 0x00, 0x01}; /* Grid Translations */ static char translations[] = ": XmLGridButtonMotion()\n\ : XmLGridCursorMotion()\n\ ~Ctrl ~Shift : XmLGridSelect(BEGIN)\n\ ~Ctrl Shift : XmLGridSelect(EXTEND)\n\ Ctrl ~Shift : XmLGridSelect(TOGGLE)\n\ : XmLGridSelect(END)\n\ : XmLGridDragStart()\n\ ~Ctrl ~Shift : XmLGridPopupSelect(BEGIN)\n\ ~Ctrl Shift : XmLGridPopupSelect(EXTEND)\n\ Ctrl ~Shift : XmLGridPopupSelect(TOGGLE)\n\ : ManagerEnter()\n\ : ManagerLeave()\n\ : ManagerFocusOut()\n\ : ManagerFocusIn()"; /* Text Translations */ static char traverseTranslations[] = "~Ctrl ~Shift osfUp: XmLGridTraverse(UP)\n\ ~Ctrl Shift osfUp: XmLGridTraverse(EXTEND_UP)\n\ Ctrl ~Shift osfUp: XmLGridTraverse(PAGE_UP)\n\ ~Ctrl ~Shift osfDown: XmLGridTraverse(DOWN)\n\ ~Ctrl Shift osfDown: XmLGridTraverse(EXTEND_DOWN)\n\ Ctrl ~Shift osfDown: XmLGridTraverse(PAGE_DOWN)\n\ ~Ctrl ~Shift osfLeft: XmLGridTraverse(LEFT)\n\ ~Ctrl Shift osfLeft: XmLGridTraverse(EXTEND_LEFT)\n\ Ctrl ~Shift osfLeft: XmLGridTraverse(PAGE_LEFT)\n\ ~Ctrl ~Shift osfRight: XmLGridTraverse(RIGHT)\n\ ~Ctrl Shift osfRight: XmLGridTraverse(EXTEND_RIGHT)\n\ Ctrl ~Shift osfRight: XmLGridTraverse(PAGE_RIGHT)\n\ ~Ctrl ~Shift osfPageUp: XmLGridTraverse(PAGE_UP)\n\ ~Ctrl Shift osfPageUp: XmLGridTraverse(EXTEND_PAGE_UP)\n\ Ctrl ~Shift osfPageUp: XmLGridTraverse(PAGE_LEFT)\n\ Ctrl Shift osfPageUp: XmLGridTraverse(EXTEND_PAGE_LEFT)\n\ ~Ctrl Shift osfPageDown: XmLGridTraverse(EXTEND_PAGE_DOWN)\n\ Ctrl ~Shift osfPageDown: XmLGridTraverse(PAGE_RIGHT)\n\ ~Ctrl ~Shift osfPageDown: XmLGridTraverse(PAGE_DOWN)\n\ Ctrl Shift osfPageDown: XmLGridTraverse(EXTEND_PAGE_RIGHT)\n\ ~Ctrl ~Shift Tab: XmLGridTraverse(RIGHT)\n\ ~Ctrl Shift Tab: XmLGridTraverse(LEFT)\n\ ~Ctrl ~Shift Home: XmLGridTraverse(TO_TOP)\n\ ~Ctrl ~Shift osfBeginLine: XmLGridTraverse(TO_TOP)\n\ Ctrl ~Shift Home: XmLGridTraverse(TO_TOP_LEFT)\n\ ~Ctrl ~Shift End: XmLGridTraverse(TO_BOTTOM)\n\ ~Ctrl ~Shift osfEndLine: XmLGridTraverse(TO_BOTTOM)\n\ Ctrl ~Shift End: XmLGridTraverse(TO_BOTTOM_RIGHT)\n\ osfInsert: XmLGridEdit()\n\ F2: XmLGridEdit()\n\ ~Ctrl ~Shift space: XmLGridSelect(BEGIN)\n\ ~Ctrl Shift space: XmLGridSelect(EXTEND)\n\ Ctrl ~Shift space: XmLGridSelect(TOGGLE)\n\ space: XmLGridSelect(END)"; /* You can't put multiple actions for any translation where one translation changes the translation table XmLGridComplete() and XmLGridCancel() do this and these actions can't be combined with others */ static char editTranslations[] = "~Ctrl ~Shift osfDown: XmLGridEditComplete(DOWN)\n\ ~Ctrl Shift Tab: XmLGridEditComplete(LEFT)\n\ ~Ctrl ~Shift Tab: XmLGridEditComplete(RIGHT)\n\ ~Ctrl ~Shift osfUp: XmLGridEditComplete(UP)\n\ osfCancel: XmLGridEditCancel()\n\ Escape: XmLGridEditCancel()"; #if 0 static char hideButtonTranslations[] = ",: XmLGridHideColumn()"; static char unhideButtonTranslations[] = ",: XmLGridUnhideColumn()"; #endif /*0*/ static XtResource resources[] = { /* Grid Resources */ { XmNactivateCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.activateCallback), XmRImmediate, (XtPointer)0, }, { XmNaddCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.addCallback), XmRImmediate, (XtPointer)0, }, { XmNallowColumnHide, XmCAllowColumnHide, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowColHide), XmRImmediate, (XtPointer)False, }, { XmNallowColumnResize, XmCAllowColumnResize, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowColResize), XmRImmediate, (XtPointer)False, }, { XmNallowDragSelected, XmCAllowDragSelected, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowDrag), XmRImmediate, (XtPointer)False, }, { XmNallowDrop, XmCAllowDrop, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowDrop), XmRImmediate, (XtPointer)False, }, { XmNallowRowHide, XmCAllowRowHide, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowRowHide), XmRImmediate, (XtPointer)False, }, { XmNallowRowResize, XmCAllowRowResize, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.allowRowResize), XmRImmediate, (XtPointer)False, }, { XmNautoSelect, XmCAutoSelect, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.autoSelect), XmRImmediate, (XtPointer)True, }, { XmNblankBackground, XmCBlankBackground, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.blankBg), XmRCallProc, (XtPointer)GetCoreBackground, }, { XmNbottomFixedCount, XmCBottomFixedCount, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.bottomFixedCount), XmRImmediate, (XtPointer)0, }, { XmNbottomFixedMargin, XmCBottomFixedMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.bottomFixedMargin), XmRImmediate, (XtPointer)0, }, { XmNcellDefaults, XmCCellDefaults, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.cellDefaults), XmRImmediate, (XtPointer)False, }, { XmNcellDrawCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.cellDrawCallback), XmRImmediate, (XtPointer)0, }, { XmNcellDropCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.cellDropCallback), XmRImmediate, (XtPointer)0, }, { XmNcellFocusCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.cellFocusCallback), XmRImmediate, (XtPointer)0, }, { XmNcellPasteCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.cellPasteCallback), XmRImmediate, (XtPointer)0, }, { XmNcolumns, XmCColumns, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.colCount), XmRImmediate, (XtPointer)0, }, { XmNdeleteCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.deleteCallback), XmRImmediate, (XtPointer)0, }, { XmNdeselectCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.deselectCallback), XmRImmediate, (XtPointer)0, }, { XmNdebugLevel, XmCDebugLevel, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.debugLevel), XmRImmediate, (XtPointer)0, }, { XmNeditCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.editCallback), XmRImmediate, (XtPointer)0, }, { XmNeditTranslations, XmCTranslations, XmRTranslationTable, sizeof(XtTranslations), XtOffset(XmLGridWidget, grid.editTrans), XmRString, (XtPointer)editTranslations, }, { XmNfontList, XmCFontList, XmRFontList, sizeof(XmFontList), XtOffset(XmLGridWidget, grid.fontList), XmRImmediate, (XtPointer)0 }, { XmNfooterColumns, XmCFooterColumns, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.footerColCount), XmRImmediate, (XtPointer)0, }, { XmNfooterRows, XmCFooterRows, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.footerRowCount), XmRImmediate, (XtPointer)0, }, { XmNglobalPixmapHeight, XmCGlobalPixmapHeight, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.globalPixmapHeight), XmRImmediate, (XtPointer)0, }, { XmNglobalPixmapWidth, XmCGlobalPixmapWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.globalPixmapWidth), XmRImmediate, (XtPointer)0, }, { XmNheadingColumns, XmCHeadingColumns, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.headingColCount), XmRImmediate, (XtPointer)0, }, { XmNheadingRows, XmCHeadingRows, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.headingRowCount), XmRImmediate, (XtPointer)0, }, { XmNhiddenColumns, XmCHiddenColumns, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.hiddenColCount), XmRImmediate, (XtPointer)0, }, { XmNhiddenRows, XmCHiddenRows, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.hiddenRowCount), XmRImmediate, (XtPointer)0, }, { XmNhighlightRowMode, XmCHighlightRowMode, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.highlightRowMode), XmRImmediate, (XtPointer)False, }, { XmNhighlightThickness, XmCHighlightThickness, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.highlightThickness), XmRImmediate, (XtPointer)2, }, { XmNhorizontalScrollBar, XmCHorizontalScrollBar, XmRWidget, sizeof(Widget), XtOffset(XmLGridWidget, grid.hsb), XmRImmediate, (XtPointer)0, }, { XmNhorizontalSizePolicy, XmCHorizontalSizePolicy, XmRGridSizePolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.hsPolicy), XmRImmediate, (XtPointer)XmCONSTANT, }, { XmNhsbDisplayPolicy, XmCHsbDisplayPolicy, XmRScrollBarDisplayPolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.hsbDisplayPolicy), XmRImmediate, (XtPointer)XmAS_NEEDED, }, { XmNimmediateDraw, XmCImmediateDraw, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.immediateDraw), XmRImmediate, (XtPointer)False, }, { XmNlayoutFrozen, XmCLayoutFrozen, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.layoutFrozen), XmRImmediate, (XtPointer)False, }, { XmNleftFixedCount, XmCLeftFixedCount, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.leftFixedCount), XmRImmediate, (XtPointer)0, }, { XmNleftFixedMargin, XmCLeftFixedMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.leftFixedMargin), XmRImmediate, (XtPointer)0, }, { XmNminColumnWidth, XmCMinColumnWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.minColWidth), XmRImmediate, (XtPointer)0, }, { XmNrightFixedCount, XmCRightFixedCount, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.rightFixedCount), XmRImmediate, (XtPointer)0, }, { XmNrightFixedMargin, XmCRightFixedMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.rightFixedMargin), XmRImmediate, (XtPointer)0, }, { XmNresizeCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.resizeCallback), XmRImmediate, (XtPointer)0, }, { XmNrows, XmCRows, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.rowCount), XmRImmediate, (XtPointer)0, }, { XmNscrollBarMargin, XmCScrollBarMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.scrollBarMargin), XmRImmediate, (XtPointer)2, }, { XmNscrollCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.scrollCallback), XmRImmediate, (XtPointer)0, }, { XmNscrollColumn, XmCScrollColumn, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cScrollCol), XmRImmediate, (XtPointer)0, }, { XmNscrollRow, XmCScrollRow, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cScrollRow), XmRImmediate, (XtPointer)0, }, { XmNselectCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.selectCallback), XmRImmediate, (XtPointer)0, }, { XmNselectionPolicy, XmCGridSelectionPolicy, XmRGridSelectionPolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.selectionPolicy), XmRImmediate, (XtPointer)XmSELECT_BROWSE_ROW, }, { XmNselectBackground, XmCSelectBackground, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.selectBg), XmRCallProc, (XtPointer)GetManagerForeground, }, { XmNselectForeground, XmCSelectForeground, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.selectFg), XmRCallProc, (XtPointer)GetCoreBackground, }, { XmNshadowRegions, XmCShadowRegions, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.shadowRegions), XmRImmediate, (XtPointer)511, }, { XmNshadowType, XmCShadowType, XmRShadowType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.shadowType), XmRImmediate, (XtPointer)XmSHADOW_IN, }, { XmNsimpleHeadings, XmCSimpleHeadings, XmRString, sizeof(char *), XtOffset(XmLGridWidget, grid.simpleHeadings), XmRImmediate, (XtPointer)0, }, { XmNsimpleWidths, XmCSimpleWidths, XmRString, sizeof(char *), XtOffset(XmLGridWidget, grid.simpleWidths), XmRImmediate, (XtPointer)0, }, { XmNtextWidget, XmCTextWidget, XmRWidget, sizeof(Widget), XtOffset(XmLGridWidget, grid.text), XmRImmediate, (XtPointer)0, }, { XmNtoggleBottomColor, XmCToggleBottomColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.toggleBotColor), XmRCallProc, (XtPointer)GetManagerForeground, }, { XmNtoggleTopColor, XmCToggleTopColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.toggleTopColor), XmRCallProc, (XtPointer)GetManagerForeground, }, { XmNtoggleSize, XmCToggleSize, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.toggleSize), XmRImmediate, (XtPointer)16, }, { XmNtraverseTranslations, XmCTranslations, XmRTranslationTable, sizeof(XtTranslations), XtOffset(XmLGridWidget, grid.traverseTrans), XmRString, (XtPointer)traverseTranslations, }, { XmNtopFixedCount, XmCTopFixedCount, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.topFixedCount), XmRImmediate, (XtPointer)0, }, { XmNtopFixedMargin, XmCTopFixedMargin, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.topFixedMargin), XmRImmediate, (XtPointer)0, }, { XmNuseAverageFontWidth, XmCUseAverageFontWidth, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.useAvgWidth), XmRImmediate, (XtPointer)True, }, { XmNverticalScrollBar, XmCVerticalScrollBar, XmRWidget, sizeof(Widget), XtOffset(XmLGridWidget, grid.vsb), XmRImmediate, (XtPointer)0, }, { XmNverticalSizePolicy, XmCVerticalSizePolicy, XmRGridSizePolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.vsPolicy), XmRImmediate, (XtPointer)XmCONSTANT, }, { XmNvisibleColumns, XmCVisibleColumns, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.visibleCols), XmRImmediate, (XtPointer)0, }, { XmNvisibleRows, XmCVisibleRows, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.visibleRows), XmRImmediate, (XtPointer)0, }, { XmNvsbDisplayPolicy, XmCVsbDisplayPolicy, XmRScrollBarDisplayPolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.vsbDisplayPolicy), XmRImmediate, (XtPointer)XmAS_NEEDED, }, /* Xfe Additions*/ { XmNpopupCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid.popupCallback), XmRImmediate, (XtPointer)0, }, { XmNenterCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid . enterCellCallback), XmRImmediate, (XtPointer) NULL }, { XmNleaveCellCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid . leaveCellCallback), XmRImmediate, (XtPointer) NULL }, { XmNenterGridCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid . enterGridCallback), XmRImmediate, (XtPointer) NULL }, { XmNleaveGridCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList), XtOffset(XmLGridWidget, grid . leaveGridCallback), XmRImmediate, (XtPointer) NULL }, /* Row Resources */ { XmNrow, XmCGridRow, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellRow), XmRImmediate, (XtPointer)-1, }, { XmNrowUserData, XmCUserData, XmRPointer, sizeof(XtPointer), XtOffset(XmLGridWidget, grid.rowUserData), XmRImmediate, (XtPointer)0, }, { XmNrowHeight, XmCRowHeight, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.rowHeight), XmRImmediate, (XtPointer)0, }, { XmNrowRangeEnd, XmCRowRangeEnd, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellRowRangeEnd), XmRImmediate, (XtPointer)-1, }, { XmNrowRangeStart, XmCRowRangeStart, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellRowRangeStart), XmRImmediate, (XtPointer)-1, }, { XmNrowSizePolicy, XmCRowSizePolicy, XmRGridSizePolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.rowSizePolicy), XmRImmediate, (XtPointer)0, }, { XmNrowStep, XmCRowStep, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.rowStep), XmRImmediate, (XtPointer)1, }, { XmNrowType, XmCRowType, XmRRowType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.rowType), XmRImmediate, (XtPointer)XmINVALID_TYPE, }, /* Column Resources */ { XmNcolumn, XmCGridColumn, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellCol), XmRImmediate, (XtPointer)-1, }, { XmNcolumnUserData, XmCUserData, XmRPointer, sizeof(XtPointer), XtOffset(XmLGridWidget, grid.colUserData), XmRImmediate, (XtPointer)0, }, { XmNcolumnResizable, XmCColumnResizable, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.colResizable), XmRImmediate, (XtPointer)TRUE, }, { XmNcolumnWidth, XmCColumnWidth, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.colWidth), XmRImmediate, (XtPointer)0, }, { XmNcolumnRangeEnd, XmCColumnRangeEnd, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellColRangeEnd), XmRImmediate, (XtPointer)-1, }, { XmNcolumnRangeStart, XmCColumnRangeStart, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellColRangeStart), XmRImmediate, (XtPointer)-1, }, { XmNcolumnSizePolicy, XmCColumnSizePolicy, XmRGridSizePolicy, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.colSizePolicy), XmRImmediate, (XtPointer)0, }, { XmNcolumnStep, XmCColumnStep, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.colStep), XmRImmediate, (XtPointer)1, }, { XmNcolumnType, XmCColumnType, XmRColumnType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.colType), XmRImmediate, (XtPointer)XmINVALID_TYPE, }, /* xfe Column Resource additions */ { XmNcolumnHidden, XmCColumnHidden, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.colHidden), XmRImmediate, (XtPointer)FALSE, }, /* Cell Resources */ { XmNcellAlignment, XmCCellAlignment, XmRCellAlignment, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.alignment), XmRImmediate, (XtPointer)0, }, { XmNcellBackground, XmCCellBackground, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.background), XmRImmediate, (XtPointer)0, }, { XmNcellBottomBorderColor, XmCCellBottomBorderColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.bottomBorderColor), XmRImmediate, (XtPointer)0, }, { XmNcellBottomBorderType, XmCCellBottomBorderType, XmRCellBorderType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.bottomBorderType), XmRImmediate, (XtPointer)0, }, { XmNcellColumnSpan, XmCCellColumnSpan, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellValues.columnSpan), XmRImmediate, (XtPointer)0, }, { XmNcellEditable, XmCCellEditable, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.cellValues.editable), XmRImmediate, (XtPointer)False, }, { XmNcellFontList, XmCCellFontList, XmRFontList, sizeof(XmFontList), XtOffset(XmLGridWidget, grid.cellValues.fontList), XmRImmediate, (XtPointer)0, }, { XmNcellForeground, XmCCellForeground, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.foreground), XmRImmediate, (XtPointer)0, }, { XmNcellLeftBorderColor, XmCCellLeftBorderColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.leftBorderColor), XmRImmediate, (XtPointer)0, }, { XmNcellLeftBorderType, XmCCellLeftBorderType, XmRCellBorderType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.leftBorderType), XmRImmediate, (XtPointer)0, }, { XmNcellMarginBottom, XmCCellMarginBottom, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.cellValues.bottomMargin), XmRImmediate, (XtPointer)0, }, { XmNcellMarginLeft, XmCCellMarginLeft, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.cellValues.leftMargin), XmRImmediate, (XtPointer)0, }, { XmNcellMarginRight, XmCCellMarginRight, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.cellValues.rightMargin), XmRImmediate, (XtPointer)0, }, { XmNcellMarginTop, XmCCellMarginTop, XmRDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.cellValues.topMargin), XmRImmediate, (XtPointer)0, }, { XmNcellPixmap, XmCCellPixmap, XmRManForegroundPixmap, sizeof(Pixmap), XtOffset(XmLGridWidget, grid.cellPixmap), XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP, }, { XmNcellPixmapMask, XmCCellPixmapMask, XtRBitmap, sizeof(Pixmap), XtOffset(XmLGridWidget, grid.cellPixmapMask), XmRImmediate, (XtPointer)XmUNSPECIFIED_PIXMAP, }, { XmNcellRightBorderColor, XmCCellRightBorderColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.rightBorderColor), XmRImmediate, (XtPointer)0, }, { XmNcellRightBorderType, XmCCellRightBorderType, XmRCellBorderType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.rightBorderType), XmRImmediate, (XtPointer)0, }, { XmNcellRowSpan, XmCCellRowSpan, XmRInt, sizeof(int), XtOffset(XmLGridWidget, grid.cellValues.rowSpan), XmRImmediate, (XtPointer)0, }, { XmNcellString, XmCXmString, XmRXmString, sizeof(XmString), XtOffset(XmLGridWidget, grid.cellString), XmRImmediate, (XtPointer)0, }, { XmNcellToggleSet, XmCCellToggleSet, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.cellToggleSet), XmRImmediate, (XtPointer)False, }, { XmNcellTopBorderColor, XmCCellTopBorderColor, XmRPixel, sizeof(Pixel), XtOffset(XmLGridWidget, grid.cellValues.topBorderColor), XmRImmediate, (XtPointer)0, }, { XmNcellTopBorderType, XmCCellTopBorderType, XmRCellBorderType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.topBorderType), XmRImmediate, (XtPointer)0, }, { XmNcellType, XmCCellType, XmRCellType, sizeof(unsigned char), XtOffset(XmLGridWidget, grid.cellValues.type), XmRImmediate, (XtPointer)XmSTRING_CELL, }, { XmNcellUserData, XmCUserData, XmRPointer, sizeof(XtPointer), XtOffset(XmLGridWidget, grid.cellValues.userData), XmRImmediate, (XtPointer)0, }, /* Overridden inherited resources */ { XmNshadowThickness, XmCShadowThickness, XmRHorizontalDimension, sizeof(Dimension), XtOffset(XmLGridWidget, manager.shadow_thickness), XmRImmediate, (XtPointer)2, }, /* XFE Addition*/ { XmNhideUnhideButtons, XmCHideUnhideButtons, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.hideUnhideButtons), XmRImmediate, (XtPointer)False, }, { XmNsingleClickActivation, XmCSingleClickActivation, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.singleClickActivation), XmRImmediate, (XtPointer)False, }, #if 0 { XmNhideButtonTranslations, XmCTranslations, XmRTranslationTable, sizeof(XtTranslations), XtOffset(XmLGridWidget, grid.hideButtonTrans), XmRString, (XtPointer)hideButtonTranslations, }, { XmNunhideButtonTranslations, XmCTranslations, XmRTranslationTable, sizeof(XtTranslations), XtOffset(XmLGridWidget, grid.unhideButtonTrans), XmRString, (XtPointer)unhideButtonTranslations, }, #endif /*0*/ { XmNuseTextWidget, XmCUseTextWidget, XmRBoolean, sizeof(Boolean), XtOffset(XmLGridWidget, grid.useTextWidget), XmRImmediate, (XtPointer)True, }, { XmNiconSpacing, XmCIconSpacing, XmRHorizontalDimension, sizeof(Dimension), XtOffset(XmLGridWidget, grid.iconSpacing), XmRImmediate, (XtPointer) 4, }, }; XmLGridClassRec xmlGridClassRec = { { /* core_class */ (WidgetClass)&xmManagerClassRec, /* superclass */ "XmLGrid", /* class_name */ sizeof(XmLGridRec), /* widget_size */ ClassInitialize, /* class_init */ ClassPartInitialize, /* class_part_init */ FALSE, /* class_inited */ (XtInitProc)Initialize, /* initialize */ 0, /* initialize_hook */ (XtRealizeProc)Realize, /* realize */ (XtActionList)actions, /* actions */ (Cardinal)XtNumber(actions), /* num_actions */ (XtResource *)resources, /* resources */ XtNumber(resources), /* num_resources */ NULLQUARK, /* xrm_class */ TRUE, /* compress_motion */ XtExposeCompressMaximal, /* compress_exposure */ TRUE, /* compress_enterleav */ TRUE, /* visible_interest */ (XtWidgetProc)Destroy, /* destroy */ (XtWidgetProc)Resize, /* resize */ (XtExposeProc)Redisplay, /* expose */ (XtSetValuesFunc)SetValues, /* set_values */ 0, /* set_values_hook */ XtInheritSetValuesAlmost, /* set_values_almost */ (XtArgsProc)GetSubValues, /* get_values_hook */ 0, /* accept_focus */ XtVersion, /* version */ 0, /* callback_private */ translations, /* tm_table */ 0, /* query_geometry */ 0, /* display_accelerato */ 0, /* extension */ }, { /* composite_class */ (XtGeometryHandler)GeometryManager, /* geometry_manager */ (XtWidgetProc)ChangeManaged, /* change_managed */ XtInheritInsertChild, /* insert_child */ XtInheritDeleteChild, /* delete_child */ 0, /* extension */ }, { /* constraint_class */ 0, /* subresources */ 0, /* subresource_count */ sizeof(XmLGridConstraintRec), /* constraint_size */ 0, /* initialize */ 0, /* destroy */ 0, /* set_values */ 0, /* extension */ }, { /* manager_class */ XtInheritTranslations, /* translations */ 0, /* syn resources */ 0, /* num syn_resources */ 0, /* get_cont_resources */ 0, /* num_get_cont_res */ XmInheritParentProcess, /* parent_process */ 0, /* extension */ }, { /* grid_class */ 0, /* initial rows */ 0, /* initial columns */ XmInheritGridPreLayout, /* pre layout */ sizeof(struct _XmLGridRowRec), /* row rec size */ _GridRowNew, /* row new */ _GridRowFree, /* row free */ _GetRowValueMask, /* get row value mask */ _GetRowValue, /* get row value */ _SetRowValues, /* set row values */ sizeof(struct _XmLGridColumnRec), /* column rec size */ _GridColumnNew, /* column new */ _GridColumnFree, /* column free */ _GetColumnValueMask, /* get col value mask */ _GetColumnValue, /* get column value */ _SetColumnValues, /* set column values */ _SetCellValuesResize, /* set cell vl resize */ _GridCellAction, /* cell action */ } }; WidgetClass xmlGridWidgetClass = (WidgetClass)&xmlGridClassRec; /* Create and Destroy */ static void ClassInitialize(void) { int off1, off2; XmLInitialize(); XtSetTypeConverter(XmRString, XmRGridSizePolicy, CvtStringToSizePolicy, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRColumnType, CvtStringToRowColType, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRRowType, CvtStringToRowColType, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRGridSelectionPolicy, CvtStringToSelectionPolicy, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRCellAlignment, CvtStringToCellAlignment, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRCellType, CvtStringToCellType, 0, 0, XtCacheNone, 0); XtSetTypeConverter(XmRString, XmRCellBorderType, CvtStringToCellBorderType, 0, 0, XtCacheNone, 0); /* long must be > 2 bytes for cell mask to work */ if (sizeof(long) < 3) fprintf(stderr, "xmlGridClass: fatal error: long < 3 bytes\n"); /* compiler sanity check - make sure array pos lines up */ off1 = XtOffset(XmLArrayItem *, pos); off2 = XtOffset(XmLGridColumn, grid.pos); if (off1 != off2) fprintf(stderr, "xmlGridClass: fatal error: column pos offset bad\n"); off2 = XtOffset(XmLGridRow, grid.pos); if (off1 != off2) fprintf(stderr, "xmlGridClass: fatal error: row pos offset bad\n"); } static void ClassPartInitialize(WidgetClass wc) { XmLGridWidgetClass c, sc; c = (XmLGridWidgetClass)wc; sc = (XmLGridWidgetClass)c->core_class.superclass; #define INHERIT_PROC(proc, inherit) \ if (c->grid_class.proc == inherit) \ c->grid_class.proc = sc->grid_class.proc; INHERIT_PROC(rowNewProc, XmInheritGridRowNew) INHERIT_PROC(rowFreeProc, XmInheritGridRowFree) INHERIT_PROC(getRowValueMaskProc, XmInheritGridGetRowValueMask) INHERIT_PROC(getRowValueProc, XmInheritGridGetRowValue) INHERIT_PROC(setRowValuesProc, XmInheritGridSetRowValues) INHERIT_PROC(columnNewProc, XmInheritGridColumnNew) INHERIT_PROC(columnFreeProc, XmInheritGridColumnFree) INHERIT_PROC(getColumnValueMaskProc, XmInheritGridGetColumnValueMask) INHERIT_PROC(getColumnValueProc, XmInheritGridGetColumnValue) INHERIT_PROC(setColumnValuesProc, XmInheritGridSetColumnValues) INHERIT_PROC(setCellValuesResizeProc, XmInheritGridSetCellValuesResize) INHERIT_PROC(cellActionProc, XmInheritGridCellAction) #undef INHERIT_PROC } static void Initialize(Widget reqW, Widget newW, ArgList args, Cardinal *narg) { XmLGridWidget g, request; Display *dpy; Pixmap pix, pixMask; Pixel white, black; XColor fg, bg; GridReg *reg; int i, valid, hc, c, fc, hr, r, fr; Boolean layoutFrozen; #ifdef POINTER_FOCUS_CHECK unsigned char kfp; Widget shell; #endif g = (XmLGridWidget)newW; dpy = XtDisplay((Widget)g); request = (XmLGridWidget)reqW; #ifdef POINTER_FOCUS_CHECK shell = XmLShellOfWidget(newW); if (shell && XmIsVendorShell(shell)) { XtVaGetValues(shell, XmNkeyboardFocusPolicy, &kfp, NULL); if (kfp == XmPOINTER) XmLWarning(newW, "keyboardFocusPolicy of XmPOINTER not supported"); } #endif black = BlackPixelOfScreen(XtScreen((Widget)g)); white = WhitePixelOfScreen(XtScreen((Widget)g)); g->grid.rowArray = XmLArrayNew(1, 1); g->grid.colArray = XmLArrayNew(1, 1); if (g->core.width <= 0) g->core.width = 100; if (g->core.height <= 0) g->core.height = 100; CopyFontList(g); if (g->grid.useTextWidget) { g->grid.text = XtVaCreateManagedWidget("text", xmTextWidgetClass, (Widget)g, XmNmarginHeight, 0, XmNmarginWidth, 3, XmNshadowThickness, 0, XmNhighlightThickness, 0, XmNx, 0, XmNy, 0, XmNwidth, 40, XmNheight, 40, XmNbackground, g->core.background_pixel, XmNforeground, g->manager.foreground, NULL); XtOverrideTranslations(g->grid.text, g->grid.traverseTrans); XtAddEventHandler(g->grid.text, StructureNotifyMask, True, (XtEventHandler)TextMapped, (XtPointer)0); XtAddCallback(g->grid.text, XmNactivateCallback, TextActivate, 0); XtAddCallback(g->grid.text, XmNfocusCallback, TextFocus, 0); XtAddCallback(g->grid.text, XmNlosingFocusCallback, TextFocus, 0); XtAddCallback(g->grid.text, XmNmodifyVerifyCallback, TextModifyVerify, 0); } g->grid.hsb = XtVaCreateWidget( "hsb", xmScrollBarWidgetClass, (Widget)g, XmNincrement, 1, XmNorientation, XmHORIZONTAL, XmNtraversalOn, False, XmNbackground, g->core.background_pixel, /* Don't force foreground on IRIX - it screws up the thumb color in sgiMode */ #ifndef IRIX XmNforeground, g->manager.foreground, #endif XmNtopShadowColor, g->manager.top_shadow_color, XmNbottomShadowColor, g->manager.bottom_shadow_color, NULL); XtAddCallback(g->grid.hsb, XmNdragCallback, ScrollCB, 0); XtAddCallback(g->grid.hsb, XmNvalueChangedCallback, ScrollCB, 0); g->grid.vsb = XtVaCreateWidget( "vsb", xmScrollBarWidgetClass, (Widget)g, XmNorientation, XmVERTICAL, XmNincrement, 1, XmNtraversalOn, False, XmNbackground, g->core.background_pixel, /* Don't force foreground on IRIX - it screws up the thumb color in sgiMode */ #ifndef IRIX XmNforeground, g->manager.foreground, #endif XmNtopShadowColor, g->manager.top_shadow_color, XmNbottomShadowColor, g->manager.bottom_shadow_color, NULL); XtAddCallback(g->grid.vsb, XmNdragCallback, ScrollCB, 0); XtAddCallback(g->grid.vsb, XmNvalueChangedCallback, ScrollCB, 0); if (g->grid.hideUnhideButtons) { CreateHideUnhideButtons(g); } else { g->grid.hideButton = 0; g->grid.unhideButton = 0; } g->grid.inResize = False; /* Cursors */ fg.red = ~0; fg.green = ~0; fg.blue = ~0; fg.pixel = white; fg.flags = DoRed | DoGreen | DoBlue; bg.red = 0; bg.green = 0; bg.blue = 0; bg.pixel = black; bg.flags = DoRed | DoGreen | DoBlue; pix = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy), (char *)horizp_bits, horizp_width, horizp_height, 0, 1, 1); pixMask = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy), (char *)horizm_bits, horizm_width, horizm_height, 1, 0, 1); g->grid.hResizeCursor = XCreatePixmapCursor(dpy, pix, pixMask, &fg, &bg, 9, 9); XFreePixmap(dpy, pix); XFreePixmap(dpy, pixMask); pix = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy), (char *)vertp_bits, vertp_width, vertp_height, 0, 1, 1); pixMask = XCreatePixmapFromBitmapData(dpy, DefaultRootWindow(dpy), (char *)vertm_bits, vertm_width, vertm_height, 1, 0, 1); g->grid.vResizeCursor = XCreatePixmapCursor(dpy, pix, pixMask, &fg, &bg, 9, 9); XFreePixmap(dpy, pix); XFreePixmap(dpy, pixMask); g->grid.cursorDefined = CursorNormal; g->grid.focusIn = 0; g->grid.focusRow = -1; g->grid.focusCol = -1; g->grid.mayHaveRowSpans = 0; g->grid.scrollCol = 0; g->grid.scrollRow = 0; g->grid.textHidden = 1; g->grid.inMode = InNormal; g->grid.inEdit = 0; g->grid.singleColScrollMode = 0; g->grid.layoutStack = 0; g->grid.needsHorizLayout = 0; g->grid.needsVertLayout = 0; g->grid.recalcHorizVisPos = 0; g->grid.recalcVertVisPos = 0; g->grid.vertVisChangedHint = 0; g->grid.defCellValues = CellRefValuesCreate(g, 0); g->grid.defCellValues->refCount = 1; g->grid.ignoreModifyVerify = 0; g->grid.extendRow = -1; g->grid.extendCol = -1; g->grid.extendToRow = -1; g->grid.extendToCol = -1; g->grid.extendSelect = True; g->grid.lastSelectRow = -1; g->grid.lastSelectCol = -1; g->grid.lastSelectTime = 0; g->grid.dragTimerSet = 0; g->grid.editTimerSet = 0; g->grid.gc = 0; /* * Support for: * * XmNenterCellCallback * XmNenterCellCallback * XmNenterCallback * XmNleaveCallback */ g->grid.lastCursorMotionRow = -1; g->grid.lastCursorMotionCol = -1; XtAddEventHandler(newW, EnterWindowMask | LeaveWindowMask, True, (XtEventHandler) GridCrossingEH, (XtPointer) NULL); reg = g->grid.reg; for (i = 0; i < 9; i++) { reg[i].x = 0; reg[i].y = 0; reg[i].width = 0; reg[i].height = 0; reg[i].row = 0; reg[i].col = 0; reg[i].nrow = 0; reg[i].ncol = 0; } layoutFrozen = g->grid.layoutFrozen; g->grid.layoutFrozen = True; if (g->grid.hiddenColCount || g->grid.hiddenRowCount) { XmLWarning(newW, "Initialize() - can't set hidden rows or columns"); g->grid.hiddenColCount = 0; g->grid.hiddenRowCount = 0; } hc = g->grid.headingColCount; c = XmLGridClassPartOfWidget(g).initialCols; if (c < g->grid.colCount) c = g->grid.colCount; fc = g->grid.footerColCount; hr = g->grid.headingRowCount; r = XmLGridClassPartOfWidget(g).initialRows; if (r < g->grid.rowCount) r = g->grid.rowCount ; fr = g->grid.footerRowCount; g->grid.headingColCount = 0; g->grid.colCount = 0; g->grid.footerColCount = 0; g->grid.headingRowCount = 0; g->grid.rowCount = 0; g->grid.footerRowCount = 0; XmLGridAddColumns(newW, XmHEADING, -1, hc); XmLGridAddColumns(newW, XmCONTENT, -1, c); XmLGridAddColumns(newW, XmFOOTER, -1, fc); XmLGridAddRows(newW, XmHEADING, -1, hr); XmLGridAddRows(newW, XmCONTENT, -1, r); XmLGridAddRows(newW, XmFOOTER, -1, fr); if (g->grid.simpleHeadings) { g->grid.simpleHeadings = (char *)strdup(g->grid.simpleHeadings); SetSimpleHeadings(g, g->grid.simpleHeadings); } if (g->grid.simpleWidths) { g->grid.simpleWidths = (char *)strdup(g->grid.simpleWidths); SetSimpleWidths(g, g->grid.simpleWidths); } if (g->grid.visibleRows) ApplyVisibleRows(g); if (g->grid.visibleCols && g->grid.hsPolicy == XmCONSTANT) ApplyVisibleCols(g); g->grid.layoutFrozen = layoutFrozen; VertLayout(g, 1); HorizLayout(g, 1); PlaceScrollbars(g); valid = 1; for (i = 0; i < *narg; i++) { if (!args[i].name) continue; if (!strcmp(args[i].name, XmNrows) || !strcmp(args[i].name, XmNcolumns)) continue; if (!strncmp(args[i].name, "row", 3) || !strncmp(args[i].name, "column", 6) || !strncmp(args[i].name, "cell", 4)) valid = 0; } if (!valid) XmLWarning(newW, "Initialize() - can't set row,column or cell values in init"); DropRegister(g, g->grid.allowDrop); } static void Destroy(Widget w) { XmLGridWidget g; Display *dpy; int i, count; g = (XmLGridWidget)w; dpy = XtDisplay(w); if (g->grid.dragTimerSet) XtRemoveTimeOut(g->grid.dragTimerId); if (g->grid.editTimerSet) XtRemoveTimeOut(g->grid.editTimerId); DefineCursor(g, CursorNormal); XFreeCursor(dpy, g->grid.hResizeCursor); XFreeCursor(dpy, g->grid.vResizeCursor); if (g->grid.gc) { XFreeGC(dpy, g->grid.gc); XFreeFont(dpy, g->grid.fallbackFont); } XmFontListFree(g->grid.fontList); XmLGridCellDerefValues(g->grid.defCellValues); ExtendSelect(g, (XEvent *)0, False, -1, -1); count = XmLArrayGetCount(g->grid.rowArray); for (i = 0; i < count; i++) XmLGridRowFree(w, (XmLGridRow)XmLArrayGet(g->grid.rowArray, i)); XmLArrayFree(g->grid.rowArray); count = XmLArrayGetCount(g->grid.colArray); for (i = 0; i < count; i++) XmLGridColumnFree(w, (XmLGridColumn)XmLArrayGet(g->grid.colArray, i)); XmLArrayFree(g->grid.colArray); if (g->grid.simpleHeadings) free((char *)g->grid.simpleHeadings); if (g->grid.simpleWidths) free((char *)g->grid.simpleWidths); } /* Geometry, Drawing, Entry and Picking */ static void Realize(Widget w, XtValueMask *valueMask, XSetWindowAttributes *attr) { XmLGridWidget g; Display *dpy; WidgetClass superClass; XtRealizeProc realize; XGCValues values; XtGCMask mask; static char dashes[2] = { 1, 1 }; g = (XmLGridWidget)w; dpy = XtDisplay(g); superClass = xmlGridWidgetClass->core_class.superclass; realize = superClass->core_class.realize; (*realize)(w, valueMask, attr); if (!g->grid.gc) { g->grid.fallbackFont = XLoadQueryFont(dpy, "fixed"); values.foreground = g->manager.foreground; values.font = g->grid.fallbackFont->fid; mask = GCForeground | GCFont; g->grid.gc = XCreateGC(dpy, XtWindow(g), mask, &values); XSetDashes(dpy, g->grid.gc, 0, dashes, 2); if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW && g->grid.autoSelect == True && g->grid.rowCount) XmLGridSelectRow(w, 0, False); } } static void Redisplay(Widget w, XExposeEvent *event, Region region) { XmLGridWidget g; Display *dpy; Window win; XmLGridCell cell; XmLGridRow row; XmLGridColumn col; XmLGridCellRefValues *cellValues; XmLGridDrawStruct ds; XmLGridCallbackStruct cbs; GridReg *reg; XRectangle eRect, rRect, clipRect, rect[6]; int i, n, st, c, r, sc, sr, width, height, rowHeight; int lastVisPos, visPos, hasDrawCB; Boolean spanUp, spanLeft; g = (XmLGridWidget)w; if (!XtIsRealized((Widget)g)) return; if (!g->core.visible) return; if (g->grid.layoutFrozen == True) XmLWarning(w, "Redisplay() - layout frozen is True during redraw"); dpy = XtDisplay(g); win = XtWindow(g); st = g->manager.shadow_thickness; reg = g->grid.reg; if (event) { eRect.x = event->x; eRect.y = event->y; eRect.width = event->width; eRect.height = event->height; if (g->grid.debugLevel > 1) fprintf(stderr, "XmLGrid: Redisplay x %d y %d w %d h %d\n", event->x, event->y, event->width, event->height); } else { eRect.x = 0; eRect.y = 0; eRect.width = g->core.width; eRect.height = g->core.height; } if (!eRect.width || !eRect.height) return; /* Hide any XORed graphics */ DrawResizeLine(g, 0, 1); hasDrawCB = 0; if (XtHasCallbacks(w, XmNcellDrawCallback) == XtCallbackHasSome) hasDrawCB = 1; /* Add extra shadow around the whole widget * if 512 is set for shadow regions */ if (g->grid.shadowRegions == 512 && g->manager.shadow_thickness && XmLRectIntersect(&eRect, &rRect) != XmLRectInside) { #ifdef MOTIF11 _XmDrawShadow(dpy, win, g->manager.bottom_shadow_GC, g->manager.top_shadow_GC, g->manager.shadow_thickness, 0,0, g->core.width, g->core.height); #else _XmDrawShadows(dpy, win, g->manager.top_shadow_GC, g->manager.bottom_shadow_GC, 0,0, g->core.width, g->core.height, g->manager.shadow_thickness, g->grid.shadowType); #endif } /* end of extra shadow */ for (i = 0; i < 9; i++) { if (!reg[i].width || !reg[i].height) continue; rRect.x = reg[i].x; rRect.y = reg[i].y; rRect.width = reg[i].width; rRect.height = reg[i].height; if (XmLRectIntersect(&eRect, &rRect) == XmLRectOutside) continue; if (g->grid.debugLevel > 2) fprintf(stderr, "XmLGrid: Redisplay region %d shadows\n", i); rRect.x += st; rRect.width -= st * 2; rRect.y += st; rRect.height -= st * 2; if (XmLRectIntersect(&eRect, &rRect) != XmLRectInside && g->manager.shadow_thickness && g->grid.shadowRegions != 512) { if (g->grid.shadowRegions & (1 << i)) #ifdef MOTIF11 _XmDrawShadow(dpy, win, g->manager.bottom_shadow_GC, g->manager.top_shadow_GC, g->manager.shadow_thickness, reg[i].x, reg[i].y, reg[i].width, reg[i].height); #else _XmDrawShadows(dpy, win, g->manager.top_shadow_GC, g->manager.bottom_shadow_GC, reg[i].x, reg[i].y, reg[i].width, reg[i].height, g->manager.shadow_thickness, g->grid.shadowType); #endif else #ifdef MOTIF11 _XmEraseShadow(dpy, win, g->manager.shadow_thickness, reg[i].x, reg[i].y, reg[i].width, reg[i].height); #else _XmClearBorder(dpy, win, reg[i].x, reg[i].y, reg[i].width, reg[i].height, g->manager.shadow_thickness); #endif } rRect.x += st; height = 0; if (g->grid.debugLevel > 2) fprintf(stderr, "XmLGrid: Redisplay region %d content\n", i); for (r = reg[i].row; r < reg[i].row + reg[i].nrow; r++) { rowHeight = GetRowHeight(g, r); if (!rowHeight && !g->grid.mayHaveRowSpans) continue; width = 0; for (c = reg[i].col; c < reg[i].col + reg[i].ncol; c++) { rRect.x = reg[i].x + st + width; rRect.y = reg[i].y + st + height; if (g->grid.singleColScrollMode) rRect.x -= g->grid.singleColScrollPos; rRect.width = GetColWidth(g, c); #if 0 if (i == 1 && r == reg[1].row && c == reg[1].col - 1) { rRect.width -= 10; } #endif /*0 slamm */ rRect.height = rowHeight; width += rRect.width; cell = GetCell(g, r, c); if (!cell) continue; cellValues = XmLGridCellGetRefValues(cell); spanUp = False; spanLeft = False; if (XmLGridCellInRowSpan(cell)) { if (r == reg[i].row) { spanUp = True; if (c == reg[i].col) spanLeft = True; } else continue; } if (XmLGridCellInColumnSpan(cell)) { if (c == reg[i].col) spanLeft = True; else continue; } sr = r; sc = c; if (spanUp == True || spanLeft == True || cellValues->rowSpan || cellValues->columnSpan) { if (RowColFirstSpan(g, r, c, &sr, &sc, &rRect, spanLeft, spanUp) == -1) continue; RowColSpanRect(g, sr, sc, &rRect); } if (!rRect.width || !rRect.height) continue; clipRect = rRect; ClipRectToReg(g, &clipRect, ®[i]); if (!clipRect.width || !clipRect.height) continue; if (event && XRectInRegion(region, clipRect.x, clipRect.y, clipRect.width, clipRect.height) == RectangleOut) continue; cell = GetCell(g, sr, sc); if (!cell) continue; cellValues = XmLGridCellGetRefValues(cell); cbs.reason = XmCR_CELL_DRAW; cbs.event = (XEvent *)event; cbs.rowType = RowPosToType(g, sr); cbs.row = RowPosToTypePos(g, cbs.rowType, sr); cbs.columnType = ColPosToType(g, sc); cbs.column = ColPosToTypePos(g, cbs.columnType, sc); cbs.clipRect = &clipRect; cbs.drawInfo = &ds; ds.gc = g->grid.gc; ds.cellRect = &rRect; ds.topMargin = cellValues->topMargin; ds.bottomMargin = cellValues->bottomMargin; ds.leftMargin = cellValues->leftMargin; ds.rightMargin = cellValues->rightMargin; ds.background = cellValues->background; ds.foreground = cellValues->foreground; ds.fontList = cellValues->fontList; ds.alignment = cellValues->alignment; ds.selectBackground = g->grid.selectBg; ds.selectForeground = g->grid.selectFg; row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, sr); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, sc); ds.drawFocusType = XmDRAW_FOCUS_NONE; if (g->grid.focusRow == sr && g->grid.highlightRowMode == True && g->grid.focusIn) { RecalcVisPos(g, 0); visPos = XmLGridColumnGetVisPos(col); lastVisPos = XmLArrayGetCount(g->grid.colArray) - g->grid.hiddenColCount - 1; if (visPos == 0 && visPos == lastVisPos) ds.drawFocusType = XmDRAW_FOCUS_CELL; else if (visPos == 0) ds.drawFocusType = XmDRAW_FOCUS_LEFT; else if (visPos == lastVisPos) ds.drawFocusType = XmDRAW_FOCUS_RIGHT; else ds.drawFocusType = XmDRAW_FOCUS_MID; } if (g->grid.focusRow == sr && g->grid.focusCol == sc && g->grid.highlightRowMode == False && g->grid.focusIn) ds.drawFocusType = XmDRAW_FOCUS_CELL; if (XmLGridRowIsSelected(row) == True || XmLGridColumnIsSelected(col) == True || XmLGridCellIsSelected(cell) == True) ds.drawSelected = True; else ds.drawSelected = False; if (g->grid.selectionPolicy == XmSELECT_CELL && g->grid.focusIn && g->grid.focusRow == sr && g->grid.focusCol == sc) ds.drawSelected = False; ds.stringDirection = g->manager.string_direction; XmLGridCellAction(cell, (Widget)g, &cbs); if (hasDrawCB) XtCallCallbackList(w, g->grid.cellDrawCallback, (XtPointer)&cbs); } height += rowHeight; } } if (g->grid.debugLevel > 1) fprintf(stderr, "XmLGrid: Redisplay non-cell areas\n"); n = 0; if (reg[0].width && g->grid.leftFixedMargin) { rect[n].x = reg[0].width; rect[n].y = 0; rect[n].width = g->grid.leftFixedMargin; rect[n].height = g->core.height; n++; } if (reg[2].width && g->grid.rightFixedMargin) { width = 0; if (reg[0].ncol) width += reg[0].width + g->grid.leftFixedMargin; if (reg[1].ncol) width += reg[1].width; rect[n].x = width; rect[n].y = 0; rect[n].width = g->grid.rightFixedMargin; rect[n].height = g->core.height; n++; } if (reg[0].height && g->grid.topFixedMargin) { rect[n].x = 0; rect[n].y = reg[0].height; rect[n].width = g->core.width; rect[n].height = g->grid.topFixedMargin; n++; } if (reg[6].height && g->grid.bottomFixedMargin) { rect[n].x = 0; height = 0; if (reg[0].nrow) height += reg[0].height + g->grid.topFixedMargin; if (reg[3].nrow) height += reg[3].height; rect[n].y = height; rect[n].width = g->core.width; rect[n].height = g->grid.bottomFixedMargin; n++; } width = reg[1].width; if (reg[0].ncol) width += reg[0].width + g->grid.leftFixedMargin; if (reg[2].ncol) width += g->grid.rightFixedMargin + reg[2].width; if (width < (int)g->core.width) { rect[n].x = width; rect[n].y = 0; rect[n].width = g->core.width - width; rect[n].height = g->core.height; n++; } height = reg[3].height; if (reg[0].nrow) height += reg[0].height + g->grid.topFixedMargin; if (reg[6].nrow) height += g->grid.bottomFixedMargin + reg[6].height; if (height < (int)g->core.height) { rect[n].x = 0; rect[n].y = height; rect[n].width = g->core.width; rect[n].height = g->core.height - height; n++; } for (i = 0; i < n; i++) { if (XmLRectIntersect(&eRect, &rect[i]) == XmLRectOutside) continue; XClearArea(dpy, win, rect[i].x, rect[i].y, rect[i].width, rect[i].height, False); } n = 0; if (reg[1].width) { width = 0; for (c = reg[1].col; c < reg[1].col + reg[1].ncol; c++) width += GetColWidth(g, c); for (i = 1; i < 9; i += 3) if (reg[i].height && width < reg[i].width - st * 2) { rect[n].x = reg[i].x + st + width; rect[n].y = reg[i].y + st; rect[n].width = reg[i].x + reg[i].width - rect[n].x - st; rect[n].height = reg[i].height - st * 2; n++; } } if (reg[3].height) { height = 0; for (r = reg[3].row; r < reg[3].row + reg[3].nrow; r++) height += GetRowHeight(g, r); for (i = 3; i < 6; i++) if (reg[i].width && height < reg[i].height - st * 2) { rect[n].x = reg[i].x + st; rect[n].y = reg[i].y + st + height; rect[n].width = reg[i].width - st * 2; rect[n].height = reg[i].y + reg[i].height - rect[n].y - st; n++; } } XSetForeground(dpy, g->grid.gc, g->grid.blankBg); for (i = 0; i < n; i++) { if (XmLRectIntersect(&eRect, &rect[i]) == XmLRectOutside) continue; XFillRectangle(dpy, win, g->grid.gc, rect[i].x, rect[i].y, rect[i].width, rect[i].height); } /* Show any XORed graphics */ DrawResizeLine(g, 0, 1); } static void DrawResizeLine(XmLGridWidget g, int xy, int erase) { if (g->grid.inMode != InResize) return; DrawXORRect(g, xy, 2, g->grid.resizeIsVert, erase); } static void DrawXORRect(XmLGridWidget g, int xy, int size, int isVert, int erase) { Display *dpy; Window win; GC gc; Pixel black, white; int oldXY, maxX, maxY; if (!XtIsRealized((Widget)g)) return; /* erase is (0 == none) (1 == hide/show) (2 == permenent erase) */ dpy = XtDisplay(g); win = XtWindow(g); gc = g->grid.gc; XSetFunction(dpy, gc, GXinvert); black = BlackPixelOfScreen(XtScreen((Widget)g)); white = WhitePixelOfScreen(XtScreen((Widget)g)); XSetForeground(dpy, gc, black ^ white); maxX = g->core.width; if (XtIsManaged(g->grid.vsb)) maxX -= g->grid.vsb->core.width + g->grid.scrollBarMargin; maxY = g->core.height; if (XtIsManaged(g->grid.hsb)) maxY -= g->grid.hsb->core.height + g->grid.scrollBarMargin; oldXY = g->grid.resizeLineXY; if (isVert) { if (oldXY != -1) XFillRectangle(dpy, win, gc, 0, oldXY, maxX, size); } else { if (oldXY != -1) XFillRectangle(dpy, win, gc, oldXY, 0, size, maxY); } if (!erase) { if (isVert) { if (xy > maxY) xy = maxY - 2; if (xy < 0) xy = 0; XFillRectangle(dpy, win, gc, 0, xy, maxX, size); } else { if (xy > maxX) xy = maxX - 2; if (xy < 0) xy = 0; XFillRectangle(dpy, win, gc, xy, 0, size, maxY); } g->grid.resizeLineXY = xy; } else if (erase == 2) g->grid.resizeLineXY = -1; XSetFunction(dpy, gc, GXcopy); } static void DefineCursor(XmLGridWidget g, char defineCursor) { Display *dpy; Window win; if (!XtIsRealized((Widget)g)) return; dpy = XtDisplay(g); win = XtWindow(g); if (defineCursor != g->grid.cursorDefined) XUndefineCursor(dpy, win); if (defineCursor == CursorVResize) XDefineCursor(dpy, win, g->grid.vResizeCursor); else if (defineCursor == CursorHResize) XDefineCursor(dpy, win, g->grid.hResizeCursor); g->grid.cursorDefined = defineCursor; } static void DrawArea(XmLGridWidget g, int type, int row, int col) { GridReg *reg; Display *dpy; Window win; XExposeEvent event; XRectangle rect[3]; Region region; int i, j, n; Dimension width, height, st; if (g->grid.layoutFrozen == True) return; if (!XtIsRealized((Widget)g)) return; if (!g->core.visible) return; dpy = XtDisplay(g); win = XtWindow(g); reg = g->grid.reg; st = g->manager.shadow_thickness; if (g->grid.debugLevel > 1) fprintf(stderr, "XmLGrid: DrawArea %d %d %d\n", type, row, col); n = 0; switch (type) { case DrawAll: { rect[n].x = 0; rect[n].y = 0; rect[n].width = g->core.width; rect[n].height = g->core.height; n++; break; } case DrawHScroll: { for (i = 1; i < 9; i += 3) { if (!reg[i].width || !reg[i].height) continue; rect[n].x = reg[i].x + st; rect[n].y = reg[i].y + st; rect[n].width = reg[i].width - st * 2; rect[n].height = reg[i].height - st * 2; n++; } break; } case DrawVScroll: { for (i = 3; i < 6; i++) { if (!reg[i].width || !reg[i].height) continue; rect[n].x = reg[i].x + st; rect[n].y = reg[i].y + st; rect[n].width = reg[i].width - st * 2; rect[n].height = reg[i].height - st * 2; n++; } break; } case DrawRow: { for (i = 0; i < 9; i++) { if (!reg[i].width || !reg[i].height) continue; if (!(row >= reg[i].row && row < reg[i].row + reg[i].nrow)) continue; height = 0; for (j = reg[i].row; j < row; j++) height += GetRowHeight(g, j); rect[n].x = reg[i].x + st; rect[n].y = reg[i].y + st + height; rect[n].width = reg[i].width - st * 2; rect[n].height = GetRowHeight(g, row); ClipRectToReg(g, &rect[n], ®[i]); n++; } break; } case DrawCol: { for (i = 0; i < 9; i++) { if (!reg[i].width || !reg[i].height) continue; if (!(col >= reg[i].col && col < reg[i].col + reg[i].ncol)) continue; width = 0; for (j = reg[i].col; j < col; j++) width += GetColWidth(g, j); rect[n].x = reg[i].x + st + width; rect[n].y = reg[i].y + st; rect[n].width = GetColWidth(g, col); rect[n].height = reg[i].height - st * 2; ClipRectToReg(g, &rect[n], ®[i]); n++; } break; } case DrawCell: { if (!RowColToXY(g, row, col, True, &rect[n])) n++; break; } } for (i = 0; i < n; i++) { if (!rect[i].width || !rect[i].height) continue; event.type = Expose; event.window = win; event.display = dpy; event.x = rect[i].x; event.y = rect[i].y; event.width = rect[i].width; event.height = rect[i].height; event.send_event = True; event.count = 0; if (g->grid.immediateDraw) { region = XCreateRegion(); XUnionRectWithRegion(&rect[i], region, region); Redisplay((Widget)g, &event, region); XDestroyRegion(region); } else XSendEvent(dpy, win, False, ExposureMask, (XEvent *)&event); if (g->grid.debugLevel > 1) fprintf(stderr, "XmLGrid: DrawArea expose x %d y %d w %d h %d\n", event.x, event.y, event.width, event.height); } } static void ExtendSelectRange(XmLGridWidget g, int *type, int *fr, int *lr, int *fc, int *lc) { int r, c; if ((g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW) || (ColPosToType(g, g->grid.extendCol) != XmCONTENT)) *type = SelectRow; else if (RowPosToType(g, g->grid.extendRow) != XmCONTENT) *type = SelectCol; else *type = SelectCell; r = g->grid.extendToRow; if (r < g->grid.headingRowCount) r = g->grid.headingRowCount; if (r >= g->grid.headingRowCount + g->grid.rowCount) r = g->grid.headingRowCount + g->grid.rowCount - 1; if (*type == SelectCol) { *fr = 0; *lr = 1; } else if (g->grid.extendRow < r) { *fr = g->grid.extendRow; *lr = r; } else { *fr = r; *lr = g->grid.extendRow; } c = g->grid.extendToCol; if (c < g->grid.headingColCount) c = g->grid.headingColCount; if (c >= g->grid.headingColCount + g->grid.colCount) c = g->grid.headingColCount + g->grid.colCount - 1; if (*type == SelectRow) { *fc = 0; *lc = 1; } else if (g->grid.extendCol < c) { *fc = g->grid.extendCol; *lc = c; } else { *fc = c; *lc = g->grid.extendCol; } } static void ExtendSelect(XmLGridWidget g, XEvent *event, Boolean set, int row, int col) { int type; int r, fr, lr; int c, fc, lc; if (row == -1 || col == -1) { g->grid.extendRow = -1; g->grid.extendCol = -1; g->grid.extendToRow = -1; g->grid.extendToCol = -1; g->grid.extendSelect = True; return; } if (RowPosToType(g, row) == XmFOOTER || ColPosToType(g, col) == XmFOOTER) return; if ((g->grid.extendToRow == row && g->grid.extendToCol == col) || (g->grid.extendRow == -1 && row == g->grid.focusRow && g->grid.extendCol == -1 && col == g->grid.focusCol)) return; if (g->grid.extendRow != -1 && g->grid.extendCol != -1) { /* clear previous extend */ ExtendSelectRange(g, &type, &fr, &lr, &fc, &lc); for (r = fr; r <= lr; r += 1) for (c = fc; c <= lc; c += 1) SelectTypeArea(g, type, event, RowPosToTypePos(g, XmCONTENT, r), ColPosToTypePos(g, XmCONTENT, c), False, True); } else { g->grid.extendRow = g->grid.focusRow; g->grid.extendCol = g->grid.focusCol; } if (set == True) { g->grid.extendRow = row; g->grid.extendCol = col; } if (g->grid.extendRow < 0 || g->grid.extendCol < 0) return; g->grid.extendToRow = row; g->grid.extendToCol = col; /* set new extend */ ExtendSelectRange(g, &type, &fr, &lr, &fc, &lc); for (r = fr; r <= lr; r += 1) for (c = fc; c <= lc; c += 1) SelectTypeArea(g, type, event, RowPosToTypePos(g, XmCONTENT, r), ColPosToTypePos(g, XmCONTENT, c), g->grid.extendSelect, True); } static void SelectTypeArea(XmLGridWidget g, int type, XEvent *event, int row, int col, Boolean select, Boolean notify) { Widget w; XmLGridRow rowp; XmLGridColumn colp; XmLGridCell cellp; int r, fr, lr, hrc; int c, fc, lc, hcc; int badPos, hasCB; XmLGridCallbackStruct cbs; w = (Widget)g; hrc = g->grid.headingRowCount; hcc = g->grid.headingColCount; cbs.event = event; cbs.rowType = XmCONTENT; cbs.columnType = XmCONTENT; hasCB = 0; if (select == True) { if (type == SelectRow) cbs.reason = XmCR_SELECT_ROW; else if (type == SelectCol) cbs.reason = XmCR_SELECT_COLUMN; else if (type == SelectCell) cbs.reason = XmCR_SELECT_CELL; if (XtHasCallbacks(w, XmNselectCallback) == XtCallbackHasSome) hasCB = 1; } else { if (type == SelectRow) cbs.reason = XmCR_DESELECT_ROW; else if (type == SelectCol) cbs.reason = XmCR_DESELECT_COLUMN; else if (type == SelectCell) cbs.reason = XmCR_DESELECT_CELL; if (XtHasCallbacks(w, XmNdeselectCallback) == XtCallbackHasSome) hasCB = 1; } if (row != -1) { fr = hrc + row; lr = fr + 1; } else { fr = hrc; lr = XmLArrayGetCount(g->grid.rowArray) - g->grid.footerRowCount; } if (col != -1) { fc = hcc + col; lc = fc + 1; } else { fc = hcc; lc = XmLArrayGetCount(g->grid.colArray) - g->grid.footerColCount; } badPos = 0; for (r = fr; r < lr; r++) for (c = fc; c < lc; c++) { if (type == SelectRow) { rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (!rowp) { badPos = 1; continue; } if (XmLGridRowIsSelected(rowp) == select) continue; if (select == True && (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW || g->grid.selectionPolicy == XmSELECT_SINGLE_ROW)) SelectTypeArea(g, SelectRow, event, -1, 0, False, notify); XmLGridRowSetSelected(rowp, select); if (RowIsVisible(g, r)) DrawArea(g, DrawRow, r, 0); if (notify && hasCB) { cbs.row = r - hrc; if (select == True) XtCallCallbackList(w, g->grid.selectCallback, (XtPointer)&cbs); else XtCallCallbackList(w, g->grid.deselectCallback, (XtPointer)&cbs); } } else if (type == SelectCol) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (!colp) { badPos = 1; continue; } if (XmLGridColumnIsSelected(colp) == select) continue; XmLGridColumnSetSelected(colp, select); if (ColIsVisible(g, c)) DrawArea(g, DrawCol, 0, c); if (notify && hasCB) { cbs.column = c - hcc; if (select == True) XtCallCallbackList(w, g->grid.selectCallback, (XtPointer)&cbs); else XtCallCallbackList(w, g->grid.deselectCallback, (XtPointer)&cbs); } } else if (type == SelectCell) { cellp = GetCell(g, r, c); if (!cellp) { badPos = 1; continue; } if (XmLGridCellIsSelected(cellp) == select) continue; XmLGridCellSetSelected(cellp, select); DrawArea(g, DrawCell, r, c); if (notify && hasCB) { cbs.column = c - hcc; cbs.row = r - hrc; if (select == True) XtCallCallbackList(w, g->grid.selectCallback, (XtPointer)&cbs); else XtCallCallbackList(w, g->grid.deselectCallback, (XtPointer)&cbs); } } } if (badPos) XmLWarning((Widget)g, "SelectTypeArea() - bad position"); } static int GetSelectedArea(XmLGridWidget g, int type, int *rowPos, int *colPos, int count) { XmLGridRow row; XmLGridColumn col; XmLGridCell cell; int r, fr, lr; int c, fc, lc; int n; if (type == SelectCol) { fr = 0; lr = 1; } else { fr = g->grid.headingRowCount; lr = XmLArrayGetCount(g->grid.rowArray) - g->grid.footerRowCount; } if (type == SelectRow) { fc = 0; lc = 1; } else { fc = g->grid.headingColCount; lc = XmLArrayGetCount(g->grid.colArray) - g->grid.footerColCount; } n = 0; for (r = fr; r < lr; r++) for (c = fc; c < lc; c++) { if (type == SelectRow) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (row && XmLGridRowIsSelected(row) == True) { if (rowPos && n < count) rowPos[n] = r - fr; n++; } } else if (type == SelectCol) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (col && XmLGridColumnIsSelected(col) == True) { if (colPos && n < count) colPos[n] = c - fc; n++; } } else if (type == SelectCell) { cell = GetCell(g, r, c); if (cell && XmLGridCellIsSelected(cell) == True) { if (rowPos && colPos && n < count) { rowPos[n] = r - fr; colPos[n] = c - fc; } n++; } } } return n; } static void ChangeManaged(Widget w) { _XmNavigChangeManaged(w); } static void Resize(Widget w) { XmLGridWidget g; XmLGridCallbackStruct cbs; g = (XmLGridWidget)w; if (!g->grid.inResize) { cbs.reason = XmCR_RESIZE_GRID; g->grid.inResize = True; XtCallCallbackList((Widget)g, g->grid.resizeCallback, (XtPointer)&cbs); g->grid.inResize = False; } VertLayout(g, 0); HorizLayout(g, 0); PlaceScrollbars(g); DrawArea(g, DrawAll, 0, 0); } static void PlaceScrollbars(XmLGridWidget g) { int x, y; int width, height; Widget vsb, hsb; Dimension st, headingRowHeight = 0; st = g->manager.shadow_thickness; vsb = g->grid.vsb; hsb = g->grid.hsb; width = g->core.width; if (XtIsManaged(vsb)) width -= vsb->core.width; if (width <= 0) width = 1; y = g->core.height - hsb->core.height; XtConfigureWidget(hsb, 0, y, width, hsb->core.height, 0); height = g->core.height; if (XtIsManaged(hsb)) height -= hsb->core.height; y = 0; if (g->grid.headingRowCount > 0) { XmLGridRow rowp; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, 0); headingRowHeight = XmLGridRowHeightInPixels(rowp) + st; } if (g->grid.hideUnhideButtons && g->grid.hideButton && g->grid.unhideButton) { int buttonWidth = vsb->core.width - 4; if (headingRowHeight == 0) headingRowHeight = 20; /* if there is at least heading row, we make the height of the button the height of the first heading row. This is pretty braindead... */ XtConfigureWidget(g->grid.unhideButton, g->core.width - buttonWidth*2 - st, y + st, buttonWidth, headingRowHeight - st, 0); XtConfigureWidget(g->grid.hideButton, g->core.width - buttonWidth - st, y + st, buttonWidth, headingRowHeight - st, 0); setHideUnhideSensitivity((Widget)g); /* once we've positioned it, make sure it's managed. Doing it in this order (position, then manage) reduces screen flickering -- the button doesn't flash on in the upper left corner for an instant. */ if (!XtIsManaged(g->grid.hideButton)) XtManageChild(g->grid.hideButton); if (!XtIsManaged(g->grid.unhideButton)) XtManageChild(g->grid.unhideButton); } if (height <= 0) width = 1; x = g->core.width - vsb->core.width; XtConfigureWidget(vsb, x, y + headingRowHeight + g->manager.shadow_thickness, vsb->core.width, height - headingRowHeight - g->manager.shadow_thickness, 0); } void _XmLGridLayout(XmLGridWidget g) { VertLayout(g, 1); HorizLayout(g, 1); } static void VertLayout(XmLGridWidget g, int resizeIfNeeded) { GridReg *reg; int i, j, st2, height, rowCount; int topNRow, topHeight; int midRow, midY, midNRow, midHeight; int botRow, botY, botNRow, botHeight; int scrollChanged, needsSB, needsResize, cRow; int maxRow, maxPos, maxHeight, newHeight, sliderSize; int horizSizeChanged; XtWidgetGeometry req; XmLGridCallbackStruct cbs; XmLGridPreLayoutProc preLayoutProc; if (g->grid.layoutFrozen == True) { g->grid.needsVertLayout = 1; return; } maxRow = maxPos = maxHeight = newHeight = horizSizeChanged = 0; preLayoutProc = XmLGridClassPartOfWidget(g).preLayoutProc; if (g->grid.layoutStack < 2 && preLayoutProc != XmInheritGridPreLayout) horizSizeChanged = preLayoutProc(g, 1); scrollChanged = 0; needsResize = 0; needsSB = 0; rowCount = XmLArrayGetCount(g->grid.rowArray); reg = g->grid.reg; st2 = g->manager.shadow_thickness * 2; TextAction(g, TEXT_HIDE); topHeight = 0; topNRow = g->grid.topFixedCount; if (topNRow > g->grid.rowCount + g->grid.headingRowCount) topNRow = g->grid.rowCount + g->grid.headingRowCount; if (topNRow) { topHeight += st2; for (i = 0; i < topNRow; i++) topHeight += GetRowHeight(g, i); } botHeight = 0; botNRow = g->grid.bottomFixedCount; if (topNRow + botNRow > rowCount) botNRow = rowCount - topNRow; botRow = rowCount - botNRow; if (botNRow) { botHeight += st2; for (i = botRow; i < rowCount; i++) botHeight += GetRowHeight(g, i); } height = 0; if (topNRow) height += topHeight + g->grid.topFixedMargin; midY = height; if (botNRow) height += botHeight + g->grid.bottomFixedMargin; if (XtIsManaged(g->grid.hsb)) { height += g->grid.hsb->core.height; height += g->grid.scrollBarMargin; } maxHeight = g->core.height - height; if (g->grid.vsPolicy != XmCONSTANT) { if (rowCount == topNRow + botNRow) midHeight = 0; else midHeight = st2; for (i = topNRow; i < rowCount - botNRow; i++) midHeight += GetRowHeight(g, i); midRow = topNRow; midNRow = rowCount - topNRow - botNRow; needsResize = 1; newHeight = midHeight + height; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout VARIABLE height\n"); } else { if (maxHeight < st2) maxHeight = 0; height = st2; j = rowCount - botNRow - 1; for (i = j; i >= topNRow; i--) { height += GetRowHeight(g, i); if (height > maxHeight) break; } i++; if (i > j) i = j; maxRow = i; if (maxRow < topNRow) maxRow = topNRow; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout max scroll row %d\n", i); if (maxRow == topNRow) { if (g->grid.scrollRow != topNRow) { scrollChanged = 1; g->grid.scrollRow = topNRow; } midRow = topNRow; midHeight = maxHeight; midNRow = rowCount - topNRow - botNRow; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout everything fits\n"); } else { if (g->grid.scrollRow < topNRow) { scrollChanged = 1; g->grid.scrollRow = topNRow; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout scrolled < topRow\n"); } if (g->grid.scrollRow > maxRow) { if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout scrolled > maxRow\n"); scrollChanged = 1; g->grid.scrollRow = maxRow; } height = st2; midNRow = 0; for (i = g->grid.scrollRow; i < rowCount - botNRow; i++) { midNRow++; height += GetRowHeight(g, i); if (height >= maxHeight) break; } needsSB = 1; midRow = g->grid.scrollRow; midHeight = maxHeight; } } botY = midY + midHeight; if (botNRow) botY += g->grid.bottomFixedMargin; for (i = 0; i < 3; i++) { reg[i].y = 0; reg[i].height = topHeight; reg[i].row = 0; reg[i].nrow = topNRow; } for (i = 3; i < 6; i++) { reg[i].y = midY; reg[i].height = midHeight; reg[i].row = midRow; reg[i].nrow = midNRow; } for (i = 6; i < 9; i++) { reg[i].y = botY; reg[i].height = botHeight; reg[i].row = botRow; reg[i].nrow = botNRow; } if (g->grid.debugLevel) { fprintf(stderr, "XmLGrid: VertLayout TOP %3dy %3dh %3dr %3dnr\n", reg[0].y, reg[0].height, reg[0].row, reg[0].nrow); fprintf(stderr, "XmLGrid: VertLayout MID %3dy %3dh %3dr %3dnr\n", reg[3].y, reg[3].height, reg[3].row, reg[3].nrow); fprintf(stderr, "XmLGrid: VertLayout BOT %3dy %3dh %3dr %3dnr\n", reg[6].y, reg[6].height, reg[6].row, reg[6].nrow); } if (needsSB) { if (!XtIsManaged(g->grid.vsb)) { XtManageChild(g->grid.vsb); horizSizeChanged = 1; } if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout set sb values\n"); maxPos = PosToVisPos(g, maxRow, 1); sliderSize = PosToVisPos(g, rowCount - botNRow - 1, 1) - maxPos + 1; XtVaSetValues(g->grid.vsb, XmNminimum, PosToVisPos(g, topNRow, 1), XmNmaximum, maxPos + sliderSize, XmNsliderSize, sliderSize, XmNpageIncrement, sliderSize, XmNvalue, PosToVisPos(g, g->grid.scrollRow, 1), NULL); } else if (g->grid.vsPolicy == XmCONSTANT && g->grid.vsbDisplayPolicy == XmSTATIC) { if (!XtIsManaged(g->grid.vsb)) { XtManageChild(g->grid.vsb); horizSizeChanged = 1; } if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout vsb not needed but static\n"); XtVaSetValues(g->grid.vsb, XmNminimum, 0, XmNmaximum, 1, XmNsliderSize, 1, XmNpageIncrement, 1, XmNvalue, 0, NULL); } else { if (XtIsManaged(g->grid.vsb)) { XtUnmanageChild(g->grid.vsb); horizSizeChanged = 1; } } if (needsResize && resizeIfNeeded) { if (newHeight < 1) newHeight = 1; req.request_mode = CWHeight; req.height = newHeight; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: VertLayout Req h %d\n", (int)newHeight); XtMakeGeometryRequest((Widget)g, &req, NULL); PlaceScrollbars(g); } if (scrollChanged) DrawArea(g, DrawVScroll, 0, 0); TextAction(g, TEXT_SHOW); cRow = g->grid.scrollRow - g->grid.headingRowCount; if (cRow != g->grid.cScrollRow) { g->grid.cScrollRow = cRow; cbs.reason = XmCR_SCROLL_ROW; cbs.rowType = XmCONTENT; cbs.row = cRow; XtCallCallbackList((Widget)g, g->grid.scrollCallback, (XtPointer)&cbs); } if (horizSizeChanged) { if (g->grid.layoutStack > 2) XmLWarning((Widget)g, "VertLayout() - recursion error"); else { g->grid.layoutStack++; HorizLayout(g, resizeIfNeeded); g->grid.layoutStack--; } PlaceScrollbars(g); } } static void HorizLayout(XmLGridWidget g, int resizeIfNeeded) { GridReg *reg; int i, j, st2, width, colCount; int leftNCol, leftWidth; int midCol, midX, midNCol, midWidth; int rightCol, rightX, rightNCol, rightWidth; int scrollChanged, needsSB, needsResize, cCol; int maxCol, maxPos, maxWidth, newWidth, sliderSize; int vertSizeChanged; XtWidgetGeometry req; XmLGridCallbackStruct cbs; XmLGridPreLayoutProc preLayoutProc; if (g->grid.layoutFrozen == True) { g->grid.needsHorizLayout = 1; return; } maxCol = maxPos = newWidth = vertSizeChanged = 0; preLayoutProc = XmLGridClassPartOfWidget(g).preLayoutProc; if (g->grid.layoutStack < 2 && preLayoutProc != XmInheritGridPreLayout) vertSizeChanged = preLayoutProc(g, 0); scrollChanged = 0; needsResize = 0; needsSB = 0; if (g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE && g->grid.visibleCols) colCount = g->grid.visibleCols; else colCount = g->grid.colCount + g->grid.headingColCount + g->grid.footerColCount; if (g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE) { SizeColumnsToFit(g, 0); } reg = g->grid.reg; st2 = g->manager.shadow_thickness * 2; TextAction(g, TEXT_HIDE); leftWidth = 0; leftNCol = g->grid.leftFixedCount; if (leftNCol > g->grid.colCount + g->grid.headingColCount) leftNCol = g->grid.colCount + g->grid.headingColCount; if (leftNCol) { leftWidth += st2; for (i = 0; i < leftNCol; i++) leftWidth += GetColWidth(g, i); } rightWidth = 0; rightNCol = g->grid.rightFixedCount; if (rightNCol + leftNCol > colCount) rightNCol = colCount - leftNCol; rightCol = colCount - rightNCol; if (rightNCol) { rightWidth += st2; for (i = rightCol; i < colCount; i++) rightWidth += GetColWidth(g, i); } width = 0; if (leftNCol) width += leftWidth + g->grid.leftFixedMargin; midX = width; if (rightNCol) width += rightWidth + g->grid.rightFixedMargin; if (XtIsManaged(g->grid.vsb)) { width += g->grid.vsb->core.width; width += g->grid.scrollBarMargin; } maxWidth = g->core.width - width; if (g->grid.hsPolicy == XmVARIABLE || g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE) { if (colCount == leftNCol + rightNCol) midWidth = 0; else midWidth = st2; for (i = leftNCol; i < colCount - rightNCol; i++) midWidth += GetColWidth(g, i); midCol = leftNCol; midNCol = colCount - leftNCol - rightNCol; needsResize = 1; newWidth = midWidth + width; if (g->grid.debugLevel) { if (g->grid.hsPolicy == XmVARIABLE) fprintf(stderr, "XmLGrid: HorizLayout VARIABLE width\n"); else fprintf(stderr, "XmLGrid: HorizLayout REZISE_IF_POSSIBLE\n"); } } else { if (maxWidth < st2) maxWidth = 0; width = st2; j = colCount - rightNCol - 1; for (i = j; i >= leftNCol; i--) { width += GetColWidth(g, i); if (width > maxWidth) break; } i++; if (i > j) i = j; maxCol = i; if (maxCol < leftNCol) maxCol = leftNCol; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout max scroll col %d\n", i); if (maxCol == leftNCol) { if (g->grid.scrollCol != leftNCol) { scrollChanged = 1; g->grid.scrollCol = leftNCol; } midCol = leftNCol; midWidth = maxWidth; midNCol = colCount - leftNCol - rightNCol; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout everything fits\n"); } else { if (g->grid.scrollCol < leftNCol) { scrollChanged = 1; g->grid.scrollCol = leftNCol; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout scroll < leftCol\n"); } if (g->grid.scrollCol > maxCol) { if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout scroll > maxCol\n"); scrollChanged = 1; g->grid.scrollCol = maxCol; } width = st2; midNCol = 0; for (i = g->grid.scrollCol; i < colCount - rightNCol; i++) { midNCol++; width += GetColWidth(g, i); if (width >= maxWidth) break; } needsSB = 1; midCol = g->grid.scrollCol; midWidth = maxWidth; } } rightX = midX + midWidth; if (rightNCol) rightX += g->grid.rightFixedMargin; for (i = 0; i < 9; i += 3) { reg[i].x = 0; reg[i].width = leftWidth; reg[i].col = 0; reg[i].ncol = leftNCol; } for (i = 1; i < 9; i += 3) { reg[i].x = midX; reg[i].width = midWidth; reg[i].col = midCol; reg[i].ncol = midNCol; } for (i = 2; i < 9; i += 3) { reg[i].x = rightX; reg[i].width = rightWidth; reg[i].col = rightCol; reg[i].ncol = rightNCol; } if (g->grid.debugLevel) { fprintf(stderr, "XmLGrid: HorizLayout LFT %3dx %3dw %3dc %3dnc\n", reg[0].x, reg[0].width, reg[0].col, reg[0].ncol); fprintf(stderr, "XmLGrid: HorizLayout MID %3dx %3dw %3dc %3dnc\n", reg[1].x, reg[1].width, reg[1].col, reg[1].ncol); fprintf(stderr, "XmLGrid: HorizLayout RHT %3dx %3dw %3dc %3dnc\n", reg[2].x, reg[2].width, reg[2].col, reg[2].ncol); } if (g->grid.hsPolicy == XmCONSTANT && colCount == 1 && g->grid.colCount == 1 && width > maxWidth) { /* Single Column Pixel Scroll Mode */ if (g->grid.singleColScrollMode) { i = g->grid.singleColScrollPos; if (i < 0) i = 0; else if (i > width - maxWidth) i = width - maxWidth; } else i = 0; XtVaSetValues(g->grid.hsb, XmNminimum, 0, XmNmaximum, width - maxWidth + 1, XmNsliderSize, 1, XmNpageIncrement, ((width - maxWidth) / 4) + 1, XmNvalue, i, NULL); if (!XtIsManaged(g->grid.hsb)) { XtManageChild(g->grid.hsb); vertSizeChanged = 1; } g->grid.singleColScrollMode = 1; g->grid.singleColScrollPos = i; } else g->grid.singleColScrollMode = 0; if (g->grid.singleColScrollMode) ; else if (needsSB) { if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout set sb values\n"); if (!XtIsManaged(g->grid.hsb)) { XtManageChild(g->grid.hsb); vertSizeChanged = 1; } maxPos = PosToVisPos(g, maxCol, 0); sliderSize = PosToVisPos(g, colCount - rightNCol - 1, 0) - maxPos + 1; XtVaSetValues(g->grid.hsb, XmNminimum, PosToVisPos(g, leftNCol, 0), XmNmaximum, maxPos + sliderSize, XmNsliderSize, sliderSize, XmNpageIncrement, sliderSize, XmNvalue, PosToVisPos(g, g->grid.scrollCol, 0), NULL); } else if (g->grid.hsPolicy == XmCONSTANT && g->grid.hsbDisplayPolicy == XmSTATIC) { if (!XtIsManaged(g->grid.hsb)) { XtManageChild(g->grid.hsb); vertSizeChanged = 1; } if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout hsb not needed - static\n"); XtVaSetValues(g->grid.hsb, XmNminimum, 0, XmNmaximum, 1, XmNsliderSize, 1, XmNpageIncrement, 1, XmNvalue, 0, NULL); } else { if (XtIsManaged(g->grid.hsb)) { XtUnmanageChild(g->grid.hsb); vertSizeChanged = 1; } } if (needsResize && resizeIfNeeded) { if (newWidth < 1) newWidth = 1; req.request_mode = CWWidth; req.width = newWidth; if (g->grid.debugLevel) fprintf(stderr, "XmLGrid: HorizLayout Req w %d\n", (int)newWidth); XtMakeGeometryRequest((Widget)g, &req, NULL); PlaceScrollbars(g); } if (scrollChanged) DrawArea(g, DrawHScroll, 0, 0); TextAction(g, TEXT_SHOW); cCol = g->grid.scrollCol - g->grid.headingColCount; if (cCol != g->grid.cScrollCol) { g->grid.cScrollCol = cCol; cbs.reason = XmCR_SCROLL_COLUMN; cbs.columnType = XmCONTENT; cbs.column = cCol; XtCallCallbackList((Widget)g, g->grid.scrollCallback, (XtPointer)&cbs); } if (vertSizeChanged) { if (g->grid.layoutStack > 2) XmLWarning((Widget)g, "HorizLayout() - recursion error"); else { g->grid.layoutStack++; VertLayout(g, resizeIfNeeded); g->grid.layoutStack--; } PlaceScrollbars(g); } } static void ApplyVisibleRows(XmLGridWidget g) { XtWidgetGeometry req; XmLGridCellRefValues *cellValues; if (g->grid.vsPolicy != XmCONSTANT) { XmLWarning((Widget)g, "verticalSizePolicy must be XmCONSTANT to set visibleRows"); return; } cellValues = g->grid.defCellValues; req.request_mode = CWHeight; req.height = g->manager.shadow_thickness * 2 + g->grid.visibleRows * (4 + cellValues->fontHeight + cellValues->topMargin + cellValues->bottomMargin); if (g->grid.hsPolicy == XmCONSTANT && g->grid.hsbDisplayPolicy == XmSTATIC) req.height += g->grid.scrollBarMargin + XtHeight(g->grid.hsb); XtMakeGeometryRequest((Widget)g, &req, NULL); } static void ApplyVisibleCols(XmLGridWidget g) { XtWidgetGeometry req; XmLGridCellRefValues *cellValues; if (g->grid.hsPolicy != XmCONSTANT) { XmLWarning((Widget)g, "horizontalSizePolicy must be XmCONSTANT to set visibleColumns"); return; } cellValues = g->grid.defCellValues; req.request_mode = CWWidth; req.width = g->manager.shadow_thickness * 2 + g->grid.visibleCols * (4 + 8 * cellValues->fontWidth + cellValues->leftMargin + cellValues->rightMargin); if (g->grid.vsPolicy == XmCONSTANT && g->grid.vsbDisplayPolicy == XmSTATIC) req.width += g->grid.scrollBarMargin + XtWidth(g->grid.vsb); XtMakeGeometryRequest((Widget)g, &req, NULL); } static void VisPosChanged(XmLGridWidget g, int isVert) { if (isVert) { g->grid.recalcVertVisPos = 1; g->grid.vertVisChangedHint = 1; } else g->grid.recalcHorizVisPos = 1; } static void RecalcVisPos(XmLGridWidget g, int isVert) { XmLGridRow row; XmLGridColumn col; int i, count, visPos; if (g->grid.layoutFrozen == True) XmLWarning((Widget)g, "RecalcVisPos() - layout is frozen"); visPos = 0; if (isVert) { if (!g->grid.recalcVertVisPos) return; count = XmLArrayGetCount(g->grid.rowArray); for (i = 0; i < count; i++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i); XmLGridRowSetVisPos(row, visPos); if (!XmLGridRowIsHidden(row)) visPos++; } g->grid.recalcVertVisPos = 0; } else { if (!g->grid.recalcHorizVisPos) return; count = XmLArrayGetCount(g->grid.colArray); for (i = 0; i < count; i++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); XmLGridColumnSetVisPos(col, visPos); if (!XmLGridColumnIsHidden(col)) visPos++; } g->grid.recalcHorizVisPos = 0; } } static int PosToVisPos(XmLGridWidget g, int pos, int isVert) { int visPos; XmLGridRow row; XmLGridColumn col; if (isVert) { if (!g->grid.hiddenRowCount) visPos = pos; else { RecalcVisPos(g, isVert); row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, pos); if (row) visPos = XmLGridRowGetVisPos(row); else visPos = -1; } } else { if (!g->grid.hiddenColCount) visPos = pos; else { RecalcVisPos(g, isVert); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, pos); if (col) visPos = XmLGridColumnGetVisPos(col); else visPos = -1; } } if (visPos == -1) XmLWarning((Widget)g, "PosToVisPos() - invalid pos"); return visPos; } static int VisPosToPos(XmLGridWidget g, int visPos, int isVert) { XmLGridRow row; XmLGridColumn col; int i1, i2, vp1, vp2, ic, mid, val, count; if (isVert) { if (!g->grid.hiddenRowCount) return visPos; count = XmLArrayGetCount(g->grid.rowArray); if (!count) { XmLWarning((Widget)g, "VisPosToPos() - called when no rows exist"); return -1; } RecalcVisPos(g, isVert); row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, 0); vp1 = XmLGridRowGetVisPos(row); row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, count - 1); vp2 = XmLGridRowGetVisPos(row); if (visPos < vp1 || visPos > vp2) { XmLWarning((Widget)g, "VisPosToPos() - invalid Vert visPos"); return -1; } } else { if (!g->grid.hiddenColCount) return visPos; count = XmLArrayGetCount(g->grid.colArray); if (!count) { XmLWarning((Widget)g, "VisPosToPos() - called when no cols exist"); return -1; } RecalcVisPos(g, isVert); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, 0); vp1 = XmLGridColumnGetVisPos(col); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, count - 1); vp2 = XmLGridColumnGetVisPos(col); if (visPos < vp1 || visPos > vp2) { XmLWarning((Widget)g, "VisPosToPos() - invalid Horiz visPos"); return -1; } } i1 = 0; i2 = count; ic = 0; while (1) { mid = i1 + (i2 - i1) / 2; if (isVert) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, mid); val = XmLGridRowGetVisPos(row); } else { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, mid); val = XmLGridColumnGetVisPos(col); } if (visPos > val) i1 = mid; else if (visPos < val) i2 = mid; else break; if (++ic > 1000) return -1; /* inf loop */ } return mid; } static unsigned char ColPosToType(XmLGridWidget g, int pos) { unsigned char type; if (pos < g->grid.headingColCount) type = XmHEADING; else if (pos < g->grid.headingColCount + g->grid.colCount) type = XmCONTENT; else type = XmFOOTER; return type; } static int ColPosToTypePos(XmLGridWidget g, unsigned char type, int pos) { int c; if (type == XmHEADING) c = pos; else if (type == XmCONTENT) c = pos - g->grid.headingColCount; else c = pos - g->grid.headingColCount - g->grid.colCount; return c; } static unsigned char RowPosToType(XmLGridWidget g, int pos) { unsigned char type; if (pos < g->grid.headingRowCount) type = XmHEADING; else if (pos < g->grid.headingRowCount + g->grid.rowCount) type = XmCONTENT; else type = XmFOOTER; return type; } static int RowPosToTypePos(XmLGridWidget g, unsigned char type, int pos) { int r; if (type == XmHEADING) r = pos; else if (type == XmCONTENT) r = pos - g->grid.headingRowCount; else r = pos - g->grid.headingRowCount - g->grid.rowCount; return r; } static int ColTypePosToPos(XmLGridWidget g, unsigned char type, int pos, int allowNeg) { if (pos < 0) { if (!allowNeg) return -1; if (type == XmHEADING) pos = g->grid.headingColCount; else if (type == XmFOOTER || type == XmALL_TYPES) pos = g->grid.headingColCount + g->grid.colCount + g->grid.footerColCount; else /* XmCONTENT */ pos = g->grid.headingColCount + g->grid.colCount; } else { if (type == XmALL_TYPES) ; else if (type == XmHEADING) { if (pos >= g->grid.headingColCount) return -1; } else if (type == XmFOOTER) { if (pos >= g->grid.footerColCount) return -1; pos += g->grid.headingColCount + g->grid.colCount; } else /* XmCONTENT */ { if (pos >= g->grid.colCount) return -1; pos += g->grid.headingColCount; } } return pos; } static int RowTypePosToPos(XmLGridWidget g, unsigned char type, int pos, int allowNeg) { if (pos < 0) { if (!allowNeg) return -1; if (type == XmHEADING) pos = g->grid.headingRowCount; else if (type == XmFOOTER || type == XmALL_TYPES) pos = g->grid.headingRowCount + g->grid.rowCount + g->grid.footerRowCount; else /* XmCONTENT */ pos = g->grid.headingRowCount + g->grid.rowCount; } else { if (type == XmALL_TYPES) ; else if (type == XmHEADING) { if (pos >= g->grid.headingRowCount) return -1; } else if (type == XmFOOTER) { if (pos >= g->grid.footerRowCount) return -1; pos += g->grid.headingRowCount + g->grid.rowCount; } else /* XmCONTENT */ { if (pos >= g->grid.rowCount) return -1; pos += g->grid.headingRowCount; } } return pos; } static int ScrollRowBottomPos(XmLGridWidget g, int row) { int r, h, height; if (g->grid.vsPolicy == XmVARIABLE) return -1; height = g->grid.reg[4].height; h = 0; r = row; while (r >= 0) { h += GetRowHeight(g, r); if (h > height) break; r--; } if (r != row) r++; return r; } static int ScrollColRightPos(XmLGridWidget g, int col) { int c, w, width; if (g->grid.hsPolicy == XmVARIABLE) return -1; width = g->grid.reg[4].width; w = 0; c = col; while (c >= 0) { w += GetColWidth(g, c); if (w >= width) break; c--; } if (c != col) c++; return c; } static int PosIsResize(XmLGridWidget g, int x, int y, int *row, int *col, int *isVert) { XRectangle rect; int i, nx, ny, margin; /* check for bottom resize */ if (g->grid.allowRowResize == True) for (i = 0; i < 2; i++) { nx = x; ny = y - (4 * i); if (XYToRowCol(g, nx, ny, row, col) != -1 && RowColToXY(g, *row, *col, False, &rect) != -1 && ColPosToType(g, *col) == XmHEADING) { margin = ny - (rect.y + rect.height); if (margin > -5 && margin < 5) { *isVert = 1; return 1; } } } /* check for right resize */ if (g->grid.allowColResize == True) for (i = 0; i < 2; i++) { XmLGridColumn colp; int c; nx = x - (4 * i); ny = y; if (XYToRowCol(g, nx, ny, row, col) != -1 && RowColToXY(g, *row, *col, False, &rect) != -1 && RowPosToType(g, *row) == XmHEADING && *col != XmLArrayGetCount(g->grid.colArray) - 1) { Boolean foundResizable = 0; colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, *col); if (!colp->grid.resizable) continue; for (c = *col + 1; c < XmLArrayGetCount(g->grid.colArray); c ++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (colp->grid.resizable) { foundResizable = True; break; } } if (!foundResizable) return 0; margin = nx - (rect.x + rect.width); if (margin > -5 && margin < 5) { *isVert = 0; return 1; } } } return 0; } int XmLGridPosIsResize(Widget g, int x, int y) { int row, col; int isVert; return PosIsResize((XmLGridWidget) g, x, y, &row, &col, &isVert); } static int XYToRowCol(XmLGridWidget g, int x, int y, int *row, int *col) { XRectangle xyRect, rect; GridReg *reg; int i, r, c; int width, height; int st; reg = g->grid.reg; st = g->manager.shadow_thickness; xyRect.x = x; xyRect.y = y; xyRect.width = 1; xyRect.height = 1; for (i = 0; i < 9; i++) { if (!reg[i].width || !reg[i].height) continue; rect.x = reg[i].x + st; rect.y = reg[i].y + st; rect.width = reg[i].width - st * 2; rect.height = reg[i].height - st * 2; if (XmLRectIntersect(&xyRect, &rect) == XmLRectOutside) continue; height = 0; for (r = reg[i].row; r < reg[i].row + reg[i].nrow; r++) { width = 0; for (c = reg[i].col; c < reg[i].col + reg[i].ncol; c++) { rect.x = reg[i].x + st + width; rect.y = reg[i].y + st + height; rect.width = GetColWidth(g, c); rect.height = GetRowHeight(g, r); if (g->grid.singleColScrollMode) rect.x -= g->grid.singleColScrollPos; ClipRectToReg(g, &rect, ®[i]); if (XmLRectIntersect(&xyRect, &rect) != XmLRectOutside) { if (!RowColFirstSpan(g, r, c, row, col, 0, True, True)) return 0; /* SUCCESS */ else return -1; } width += GetColWidth(g, c); } height += GetRowHeight(g, r); } } return -1; } static int RowColToXY(XmLGridWidget g, int row, int col, Boolean clipped, XRectangle *rect) { XmLGridCell cell; XmLGridCellRefValues *cellValues; GridReg *reg; Dimension st; int i, r, c, off; reg = g->grid.reg; st = g->manager.shadow_thickness; cell = GetCell(g, row, col); if (!cell) return -1; cellValues = XmLGridCellGetRefValues(cell); if (!cellValues) return -1; for (i = 0; i < 9; i++) { if (!reg[i].width || !reg[i].height) continue; if (!(col >= reg[i].col && col < reg[i].col + reg[i].ncol && row >= reg[i].row && row < reg[i].row + reg[i].nrow)) continue; off = 0; for (r = reg[i].row; r < row; r++) off += GetRowHeight(g, r); rect->y = reg[i].y + st + off; rect->height = GetRowHeight(g, row); if (cellValues->rowSpan) for (r = row + 1; r <= row + cellValues->rowSpan; r++) rect->height += GetRowHeight(g, r); off = 0; for (c = reg[i].col; c < col; c++) off += GetColWidth(g, c); rect->x = reg[i].x + st + off; rect->width = GetColWidth(g, col); if (cellValues->columnSpan) for (c = col + 1; c <= col + cellValues->columnSpan; c++) rect->width += GetColWidth(g, c); if (g->grid.singleColScrollMode) rect->x -= g->grid.singleColScrollPos; if (clipped == True) ClipRectToReg(g, rect, ®[i]); return 0; } return -1; } static int RowColFirstSpan(XmLGridWidget g, int row, int col, int *firstRow, int *firstCol, XRectangle *rect, Boolean lookLeft, Boolean lookUp) { XmLGridCell cell; int done; done = 0; while (!done) { cell = GetCell(g, row, col); if (!cell) return -1; if (XmLGridCellInRowSpan(cell) == True) { if (lookUp == True) { row--; if (rect) rect->y -= GetRowHeight(g, row); } else row = -1; if (row < 0) done = 1; } else if (XmLGridCellInColumnSpan(cell) == True) { if (lookLeft == True) { col--; if (rect) rect->x -= GetColWidth(g, col); } else col = -1; if (col < 0) done = 1; } else done = 1; } if (row < 0 || col < 0) return -1; *firstRow = row; *firstCol = col; return 0; } static void RowColSpanRect(XmLGridWidget g, int row, int col, XRectangle *rect) { XmLGridCell cell; XmLGridCellRefValues *cellValues; int r, c; cell = GetCell(g, row, col); cellValues = XmLGridCellGetRefValues(cell); rect->width = 0; rect->height = 0; for (r = row; r <= row + cellValues->rowSpan; r++) rect->height += GetRowHeight(g, r); for (c = col; c <= col + cellValues->columnSpan; c++) rect->width += GetColWidth(g, c); } static XmLGridCell GetCell(XmLGridWidget g, int row, int col) { XmLGridRow rowp; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (!rowp) return 0; return (XmLGridCell)XmLArrayGet(XmLGridRowCells(rowp), col); } static int GetColWidth(XmLGridWidget g, int col) { XmLGridColumn colp; colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col); if (!colp) return 0; return XmLGridColumnWidthInPixels(colp); } static int GetRowHeight(XmLGridWidget g, int row) { XmLGridRow rowp; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (!rowp) return 0; return XmLGridRowHeightInPixels(rowp); } static int ColIsVisible(XmLGridWidget g, int col) { XmLGridColumn c; int i, c1, c2; c = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col); if (!c) { XmLWarning((Widget)g, "ColumnIsVisible() - invalid column"); return -1; } if (XmLGridColumnIsHidden(c) == True) return 0; if (g->grid.hsPolicy != XmCONSTANT) return 1; for (i = 0; i < 3; i ++) { c1 = g->grid.reg[i].col; c2 = c1 + g->grid.reg[i].ncol; if (col >= c1 && col < c2) return 1; } return 0; } static int RowIsVisible(XmLGridWidget g, int row) { XmLGridRow r; int i, r1, r2; r = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (!r) { XmLWarning((Widget)g, "RowIsVisible() - invalid row"); return -1; } if (XmLGridRowIsHidden(r) == True) return 0; if (g->grid.vsPolicy != XmCONSTANT) return 1; for (i = 0; i < 9; i += 3) { r1 = g->grid.reg[i].row; r2 = r1 + g->grid.reg[i].nrow; if (row >= r1 && row < r2) return 1; } return 0; } static XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *allow) { if (request->request_mode & CWWidth) w->core.width = request->width; if (request->request_mode & CWHeight) w->core.height = request->height; if (request->request_mode & CWX) w->core.x = request->x; if (request->request_mode & CWY) w->core.y = request->y; if (request->request_mode & CWBorderWidth) w->core.border_width = request->border_width; return XtGeometryYes; } static void ScrollCB(Widget w, XtPointer clientData, XtPointer callData) { XmLGridWidget g; XmScrollBarCallbackStruct *cbs; unsigned char orientation; int visPos; g = (XmLGridWidget)(XtParent(w)); cbs = (XmScrollBarCallbackStruct *)callData; visPos = cbs->value; XtVaGetValues(w, XmNorientation, &orientation, NULL); if (orientation == XmHORIZONTAL && g->grid.singleColScrollMode) { g->grid.singleColScrollPos = visPos; DrawArea(g, DrawHScroll, 0, 0); } else if (orientation == XmVERTICAL) { if (visPos == PosToVisPos(g, g->grid.scrollRow, 1)) return; g->grid.scrollRow = VisPosToPos(g, visPos, 1); VertLayout(g, 0); DrawArea(g, DrawVScroll, 0, 0); } else { if (visPos == PosToVisPos(g, g->grid.scrollCol, 0)) return; g->grid.scrollCol = VisPosToPos(g, visPos, 0); HorizLayout(g, 0); DrawArea(g, DrawHScroll, 0, 0); } } static int FindNextFocus(XmLGridWidget g, int row, int col, int rowDir, int colDir, int *nextRow, int *nextCol) { int traverse; int hrc, hcc, rc, cc; XmLGridColumn colp; XmLGridRow rowp; XmLGridCell cell; hcc = g->grid.headingColCount; cc = g->grid.colCount; hrc = g->grid.headingRowCount; rc = g->grid.rowCount; if (!rc || !cc) return -1; if (col < hcc) col = hcc; else if (col >= hcc + cc) col = hcc + cc - 1; if (row < hrc) row = hrc; else if (row >= hrc + rc) row = hrc + rc - 1; traverse = 0; while (1) { if (row < hrc || row >= hrc + rc) break; if (col < hcc || col >= hcc + cc) break; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col); cell = GetCell(g, row, col); if (cell && RowPosToType(g, row) == XmCONTENT && ColPosToType(g, col) == XmCONTENT && XmLGridCellInRowSpan(cell) == False && XmLGridCellInColumnSpan(cell) == False && XmLGridRowIsHidden(rowp) == False && XmLGridColumnIsHidden(colp) == False) { traverse = 1; break; } if (!rowDir && !colDir) break; row += rowDir; col += colDir; } if (!traverse) return -1; *nextRow = row; *nextCol = col; return 0; } static int SetFocus(XmLGridWidget g, int row, int col, int rowDir, int colDir) { if (FindNextFocus(g, row, col, rowDir, colDir, &row, &col) == -1) return -1; ChangeFocus(g, row, col); return 0; } static void ChangeFocus(XmLGridWidget g, int row, int col) { XmLGridCell cell; XmLGridCallbackStruct cbs; int focusRow, focusCol; focusRow = g->grid.focusRow; focusCol = g->grid.focusCol; g->grid.focusRow = row; g->grid.focusCol = col; if (focusRow != -1 && focusCol != -1) { cell = GetCell(g, focusRow, focusCol); if (cell) { if (g->grid.highlightRowMode == True) DrawArea(g, DrawRow, focusRow, 0); else DrawArea(g, DrawCell, focusRow, focusCol); cbs.reason = XmCR_CELL_FOCUS_OUT; cbs.columnType = ColPosToType(g, focusCol); cbs.column = ColPosToTypePos(g, cbs.columnType, focusCol); cbs.rowType = RowPosToType(g, focusRow); cbs.row = RowPosToTypePos(g, cbs.rowType, focusRow); XmLGridCellAction(cell, (Widget)g, &cbs); XtCallCallbackList((Widget)g, g->grid.cellFocusCallback, (XtPointer)&cbs); } } if (row != -1 && col != -1) { cell = GetCell(g, row, col); if (cell) { if (g->grid.highlightRowMode == True) DrawArea(g, DrawRow, row, 0); else DrawArea(g, DrawCell, row, col); cbs.reason = XmCR_CELL_FOCUS_IN; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XmLGridCellAction(cell, (Widget)g, &cbs); XtCallCallbackList((Widget)g, g->grid.cellFocusCallback, (XtPointer)&cbs); } else { if (!XmLArrayGet(g->grid.rowArray, row)) g->grid.focusRow = -1; if (!XmLArrayGet(g->grid.colArray, col)) g->grid.focusCol = -1; } } } static void MakeColVisible(XmLGridWidget g, int col) { int st, width, scrollWidth, scrollCol, prevScrollCol; if (g->grid.hsPolicy != XmCONSTANT) return; if (col < g->grid.leftFixedCount || col >= XmLArrayGetCount(g->grid.colArray) - g->grid.rightFixedCount) return; st = g->manager.shadow_thickness; scrollCol = col; if (col > g->grid.scrollCol) { scrollWidth = g->grid.reg[4].width - st * 2; width = 0; while (1) { width += GetColWidth(g, scrollCol); if (width > scrollWidth) break; if (scrollCol < g->grid.leftFixedCount) break; scrollCol--; } scrollCol++; if (scrollCol > col) scrollCol = col; /* only scroll if needed */ if (scrollCol < g->grid.scrollCol) scrollCol = g->grid.scrollCol; } if (scrollCol == g->grid.scrollCol) return; prevScrollCol = g->grid.scrollCol; g->grid.scrollCol = scrollCol; HorizLayout(g, 0); if (g->grid.scrollCol != prevScrollCol) DrawArea(g, DrawHScroll, 0, 0); } static void MakeRowVisible(XmLGridWidget g, int row) { int st, height, scrollHeight, scrollRow, prevScrollRow; if (g->grid.vsPolicy != XmCONSTANT) return; if (row < g->grid.topFixedCount || row >= XmLArrayGetCount(g->grid.rowArray) - g->grid.bottomFixedCount) return; st = g->manager.shadow_thickness; scrollRow = row; if (row > g->grid.scrollRow) { scrollHeight = g->grid.reg[4].height - st * 2; height = 0; while (1) { height += GetRowHeight(g, scrollRow); if (height > scrollHeight) break; if (scrollRow < g->grid.topFixedCount) break; scrollRow--; } scrollRow++; if (scrollRow > row) scrollRow = row; /* only scroll if needed */ if (scrollRow < g->grid.scrollRow) scrollRow = g->grid.scrollRow; } if (scrollRow == g->grid.scrollRow) return; prevScrollRow = g->grid.scrollRow; g->grid.scrollRow = scrollRow; VertLayout(g, 0); if (g->grid.scrollRow != prevScrollRow) DrawArea(g, DrawVScroll, 0, 0); } static void TextAction(XmLGridWidget g, int action) { int row, col, reason, ret, isVisible; XRectangle rect; XtTranslations trans; WidgetClass wc; XmLGridCell cellp; XmLGridCallbackStruct cbs; if (!g->grid.text || !XtIsRealized(g->grid.text)) return; row = g->grid.focusRow; col = g->grid.focusCol; if (row == -1 || col == -1) return; isVisible = 0; if (RowColToXY(g, row, col, True, &rect) != -1) isVisible = 1; cellp = GetCell(g, row, col); if (!cellp) return; cbs.rowType = XmCONTENT; cbs.row = RowPosToTypePos(g, XmCONTENT, row); cbs.columnType = XmCONTENT; cbs.column = ColPosToTypePos(g, XmCONTENT, col); cbs.clipRect = ▭ switch (action) { case TEXT_EDIT: case TEXT_EDIT_INSERT: { if (g->grid.inEdit || !isVisible) return; g->grid.inEdit = 1; if (action == TEXT_EDIT) cbs.reason = XmCR_EDIT_BEGIN; else cbs.reason = XmCR_EDIT_INSERT; ret = XmLGridCellAction(cellp, (Widget)g, &cbs); if (ret) { reason = cbs.reason; cbs.reason = XmCR_CONF_TEXT; XmLGridCellAction(cellp, (Widget)g, &cbs); cbs.reason = reason; wc = g->grid.text->core.widget_class; trans = (XtTranslations)wc->core_class.tm_table; XtVaSetValues(g->grid.text, XmNtranslations, trans, NULL); XtOverrideTranslations(g->grid.text, g->grid.editTrans); XtMapWidget(g->grid.text); g->grid.textHidden = 0; XtCallCallbackList((Widget)g, g->grid.editCallback, (XtPointer)&cbs); } else g->grid.inEdit = 0; break; } case TEXT_EDIT_CANCEL: case TEXT_EDIT_COMPLETE: { if (!g->grid.inEdit) return; if (action == TEXT_EDIT_COMPLETE) cbs.reason = XmCR_EDIT_COMPLETE; else cbs.reason = XmCR_EDIT_CANCEL; XmLGridCellAction(cellp, (Widget)g, &cbs); wc = g->grid.text->core.widget_class; trans = (XtTranslations)wc->core_class.tm_table; XtVaSetValues(g->grid.text, XmNtranslations, trans, NULL); XtOverrideTranslations(g->grid.text, g->grid.traverseTrans); XtCallCallbackList((Widget)g, g->grid.editCallback, (XtPointer)&cbs); XmTextSetString(g->grid.text, ""); XmTextSetInsertionPosition(g->grid.text, 0); g->grid.inEdit = 0; XtUnmapWidget(g->grid.text); g->grid.textHidden = 1; XtConfigureWidget(g->grid.text, 0, 0, 30, 10, 0); break; } case TEXT_HIDE: { if (g->grid.textHidden || !isVisible) return; XtUnmapWidget(g->grid.text); g->grid.textHidden = 1; break; } case TEXT_SHOW: { if (!g->grid.textHidden || !g->grid.inEdit || !isVisible) return; if (rect.width == 0 || rect.height == 0) TextAction(g, TEXT_EDIT_CANCEL); else { cbs.reason = XmCR_CONF_TEXT; XmLGridCellAction(cellp, (Widget)g, &cbs); XtMapWidget(g->grid.text); g->grid.textHidden = 0; } break; } } } /* Getting and Setting Values */ static void GetSubValues(Widget w, ArgList args, Cardinal *nargs) { XmLGridWidget g; int i, c; long mask; XmLGridRow row; XmLGridColumn col; XmLGridCell cell; g = (XmLGridWidget)w; row = 0; col = 0; for (i = 0; i < *nargs; i++) { if (!args[i].name) continue; if (!strncmp(args[i].name, "row", 3)) { if (!strcmp(args[i].name, XmNrowPtr)) { row = (XmLGridRow)args[i].value; continue; } mask = 0; GetRowValueMask(g, args[i].name, &mask); if (!mask) continue; if (!row) { XmLWarning(w, "GetValues() - invalid row"); continue; } GetRowValue(g, row, args[i].value, mask); } else if (!strncmp(args[i].name, "column", 6)) { if (!strcmp(args[i].name, XmNcolumnPtr)) { col = (XmLGridColumn)args[i].value; continue; } mask = 0; GetColumnValueMask(g, args[i].name, &mask); if (!mask) continue; if (!col) { XmLWarning(w, "GetValues() - invalid column"); continue; } GetColumnValue(g, col, args[i].value, mask); } else if (!strncmp(args[i].name, "cell", 4)) { mask = 0; CellValueGetMask(args[i].name, &mask); if (!mask) continue; if (!row || !col) { XmLWarning(w, "GetValues() - invalid cell"); continue; } c = XmLGridColumnGetPos(col); cell = (XmLGridCell)XmLArrayGet(XmLGridRowCells(row), c); GetCellValue(cell, args[i].value, mask); } } } static void SetSubValues(Widget w, ArgList args, Cardinal *nargs) { XmLGridWidget g; XmLGridRow row; XmLGridColumn col; XmLGridCell cell; XmLGridCellRefValues *values, *newValues, *prevValues; XmLArray cellArray; int r, r1, r2, rowsValid; int c, c1, c2, cd1, cd2, colsValid; unsigned char rowType, colType; long rowMask, colMask, cellMask; int i, nRefValues, allCols; int needsHorizResize, needsVertResize; char buf[256]; newValues = (XmLGridCellRefValues *)NULL; g = (XmLGridWidget)w; needsHorizResize = 0; needsVertResize = 0; rowMask = 0; colMask = 0; cellMask = 0; for (i = 0; i < *nargs; i++) { if (!args[i].name) continue; if (!strncmp(args[i].name, "row", 3)) { if (!strcmp(args[i].name, XmNrowPtr)) XmLWarning(w, "SetValues() - can't use XmNrowPtr"); GetRowValueMask(g, args[i].name, &rowMask); } else if (!strncmp(args[i].name, "column", 6)) { if (!strcmp(args[i].name, XmNcolumnPtr)) XmLWarning(w, "SetValues() - can't use XmNcolumnPtr"); GetColumnValueMask(g, args[i].name, &colMask); } else if (!strncmp(args[i].name, "cell", 4)) CellValueGetMask(args[i].name, &cellMask); else if (rowMask || colMask || cellMask) { sprintf(buf, "SetValues() - %s is not a row/column/cell resource", args[i].name); XmLWarning(w, buf); } } if (rowMask || colMask || cellMask) { if (g->grid.rowType == XmINVALID_TYPE) rowType = XmCONTENT; else rowType = g->grid.rowType; rowsValid = 1; if (g->grid.cellRowRangeStart != -1 && g->grid.cellRowRangeEnd != -1) { r1 = RowTypePosToPos(g, rowType, g->grid.cellRowRangeStart, 0); r2 = RowTypePosToPos(g, rowType, g->grid.cellRowRangeEnd, 0); if (r1 < 0 || r2 < 0 || r1 > r2) rowsValid = 0; r2++; } else if (g->grid.cellRow != -1) { r1 = RowTypePosToPos(g, rowType, g->grid.cellRow, 0); if (r1 == -1) rowsValid = 0; r2 = r1 + 1; } else { r1 = RowTypePosToPos(g, rowType, 0, 0); if (r1 == -1) r1 = 0; r2 = RowTypePosToPos(g, rowType, -1, 1); } if (!rowsValid) { XmLWarning(w, "SetValues() - invalid row(s) specified"); r1 = 0; r2 = 0; } if (g->grid.colType == XmINVALID_TYPE) colType = XmCONTENT; else colType = g->grid.colType; colsValid = 1; if (g->grid.cellColRangeStart != -1 && g->grid.cellColRangeEnd != -1) { c1 = ColTypePosToPos(g, colType, g->grid.cellColRangeStart, 0); c2 = ColTypePosToPos(g, colType, g->grid.cellColRangeEnd, 0); if (c1 < 0 || c2 < 0 || c1 > c2) colsValid = 0; c2++; } else if (g->grid.cellCol != -1) { c1 = ColTypePosToPos(g, colType, g->grid.cellCol, 0); if (c1 == -1) colsValid = 0; c2 = c1 + 1; } else { c1 = ColTypePosToPos(g, colType, 0, 0); if (c1 == -1) c1 = 0; c2 = ColTypePosToPos(g, colType, -1, 1); } if (!colsValid) { XmLWarning(w, "SetValues() - invalid column(s) specified"); c1 = 0; c2 = 0; } if (g->grid.debugLevel) { fprintf(stderr, "XmLGrid: SetValues for rows %d to %d\n", r1, r2); fprintf(stderr, "XmLGrid: & columns %d to %d\n", c1, c2); } if (rowMask) for (r = r1; r < r2; r += g->grid.rowStep) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (!row) continue; if (SetRowValues(g, row, rowMask)) needsVertResize = 1; DrawArea(g, DrawRow, r, 0); } if (colMask) for (c = c1; c < c2; c += g->grid.colStep) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (!col) continue; if (SetColumnValues(g, col, colMask)) needsHorizResize = 1; DrawArea(g, DrawCol, 0, c); } if (cellMask) SetCellValuesPreprocess(g, cellMask); if (cellMask && g->grid.cellDefaults == True) { allCols = 0; if (g->grid.colType == XmINVALID_TYPE && g->grid.cellCol == -1 && g->grid.cellColRangeStart == -1 && g->grid.cellColRangeEnd == -1 && g->grid.colStep == 1) allCols = 1; if (allCols) { /* set cell default values */ newValues = CellRefValuesCreate(g, g->grid.defCellValues); newValues->refCount = 1; SetCellRefValues(g, newValues, cellMask); if (newValues->rowSpan || newValues->columnSpan) { newValues->rowSpan = 0; newValues->columnSpan = 0; XmLWarning((Widget)g, "SetValues() - can't set default cell spans"); } XmLGridCellDerefValues(g->grid.defCellValues); g->grid.defCellValues = newValues; cd1 = 0; cd2 = XmLArrayGetCount(g->grid.colArray); } else { cd1 = c1; cd2 = c2; } /* set column cell default values */ for (c = cd1; c < cd2; c += g->grid.colStep) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (!col) continue; if (allCols && !col->grid.defCellValues) continue; if (col->grid.defCellValues) newValues = CellRefValuesCreate(g, col->grid.defCellValues); else newValues = CellRefValuesCreate(g, g->grid.defCellValues); newValues->refCount = 1; SetCellRefValues(g, newValues, cellMask); if (newValues->rowSpan || newValues->columnSpan) { newValues->rowSpan = 0; newValues->columnSpan = 0; XmLWarning((Widget)g, "SetValues() - can't set default cell spans"); } if (col->grid.defCellValues) XmLGridCellDerefValues(col->grid.defCellValues); col->grid.defCellValues = newValues; } } else if (cellMask) { /* set cell values */ if (SetCellHasRefValues(cellMask)) { cellArray = XmLArrayNew(0, 0); XmLArrayAdd(cellArray, -1, (r2 - r1) * (c2 - c1)); nRefValues = 0; for (r = r1; r < r2; r += g->grid.rowStep) for (c = c1; c < c2; c += g->grid.colStep) { cell = GetCell(g, r, c); if (!cell) continue; SetCellRefValuesPreprocess(g, r, c, cell, cellMask); XmLArraySet(cellArray, nRefValues, cell); nRefValues++; } XmLArraySort(cellArray, SetCellRefValuesCompare, (void *)&cellMask, 0, nRefValues); prevValues = 0; for (i = 0; i < nRefValues; i++) { cell = (XmLGridCell)XmLArrayGet(cellArray, i); values = XmLGridCellGetRefValues(cell); if (values != prevValues) { newValues = CellRefValuesCreate(g, values); SetCellRefValues(g, newValues, cellMask); } XmLGridCellSetRefValues(cell, newValues); prevValues = values; } XmLArrayFree(cellArray); } for (r = r1; r < r2; r += g->grid.rowStep) for (c = c1; c < c2; c += g->grid.colStep) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); cell = GetCell(g, r, c); if (!row || !col || !cell) continue; if (SetCellValuesResize(g, row, col, cell, cellMask)) { needsHorizResize = 1; needsVertResize = 1; } SetCellValues(g, cell, cellMask); if (!needsHorizResize && !needsVertResize) DrawArea(g, DrawCell, r, c); } } } if (needsHorizResize) HorizLayout(g, 1); if (needsVertResize) VertLayout(g, 1); if (needsHorizResize || needsVertResize) DrawArea(g, DrawAll, 0, 0); g->grid.rowType = XmINVALID_TYPE; g->grid.colType = XmINVALID_TYPE; g->grid.rowStep = 1; g->grid.colStep = 1; g->grid.cellRow = -1; g->grid.cellRowRangeStart = -1; g->grid.cellRowRangeEnd = -1; g->grid.cellCol = -1; g->grid.cellColRangeStart = -1; g->grid.cellColRangeEnd = -1; g->grid.cellDefaults = False; } static Boolean SetValues(Widget curW, Widget reqW, Widget newW, ArgList args, Cardinal *nargs) { XmLGridWidget g, cur; int hc, c, fc, hr, r, fr; int tfc, bfc, lfc, rfc; int needsVertLayout, needsHorizLayout, needsRedraw; XmLGridCellRefValues *cellValues; g = (XmLGridWidget)newW; cur = (XmLGridWidget)curW; needsRedraw = 0; needsVertLayout = 0; needsHorizLayout = 0; #define NE(value) (g->value != cur->value) if (NE(grid.cScrollCol)) { g->grid.scrollCol = g->grid.cScrollCol + g->grid.headingColCount; needsHorizLayout = 1; needsRedraw = 1; } if (NE(grid.cScrollRow)) { g->grid.scrollRow = g->grid.cScrollRow + g->grid.headingRowCount; needsVertLayout = 1; needsRedraw = 1; } if (NE(grid.bottomFixedCount) || NE(grid.bottomFixedMargin) || NE(grid.topFixedCount) || NE(grid.topFixedMargin) || NE(grid.vsbDisplayPolicy)) { needsVertLayout = 1; needsRedraw = 1; } if (NE(grid.leftFixedCount) || NE(grid.leftFixedMargin) || NE(grid.rightFixedCount) || NE(grid.rightFixedMargin) || NE(grid.hsbDisplayPolicy)) { needsHorizLayout = 1; needsRedraw = 1; } if (NE(grid.layoutFrozen)) { if (g->grid.layoutFrozen == False) { if (g->grid.needsVertLayout == True) { needsVertLayout = 1; g->grid.needsVertLayout = False; } if (g->grid.needsHorizLayout == True) { needsHorizLayout = 1; g->grid.needsHorizLayout = False; } needsRedraw = 1; } } if (NE(grid.scrollBarMargin) || NE(manager.shadow_thickness) || NE(core.border_width) || NE(grid.vsPolicy) || NE(grid.hsPolicy)) { needsVertLayout = 1; needsHorizLayout = 1; needsRedraw = 1; } if (NE(grid.blankBg) || NE(grid.highlightThickness) || NE(grid.selectBg) || NE(grid.selectFg) || NE(grid.toggleTopColor) || NE(grid.toggleBotColor) || NE(grid.shadowRegions) || NE(grid.shadowType)) needsRedraw = 1; if (NE(grid.fontList)) { XmFontListFree(cur->grid.fontList); CopyFontList(g); cellValues = CellRefValuesCreate(g, g->grid.defCellValues); cellValues->refCount = 1; XmFontListFree(cellValues->fontList); cellValues->fontList = XmFontListCopy(g->grid.fontList); XmLFontListGetDimensions(cellValues->fontList, &cellValues->fontWidth, &cellValues->fontHeight, g->grid.useAvgWidth); XmLGridCellDerefValues(g->grid.defCellValues); g->grid.defCellValues = cellValues; } if (NE(grid.allowDrop)) DropRegister(g, g->grid.allowDrop); if (g->grid.rowStep < 1) { XmLWarning(newW, "SetValues() - rowStep can't be < 1"); g->grid.rowStep = 1; } if (g->grid.colStep < 1) { XmLWarning(newW, "SetValues() - colStep can't be < 1"); g->grid.colStep = 1; } if (NE(grid.hsb) || NE(grid.vsb) || NE(grid.text)) { XmLWarning(newW, "SetValues() - child Widgets are read-only"); g->grid.hsb = cur->grid.hsb; g->grid.vsb = cur->grid.vsb; g->grid.text = cur->grid.text; } if (NE(grid.useTextWidget)) { XmLWarning(newW, "SetValues() - can't set use of text widget"); g->grid.useTextWidget = cur->grid.useTextWidget; } if (NE(grid.hiddenColCount) || NE(grid.hiddenRowCount)) { XmLWarning(newW, "SetValues() - can't set hidden rows or columns"); g->grid.hiddenColCount = cur->grid.hiddenColCount; g->grid.hiddenRowCount = cur->grid.hiddenRowCount; } /* store fixed counts, add/removing rows/columns can change these */ tfc = -1; bfc = -1; lfc = -1; rfc = -1; if (NE(grid.topFixedCount)) tfc = g->grid.topFixedCount; if (NE(grid.bottomFixedCount)) bfc = g->grid.bottomFixedCount; if (NE(grid.leftFixedCount)) lfc = g->grid.leftFixedCount; if (NE(grid.rightFixedCount)) rfc = g->grid.rightFixedCount; g->grid.topFixedCount = cur->grid.topFixedCount; g->grid.bottomFixedCount = cur->grid.bottomFixedCount; g->grid.leftFixedCount = cur->grid.leftFixedCount; g->grid.rightFixedCount = cur->grid.rightFixedCount; hc = g->grid.headingColCount - cur->grid.headingColCount; c = g->grid.colCount - cur->grid.colCount; fc = g->grid.footerColCount - cur->grid.footerColCount; hr = g->grid.headingRowCount - cur->grid.headingRowCount; r = g->grid.rowCount - cur->grid.rowCount; fr = g->grid.footerRowCount - cur->grid.footerRowCount; g->grid.headingColCount = cur->grid.headingColCount; g->grid.colCount = cur->grid.colCount; g->grid.footerColCount = cur->grid.footerColCount; g->grid.headingRowCount = cur->grid.headingRowCount; g->grid.rowCount = cur->grid.rowCount; g->grid.footerRowCount = cur->grid.footerRowCount; if (hc > 0) XmLGridAddColumns((Widget)g, XmHEADING, -1, hc); if (hc < 0) XmLGridDeleteColumns((Widget)g, XmHEADING, g->grid.headingColCount + hc, -(hc)); if (c > 0) XmLGridAddColumns((Widget)g, XmCONTENT, -1, c); if (c < 0) XmLGridDeleteColumns((Widget)g, XmCONTENT, g->grid.colCount + c, -(c)); if (fc > 0) XmLGridAddColumns((Widget)g, XmFOOTER, -1, fc); if (fc < 0) XmLGridDeleteColumns((Widget)g, XmFOOTER, g->grid.footerColCount + fc, -(fc)); if (hr > 0) XmLGridAddRows((Widget)g, XmHEADING, -1, hr); if (hr < 0) XmLGridDeleteRows((Widget)g, XmHEADING, g->grid.headingRowCount + hr, -(hr)); if (r > 0) XmLGridAddRows((Widget)g, XmCONTENT, -1, r); if (r < 0) XmLGridDeleteRows((Widget)g, XmCONTENT, g->grid.rowCount + r, -(r)); if (fr > 0) XmLGridAddRows((Widget)g, XmFOOTER, -1, fr); if (fr < 0) XmLGridDeleteRows((Widget)g, XmFOOTER, g->grid.footerRowCount + fr, -(fr)); /* restore fixed counts if user specified */ if (tfc != -1) g->grid.topFixedCount = tfc; if (bfc != -1) g->grid.bottomFixedCount = bfc; if (lfc != -1) g->grid.leftFixedCount = lfc; if (rfc != -1) g->grid.rightFixedCount = rfc; if (g->grid.topFixedCount < g->grid.headingRowCount) { XmLWarning(newW, "SetValues() - can't set topFixedCount < headingRowCount"); g->grid.topFixedCount = cur->grid.topFixedCount; } if (g->grid.bottomFixedCount < g->grid.footerRowCount) { XmLWarning(newW, "SetValues() - can't set bottomFixedCount < footerRowCount"); g->grid.bottomFixedCount = cur->grid.bottomFixedCount; } if (g->grid.leftFixedCount < g->grid.headingColCount) { XmLWarning(newW, "SetValues() - can't set leftFixedCount < headingColumnCount"); g->grid.leftFixedCount = cur->grid.leftFixedCount; } if (g->grid.rightFixedCount < g->grid.footerColCount) { XmLWarning(newW, "SetValues() - can't set rightFixedCount < footerColumnCount"); g->grid.rightFixedCount = cur->grid.rightFixedCount; } if (NE(grid.simpleHeadings)) { if (cur->grid.simpleHeadings) free((char *)cur->grid.simpleHeadings); if (g->grid.simpleHeadings) { g->grid.simpleHeadings = (char *)strdup(g->grid.simpleHeadings); SetSimpleHeadings(g, g->grid.simpleHeadings); } } if (NE(grid.simpleWidths)) { if (cur->grid.simpleWidths) free((char *)cur->grid.simpleWidths); if (g->grid.simpleWidths) { g->grid.simpleWidths = (char *)strdup(g->grid.simpleWidths); SetSimpleWidths(g, g->grid.simpleWidths); } } if (NE(grid.visibleRows)) { ApplyVisibleRows(g); needsVertLayout = 1; needsRedraw = 1; } if (NE(grid.visibleCols)) { if (g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE) XmLGridSetVisibleColumnCount((Widget)g, g->grid.visibleCols); else ApplyVisibleCols(g); needsHorizLayout = 1; needsRedraw = 1; } /* for the hidden columns stuff */ if (NE(grid.hideUnhideButtons)) { if (g->grid.hideUnhideButtons) { CreateHideUnhideButtons(g); } else { XtDestroyWidget(g->grid.hideButton); XtDestroyWidget(g->grid.unhideButton); g->grid.hideButton = 0; g->grid.unhideButton = 0; } needsVertLayout = 1; needsHorizLayout = 1; needsRedraw = 1; } #undef NE SetSubValues(newW, args, nargs); if (needsVertLayout) VertLayout(g, 1); if (needsHorizLayout) HorizLayout(g, 1); if (needsRedraw) DrawArea(g, DrawAll, 0, 0); return (False); } static void CopyFontList(XmLGridWidget g) { if (!g->grid.fontList) g->grid.fontList = XmLFontListCopyDefault((Widget)g); else g->grid.fontList = XmFontListCopy(g->grid.fontList); if (!g->grid.fontList) XmLWarning((Widget)g, "- fatal error - font list NULL"); } static Boolean CvtStringToSizePolicy(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "CONSTANT", XmCONSTANT }, { "VARIABLE", XmVARIABLE }, { "RESIZE_IF_POSSIBLE", XmRESIZE_IF_POSSIBLE }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRGridSizePolicy", map, fromVal, toVal); } static Boolean CvtStringToRowColType(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "HEADING", XmHEADING }, { "CONTENT", XmCONTENT }, { "FOOTER", XmFOOTER }, { "ALL_TYPES", XmALL_TYPES }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRRowColType", map, fromVal, toVal); } static Boolean CvtStringToSelectionPolicy(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "SELECT_NONE", XmSELECT_NONE }, { "SELECT_SINGLE_ROW", XmSELECT_SINGLE_ROW }, { "SELECT_BROWSE_ROW", XmSELECT_BROWSE_ROW }, { "SELECT_MULTIPLE_ROW", XmSELECT_MULTIPLE_ROW }, { "SELECT_CELL", XmSELECT_CELL }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRGridSelectionPolicy", map, fromVal, toVal); } static Boolean CvtStringToCellAlignment(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "ALIGNMENT_LEFT", XmALIGNMENT_LEFT }, { "ALIGNMENT_CENTER", XmALIGNMENT_CENTER }, { "ALIGNMENT_RIGHT", XmALIGNMENT_RIGHT }, { "ALIGNMENT_TOP_LEFT", XmALIGNMENT_TOP_LEFT }, { "ALIGNMENT_TOP", XmALIGNMENT_TOP }, { "ALIGNMENT_TOP_RIGHT", XmALIGNMENT_TOP_RIGHT }, { "ALIGNMENT_BOTTOM_LEFT", XmALIGNMENT_BOTTOM_LEFT }, { "ALIGNMENT_BOTTOM", XmALIGNMENT_BOTTOM }, { "ALIGNMENT_BOTTOM_RIGHT", XmALIGNMENT_BOTTOM_RIGHT }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRGridCellAlignment", map, fromVal, toVal); } static Boolean CvtStringToCellBorderType(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "BORDER_NONE", XmBORDER_NONE }, { "BORDER_LINE", XmBORDER_LINE }, { "BORDER_DASH", XmBORDER_DASH }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRGridCellBorderType", map, fromVal, toVal); } static Boolean CvtStringToCellType(Display *dpy, XrmValuePtr args, Cardinal *narg, XrmValuePtr fromVal, XrmValuePtr toVal, XtPointer *data) { static XmLStringToUCharMap map[] = { { "ICON_CELL", XmICON_CELL }, { "STRING_CELL", XmSTRING_CELL }, { "PIXMAP_CELL", XmPIXMAP_CELL }, { "TOGGLE_CELL", XmTOGGLE_CELL }, { 0, 0 }, }; return XmLCvtStringToUChar(dpy, "XmRGridCellType", map, fromVal, toVal); } static void SetSimpleHeadings(XmLGridWidget g, char *data) { char *c; int n, count; if (!data || !*data) return; c = data; n = 1; while (*c) { if (*c == '|') n++; c++; } count = XmLArrayGetCount(g->grid.colArray); if (n > count) { XmLWarning((Widget)g, "SetSimpleHeadings() - headings given for non-existing columns"); return; } if (g->grid.headingRowCount < 1) { XmLWarning((Widget)g, "SetSimpleHeadings() - no heading row exists"); return; } XmLGridSetStrings((Widget)g, data); } static void SetSimpleWidths(XmLGridWidget g, char *data) { XmLGridColumn colp; int i, n, colCount, valid; Dimension prevWidth; unsigned char prevSizePolicy; long mask; struct WidthRec { Dimension width; unsigned char sizePolicy; } *widths; if (!data) return; i = ((int)strlen(data) / 2) + 1; widths = (struct WidthRec *)malloc(i * sizeof(struct WidthRec)); valid = 1; n = 0; while (*data) { if (*data >= '0' && *data <= '9') { widths[n].width = atoi(data); while (*data >= '0' && *data <= '9') data++; } else { valid = 0; break; } if (*data == 'c' || *data == 'C') { widths[n].sizePolicy = XmVARIABLE; data++; } else if (*data == 'p' || *data == 'P') { widths[n].sizePolicy = XmCONSTANT; data++; } else { valid = 0; break; } while (*data == ' ') data++; n++; } if (!valid) { free((char *)widths); XmLWarning((Widget)g, "SetSimpleWidths() - invalid widths string"); return; } colCount = XmLArrayGetCount(g->grid.colArray); if (n > colCount) { free((char *)widths); XmLWarning((Widget)g, "SetSimpleWidths() - widths given for non-existing columns"); return; } prevWidth = g->grid.colWidth; prevSizePolicy = g->grid.colSizePolicy; for (i = 0; i < n; i++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); if (!colp) continue; GetColumnValueMask(g, XmNcolumnWidth, &mask); GetColumnValueMask(g, XmNcolumnSizePolicy, &mask); g->grid.colWidth = widths[i].width; g->grid.colSizePolicy = widths[i].sizePolicy; SetColumnValues(g, colp, mask); } free((char *)widths); g->grid.colWidth = prevWidth; g->grid.colSizePolicy = prevSizePolicy; HorizLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } /* Getting and Setting Row Values */ static void GetRowValueMask(XmLGridWidget g, char *s, long *mask) { XmLGridClassPartOfWidget(g).getRowValueMaskProc(g, s, mask); } /* Only to be called through Grid class */ static void _GetRowValueMask(XmLGridWidget g, char *s, long *mask) { static XrmQuark qHeight, qSizePolicy, qUserData; static int quarksValid = 0; XrmQuark q; if (!quarksValid) { qHeight = XrmStringToQuark(XmNrowHeight); qSizePolicy = XrmStringToQuark(XmNrowSizePolicy); qUserData = XrmStringToQuark(XmNrowUserData); quarksValid = 1; } q = XrmStringToQuark(s); if (q == qHeight) *mask |= XmLGridRowHeight; else if (q == qSizePolicy) *mask |= XmLGridRowSizePolicy; else if (q == qUserData) *mask |= XmLGridRowUserData; } static void GetRowValue(XmLGridWidget g, XmLGridRow row, XtArgVal value, long mask) { XmLGridClassPartOfWidget(g).getRowValueProc(g, row, value, mask); } /* Only to be called through Grid class */ static void _GetRowValue(XmLGridWidget g, XmLGridRow row, XtArgVal value, long mask) { switch (mask) { case XmLGridRowHeight: *((Dimension *)value) = row->grid.height; break; case XmLGridRowSizePolicy: *((unsigned char *)value) = row->grid.sizePolicy; break; case XmLGridRowUserData: *((XtPointer *)value) = (XtPointer)row->grid.userData; break; } } static int SetRowValues(XmLGridWidget g, XmLGridRow row, long mask) { return XmLGridClassPartOfWidget(g).setRowValuesProc(g, row, mask); } /* Only to be called through Grid class */ static int _SetRowValues(XmLGridWidget g, XmLGridRow row, long mask) { int needsResize = 0, visible = 0; Boolean newIsHidden; if (mask & XmLGridRowHeight || mask & XmLGridRowSizePolicy) { visible = RowIsVisible(g, XmLGridRowGetPos(row)); XmLGridRowHeightChanged(row); } if (mask & XmLGridRowHeight) { if (g->grid.rowHeight > 0) newIsHidden = False; else newIsHidden = True; if (XmLGridRowIsHidden(row) != newIsHidden) { if (newIsHidden == True) g->grid.hiddenRowCount++; else g->grid.hiddenRowCount--; VisPosChanged(g, 1); needsResize = 1; } if (visible && !g->grid.inResize) needsResize = 1; row->grid.height = g->grid.rowHeight; } if (mask & XmLGridRowSizePolicy) { row->grid.sizePolicy = g->grid.rowSizePolicy; if (visible && !g->grid.inResize) needsResize = 1; } if (mask & XmLGridRowUserData) row->grid.userData = g->grid.rowUserData; return needsResize; } /* Getting and Setting Column Values */ static void GetColumnValueMask(XmLGridWidget g, char *s, long *mask) { XmLGridClassPartOfWidget(g).getColumnValueMaskProc(g, s, mask); } /* Only to be called through Grid class */ static void _GetColumnValueMask(XmLGridWidget g, char *s, long *mask) { static XrmQuark qWidth, qSizePolicy, qUserData, qResizable, qHidden; static int quarksValid = 0; XrmQuark q; if (!quarksValid) { qWidth = XrmStringToQuark(XmNcolumnWidth); qSizePolicy = XrmStringToQuark(XmNcolumnSizePolicy); qUserData = XrmStringToQuark(XmNcolumnUserData); qResizable = XrmStringToQuark(XmNcolumnResizable); qHidden = XrmStringToQuark(XmNcolumnHidden); quarksValid = 1; } q = XrmStringToQuark(s); if (q == qWidth) *mask |= XmLGridColumnWidth; else if (q == qSizePolicy) *mask |= XmLGridColumnSizePolicy; else if (q == qUserData) *mask |= XmLGridColumnUserData; else if (q == qResizable) *mask |= XmLGridColumnResizable; else if (q == qHidden) *mask |= XmLGridColumnHidden; } static void GetColumnValue(XmLGridWidget g, XmLGridColumn col, XtArgVal value, long mask) { XmLGridClassPartOfWidget(g).getColumnValueProc(g, col, value, mask); } /* Only to be called through Grid class */ static void _GetColumnValue(XmLGridWidget g, XmLGridColumn col, XtArgVal value, long mask) { switch (mask) { case XmLGridColumnWidth: *((Dimension *)value) = col->grid.width; break; case XmLGridColumnSizePolicy: *((unsigned char *)value) = col->grid.sizePolicy; break; case XmLGridColumnUserData: *((XtPointer *)value) = col->grid.userData; break; case XmLGridColumnResizable: *((Boolean *)value) = col->grid.resizable; break; case XmLGridColumnHidden: *((Boolean *)value) = col->grid.hidden; break; } } static int SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask) { return XmLGridClassPartOfWidget(g).setColumnValuesProc(g, col, mask); } /* Only to be called through Grid class */ static int _SetColumnValues(XmLGridWidget g, XmLGridColumn col, long mask) { int needsResize = 0, visible = 0; Boolean newIsHidden; if (mask & XmLGridColumnWidth || mask & XmLGridColumnSizePolicy) { visible = ColIsVisible(g, XmLGridColumnGetPos(col)); XmLGridColumnWidthChanged(col); } if (mask & XmLGridColumnWidth) { if (g->grid.colWidth > 0) newIsHidden = False; else newIsHidden = True; if (XmLGridColumnIsHidden(col) != newIsHidden) { if (newIsHidden == True) g->grid.hiddenColCount++; else g->grid.hiddenRowCount--; VisPosChanged(g, 0); needsResize = 1; } if (visible && !g->grid.inResize) needsResize = 1; col->grid.width = g->grid.colWidth; } if (mask & XmLGridColumnSizePolicy) { col->grid.sizePolicy = g->grid.colSizePolicy; if (visible && !g->grid.inResize) needsResize = 1; if (col->grid.sizePolicy != XmCONSTANT && g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE) { XmLWarning((Widget)g, "XmNcolumnSizePolicy must equal XmCONSTANT"); } } if (mask & XmLGridColumnUserData) col->grid.userData = g->grid.colUserData; if (mask & XmLGridColumnResizable) col->grid.resizable = g->grid.colResizable; if (mask & XmLGridColumnHidden) col->grid.hidden = g->grid.colHidden; return needsResize; } /* Getting and Setting Cell Values */ static void CellValueGetMask(char *s, long *mask) { static XrmQuark qAlignment, qBackground, qBottomBorderColor; static XrmQuark qBottomBorderType, qColumnSpan; static XrmQuark qEditable, qFontList, qForeground; static XrmQuark qLeftBorderColor, qLeftBorderType; static XrmQuark qMarginBottom, qMarginLeft, qMarginRight; static XrmQuark qMarginTop, qPixmap, qPixmapMask; static XrmQuark qRightBorderColor, qRightBorderType; static XrmQuark qRowSpan, qString, qToggleSet; static XrmQuark qTopBorderColor, qTopBorderType, qType; static XrmQuark qUserData; static int quarksValid = 0; XrmQuark q; if (!quarksValid) { qAlignment = XrmStringToQuark(XmNcellAlignment); qBackground = XrmStringToQuark(XmNcellBackground); qBottomBorderColor = XrmStringToQuark(XmNcellBottomBorderColor); qBottomBorderType = XrmStringToQuark(XmNcellBottomBorderType); qColumnSpan = XrmStringToQuark(XmNcellColumnSpan); qEditable = XrmStringToQuark(XmNcellEditable); qFontList = XrmStringToQuark(XmNcellFontList); qForeground = XrmStringToQuark(XmNcellForeground); qLeftBorderColor = XrmStringToQuark(XmNcellLeftBorderColor); qLeftBorderType = XrmStringToQuark(XmNcellLeftBorderType); qMarginBottom = XrmStringToQuark(XmNcellMarginBottom); qMarginLeft = XrmStringToQuark(XmNcellMarginLeft); qMarginRight = XrmStringToQuark(XmNcellMarginRight); qMarginTop= XrmStringToQuark(XmNcellMarginTop); qPixmap = XrmStringToQuark(XmNcellPixmap); qPixmapMask = XrmStringToQuark(XmNcellPixmapMask); qRightBorderColor = XrmStringToQuark(XmNcellRightBorderColor); qRightBorderType = XrmStringToQuark(XmNcellRightBorderType); qRowSpan = XrmStringToQuark(XmNcellRowSpan); qString = XrmStringToQuark(XmNcellString); qToggleSet = XrmStringToQuark(XmNcellToggleSet); qTopBorderColor = XrmStringToQuark(XmNcellTopBorderColor); qTopBorderType = XrmStringToQuark(XmNcellTopBorderType); qType = XrmStringToQuark(XmNcellType); qUserData = XrmStringToQuark(XmNcellUserData); quarksValid = 1; } q = XrmStringToQuark(s); if (q == qAlignment) *mask |= XmLGridCellAlignment; else if (q == qBackground) *mask |= XmLGridCellBackground; else if (q == qBottomBorderColor) *mask |= XmLGridCellBottomBorderColor; else if (q == qBottomBorderType) *mask |= XmLGridCellBottomBorderType; else if (q == qColumnSpan) *mask |= XmLGridCellColumnSpan; else if (q == qEditable) *mask |= XmLGridCellEditable; else if (q == qFontList) *mask |= XmLGridCellFontList; else if (q == qForeground) *mask |= XmLGridCellForeground; else if (q == qLeftBorderColor) *mask |= XmLGridCellLeftBorderColor; else if (q == qLeftBorderType) *mask |= XmLGridCellLeftBorderType; else if (q == qMarginBottom) *mask |= XmLGridCellMarginBottom; else if (q == qMarginLeft) *mask |= XmLGridCellMarginLeft; else if (q == qMarginRight) *mask |= XmLGridCellMarginRight; else if (q == qMarginTop) *mask |= XmLGridCellMarginTop; else if (q == qPixmap) *mask |= XmLGridCellPixmapF; else if (q == qPixmapMask) *mask |= XmLGridCellPixmapMask; else if (q == qRightBorderColor) *mask |= XmLGridCellRightBorderColor; else if (q == qRightBorderType) *mask |= XmLGridCellRightBorderType; else if (q == qRowSpan) *mask |= XmLGridCellRowSpan; else if (q == qString) *mask |= XmLGridCellString; else if (q == qToggleSet) *mask |= XmLGridCellToggleSet; else if (q == qTopBorderColor) *mask |= XmLGridCellTopBorderColor; else if (q == qTopBorderType) *mask |= XmLGridCellTopBorderType; else if (q == qType) *mask |= XmLGridCellType; else if (q == qUserData) *mask |= XmLGridCellUserData; } static void GetCellValue(XmLGridCell cell, XtArgVal value, long mask) { XmLGridCellRefValues *values; XmLGridCellPixmap *pix; XmString str; values = XmLGridCellGetRefValues(cell); switch (mask) { case XmLGridCellAlignment: *((unsigned char *)value) = values->alignment; break; case XmLGridCellBackground: *((Pixel *)value) = values->background; break; case XmLGridCellBottomBorderColor: *((Pixel *)value) = values->bottomBorderColor; break; case XmLGridCellBottomBorderType: *((unsigned char *)value) = values->bottomBorderType; break; case XmLGridCellColumnSpan: *((int *)value) = values->columnSpan; break; case XmLGridCellEditable: *((Boolean *)value) = values->editable; break; case XmLGridCellFontList: *((XmFontList *)value) = values->fontList; break; case XmLGridCellForeground: *((Pixel *)value) = values->foreground; break; case XmLGridCellLeftBorderColor: *((Pixel *)value) = values->leftBorderColor; break; case XmLGridCellLeftBorderType: *((unsigned char *)value) = values->leftBorderType; break; case XmLGridCellMarginBottom: *((Dimension *)value) = values->bottomMargin; break; case XmLGridCellMarginLeft: *((Dimension *)value) = values->leftMargin; break; case XmLGridCellMarginRight: *((Dimension *)value) = values->rightMargin; break; case XmLGridCellMarginTop: *((Dimension *)value) = values->topMargin; break; case XmLGridCellPixmapF: pix = XmLGridCellGetPixmap(cell); if (pix) *((Pixmap *)value) = pix->pixmap; else *((Pixmap *)value) = (Pixmap)XmUNSPECIFIED_PIXMAP; break; case XmLGridCellPixmapMask: pix = XmLGridCellGetPixmap(cell); if (pix) *((Pixmap *)value) = pix->pixmask; else *((Pixmap *)value) = (Pixmap)XmUNSPECIFIED_PIXMAP; break; case XmLGridCellRightBorderColor: *((Pixel *)value) = values->rightBorderColor; break; case XmLGridCellRightBorderType: *((unsigned char *)value) = values->rightBorderType; break; case XmLGridCellRowSpan: *((int *)value) = values->rowSpan; break; case XmLGridCellString: str = XmLGridCellGetString(cell); if (str) *((XmString *)value) = XmStringCopy(str); else *((XmString *)value) = 0; break; case XmLGridCellToggleSet: *((Boolean *)value) = XmLGridCellGetToggle(cell); break; case XmLGridCellTopBorderColor: *((Pixel *)value) = values->topBorderColor; break; case XmLGridCellTopBorderType: *((unsigned char *)value) = values->topBorderType; break; case XmLGridCellType: *((unsigned char *)value) = values->type; break; case XmLGridCellUserData: *((XtPointer *)value) = (XtPointer)values->userData; break; } } static XmLGridCellRefValues * CellRefValuesCreate(XmLGridWidget g, XmLGridCellRefValues *copy) { short width, height; XmLGridCellRefValues *values; values = (XmLGridCellRefValues *)malloc(sizeof(XmLGridCellRefValues)); if (!copy) { /* default values */ values->bottomBorderType = XmBORDER_LINE; values->leftBorderType = XmBORDER_LINE; values->rightBorderType = XmBORDER_LINE; values->topBorderType = XmBORDER_LINE; XmLFontListGetDimensions(g->grid.fontList, &width, &height, g->grid.useAvgWidth); values->alignment = XmALIGNMENT_CENTER; values->background = g->core.background_pixel; values->bottomBorderColor = g->manager.bottom_shadow_color; values->bottomMargin = 0; values->columnSpan = 0; values->editable = False; values->fontHeight = height; values->fontList = XmFontListCopy(g->grid.fontList); values->fontWidth = width; values->foreground = g->manager.foreground; values->leftBorderColor = g->manager.top_shadow_color; values->leftMargin = 0; values->refCount = 0; values->rightBorderColor = g->manager.bottom_shadow_color; values->rightMargin = 0; values->rowSpan = 0; values->topBorderColor = g->manager.top_shadow_color; values->topMargin = 0; values->type = XmSTRING_CELL; values->userData = 0; } else { /* copy values */ *values = *copy; values->fontList = XmFontListCopy(copy->fontList); values->refCount = 0; } return values; } static void SetCellValuesPreprocess(XmLGridWidget g, long mask) { XmLGridCellRefValues *newValues; int x, y; short width, height; Display *dpy; Window pixRoot; unsigned int pixWidth, pixHeight; unsigned int pixBW, pixDepth; /* calculate font width and height if set */ newValues = &g->grid.cellValues; if (mask & XmLGridCellFontList) { XmLFontListGetDimensions(newValues->fontList, &width, &height, g->grid.useAvgWidth); newValues->fontWidth = width; newValues->fontHeight = height; } if (mask & XmLGridCellPixmapF) { if (g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP && g->grid.globalPixmapWidth && g->grid.globalPixmapHeight) { g->grid.cellPixmapWidth = g->grid.globalPixmapWidth; g->grid.cellPixmapHeight = g->grid.globalPixmapHeight; } else if (g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP) { dpy = XtDisplay(g); XGetGeometry(dpy, g->grid.cellPixmap, &pixRoot, &x, &y, &pixWidth, &pixHeight, &pixBW, &pixDepth); g->grid.cellPixmapWidth = (Dimension)pixWidth; g->grid.cellPixmapHeight = (Dimension)pixHeight; } else { g->grid.cellPixmapWidth = 0; g->grid.cellPixmapHeight = 0; } } } static int SetCellHasRefValues(long mask) { long unrefMask; /* return 1 if mask contains any reference counted values */ unrefMask = XmLGridCellPixmapF | XmLGridCellPixmapMask | XmLGridCellString | XmLGridCellToggleSet; mask = mask | unrefMask; mask = mask ^ unrefMask; if (!mask) return 0; return 1; } static int SetCellValuesResize(XmLGridWidget g, XmLGridRow row, XmLGridColumn col, XmLGridCell cell, long mask) { return XmLGridClassPartOfWidget(g).setCellValuesResizeProc(g, row, col, cell, mask); } static int _SetCellValuesResize(XmLGridWidget g, XmLGridRow row, XmLGridColumn col, XmLGridCell cell, long mask) { XmLGridCellPixmap *cellPix; int pixResize, needsResize, rowVisible, colVisible; needsResize = 0; pixResize = 0; if (mask & XmLGridCellPixmapF) { pixResize = 1; if (!(mask & XmLGridCellType)) { /* no resize needed if we replace with an equal size pixmap */ cellPix = XmLGridCellGetPixmap(cell); if (cellPix && cellPix->pixmap != XmUNSPECIFIED_PIXMAP && g->grid.cellPixmap != XmUNSPECIFIED_PIXMAP) { if (cellPix->width == g->grid.cellPixmapWidth && cellPix->height == g->grid.cellPixmapHeight) pixResize = 0; } } } if (mask & XmLGridCellType || mask & XmLGridCellFontList || pixResize || mask & XmLGridCellRowSpan || mask & XmLGridCellColumnSpan || mask & XmLGridCellMarginLeft || mask & XmLGridCellMarginRight || mask & XmLGridCellMarginTop || mask & XmLGridCellMarginBottom) { XmLGridRowHeightChanged(row); XmLGridColumnWidthChanged(col); rowVisible = RowIsVisible(g, XmLGridRowGetPos(row)); colVisible = ColIsVisible(g, XmLGridColumnGetPos(col)); if (rowVisible | colVisible) needsResize = 1; } return needsResize; } static void SetCellValues(XmLGridWidget g, XmLGridCell cell, long mask) { /* set non-reference counted cell values */ if (mask & XmLGridCellPixmapF) XmLGridCellSetPixmap(cell, g->grid.cellPixmap, g->grid.cellPixmapWidth, g->grid.cellPixmapHeight); if (mask & XmLGridCellPixmapMask) XmLGridCellSetPixmask(cell, g->grid.cellPixmapMask); if (mask & XmLGridCellString) XmLGridCellSetString(cell, g->grid.cellString, True); if (mask & XmLGridCellToggleSet) XmLGridCellSetToggle(cell, g->grid.cellToggleSet); } static void SetCellRefValues(XmLGridWidget g, XmLGridCellRefValues *values, long mask) { XmLGridCellRefValues *newValues; /* set reference counted cell values */ newValues = &g->grid.cellValues; if (mask & XmLGridCellAlignment) values->alignment = newValues->alignment; if (mask & XmLGridCellBackground) values->background = newValues->background; if (mask & XmLGridCellBottomBorderColor) values->bottomBorderColor = newValues->bottomBorderColor; if (mask & XmLGridCellBottomBorderType) values->bottomBorderType = newValues->bottomBorderType; if (mask & XmLGridCellColumnSpan) values->columnSpan = newValues->columnSpan; if (mask & XmLGridCellEditable) values->editable = newValues->editable; if (mask & XmLGridCellFontList) { XmFontListFree(values->fontList); values->fontList = XmFontListCopy(newValues->fontList); values->fontWidth = newValues->fontWidth; values->fontHeight = newValues->fontHeight; } if (mask & XmLGridCellForeground) values->foreground = newValues->foreground; if (mask & XmLGridCellLeftBorderColor) values->leftBorderColor = newValues->leftBorderColor; if (mask & XmLGridCellLeftBorderType) values->leftBorderType = newValues->leftBorderType; if (mask & XmLGridCellRightBorderColor) values->rightBorderColor = newValues->rightBorderColor; if (mask & XmLGridCellRightBorderType) values->rightBorderType = newValues->rightBorderType; if (mask & XmLGridCellMarginBottom) values->bottomMargin = newValues->bottomMargin; if (mask & XmLGridCellMarginLeft) values->leftMargin = newValues->leftMargin; if (mask & XmLGridCellMarginRight) values->rightMargin = newValues->rightMargin; if (mask & XmLGridCellMarginTop) values->topMargin = newValues->topMargin; if (mask & XmLGridCellRowSpan) values->rowSpan = newValues->rowSpan; if (mask & XmLGridCellTopBorderColor) values->topBorderColor = newValues->topBorderColor; if (mask & XmLGridCellTopBorderType) values->topBorderType = newValues->topBorderType; if (mask & XmLGridCellType) { values->type = newValues->type; /* backwards compatibility cell types */ if (values->type == XmLABEL_CELL) { values->type = XmSTRING_CELL; values->editable = False; } else if (values->type == XmTEXT_CELL) { values->type = XmSTRING_CELL; values->editable = True; } } if (mask & XmLGridCellUserData) values->userData = newValues->userData; } static int SetCellRefValuesCompare(void *userData, void **item1, void **item2) { XmLGridCell cell1, cell2; XmLGridCellRefValues *values1, *values2; long mask; mask = *((long *)userData); cell1 = (XmLGridCell)*item1; cell2 = (XmLGridCell)*item2; values1 = XmLGridCellGetRefValues(cell1); values2 = XmLGridCellGetRefValues(cell2); if (values1 == values2) return 0; #define RVCOMPARE(res, var) \ if (!(mask & res)) \ { \ if (values1->var < values2->var) \ return -1; \ if (values1->var > values2->var) \ return 1; \ } RVCOMPARE(XmLGridCellAlignment, alignment) RVCOMPARE(XmLGridCellBackground, background) RVCOMPARE(XmLGridCellBottomBorderColor, bottomBorderColor) RVCOMPARE(XmLGridCellBottomBorderType, bottomBorderType) RVCOMPARE(XmLGridCellColumnSpan, columnSpan) RVCOMPARE(XmLGridCellEditable, editable) RVCOMPARE(XmLGridCellFontList, fontList) RVCOMPARE(XmLGridCellForeground, foreground) RVCOMPARE(XmLGridCellLeftBorderColor, leftBorderColor) RVCOMPARE(XmLGridCellLeftBorderType, leftBorderType) RVCOMPARE(XmLGridCellMarginBottom, bottomMargin) RVCOMPARE(XmLGridCellMarginLeft, leftMargin) RVCOMPARE(XmLGridCellMarginRight, rightMargin) RVCOMPARE(XmLGridCellMarginTop, topMargin) RVCOMPARE(XmLGridCellRightBorderColor, rightBorderColor) RVCOMPARE(XmLGridCellRightBorderType, rightBorderType) RVCOMPARE(XmLGridCellRowSpan, rowSpan) RVCOMPARE(XmLGridCellTopBorderColor, topBorderColor) RVCOMPARE(XmLGridCellTopBorderType, topBorderType) RVCOMPARE(XmLGridCellType, type) RVCOMPARE(XmLGridCellUserData, userData) #undef RVCOMPARE /* If the two cell values are equal, we merge them into one record here. This speeds up the sort and will allow the merge to compare just the values pointers to test equality. Note that this will not merge every possible item that could be merged, we don't want to do that because of the performance impact */ if (values1 < values2) XmLGridCellSetRefValues(cell1, values2); else XmLGridCellSetRefValues(cell2, values1); return 0; } static void SetCellRefValuesPreprocess(XmLGridWidget g, int row, int col, XmLGridCell cell, long mask) { int r, c, rowSpan, colSpan; XmLGridCell spanCell; XmLGridCellRefValues *oldValues, *newValues; unsigned char oldType, newType; XmLGridCallbackStruct cbs; if (mask & XmLGridCellType) { oldType = XmLGridCellGetRefValues(cell)->type; newType = g->grid.cellValues.type; if (oldType != newType) { cbs.reason = XmCR_FREE_VALUE; XmLGridCellAction(cell, (Widget)g, &cbs); } } if (mask & XmLGridCellRowSpan || mask & XmLGridCellColumnSpan) { /* expose old cell area in case the span area shrinks */ DrawArea(g, DrawCell, row, col); oldValues = XmLGridCellGetRefValues(cell); newValues = &g->grid.cellValues; if (mask & XmLGridCellRowSpan) { g->grid.mayHaveRowSpans = 1; if (newValues->rowSpan < 0) { XmLWarning((Widget)g, "SetValues() - row span can't be < 0"); newValues->rowSpan = 0; } rowSpan = newValues->rowSpan; } else rowSpan = oldValues->rowSpan; if (mask & XmLGridCellColumnSpan) { if (newValues->columnSpan < 0) { XmLWarning((Widget)g, "SetValues() - column span can't be < 0"); newValues->columnSpan = 0; } colSpan = newValues->columnSpan; } else colSpan = oldValues->columnSpan; /* clear old span */ for (c = col; c <= col + oldValues->columnSpan; c++) for (r = row; r <= row + oldValues->rowSpan; r++) { /* skip the cell itself */ if (c == col && r == row) continue; spanCell = GetCell(g, r, c); if (!spanCell) continue; XmLGridCellSetInRowSpan(spanCell, False); XmLGridCellSetInColumnSpan(spanCell, False); } /* set new span */ for (c = col; c <= col + colSpan; c++) for (r = row; r <= row + rowSpan; r++) { /* skip the cell itself */ if (c == col && r == row) continue; spanCell = GetCell(g, r, c); if (!spanCell) continue; if (r == row) XmLGridCellSetInColumnSpan(spanCell, True); else XmLGridCellSetInRowSpan(spanCell, True); } } } /* Read, Write, Copy, Paste */ static int Read(XmLGridWidget g, int format, char delimiter, int row, int col, char *data) { char *c1, *c2, buf[256], *bufp; int r, c, i, j, len, n, needsResize, allowSet, done; XmString str; XmLGridCell cell; XmLGridRow rowp; XmLGridColumn colp; XmLGridCellRefValues *cellValues; XmLGridCallbackStruct cbs; if (format == XmFORMAT_PAD) { XmLWarning((Widget)g, "Read() - FORMAT_PAD not supported"); return 0; } if (format == XmFORMAT_XL || format == XmFORMAT_DROP || format == XmFORMAT_PASTE) delimiter = '\t'; c1 = data; c2 = data; r = row; c = col; needsResize = 0; done = 0; n = 0; while (!done) { if (!(*c2) || *c2 == delimiter || *c2 == '\n') { len = c2 - c1; if (len < 256) bufp = buf; else bufp = (char *)malloc(len + 1); if (format == XmFORMAT_XL) { /* strip leading and trailing double-quotes */ if (len && c1[0] == '"') { c1++; len--; } if (len && c1[len - 1] == '"') len--; } j = 0; for (i = 0; i < len; i++) { if (c1[0] == '\\' && c1[1] == 'n') { bufp[j++] = '\n'; c1 += 2; i++; } else bufp[j++] = *c1++; } bufp[j] = 0; j = 0; str = XmStringCreateLtoR(bufp, XmSTRING_DEFAULT_CHARSET); if (bufp != buf) free((char *)bufp); rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); cell = GetCell(g, r, c); allowSet = 1; if (cell && (format == XmFORMAT_PASTE || format == XmFORMAT_DROP)) { cellValues = XmLGridCellGetRefValues(cell); if (cellValues->type != XmSTRING_CELL || cellValues->editable != True || RowPosToType(g, r) != XmCONTENT || ColPosToType(g, c) != XmCONTENT) allowSet = 0; } if (cell && allowSet) { XmLGridCellSetString(cell, str, False); if (SetCellValuesResize(g, rowp, colp, cell, XmLGridCellString)) needsResize = 1; if (!needsResize) DrawArea(g, DrawCell, r, c); cbs.columnType = ColPosToType(g, c); cbs.column = ColPosToTypePos(g, cbs.columnType, c); cbs.rowType = RowPosToType(g, r); cbs.row = RowPosToTypePos(g, cbs.rowType, r); if (format == XmFORMAT_PASTE) { cbs.reason = XmCR_CELL_PASTE; XtCallCallbackList((Widget)g, g->grid.cellPasteCallback, (XtPointer)&cbs); } else if (format == XmFORMAT_DROP) { cbs.reason = XmCR_CELL_DROP; XtCallCallbackList((Widget)g, g->grid.cellDropCallback, (XtPointer)&cbs); } n++; } else XmStringFree(str); } if (!(*c2)) done = 1; else if (*c2 == delimiter) { c++; c1 = c2 + 1; } else if (*c2 == '\n') { r++; c = col; c1 = c2 + 1; } c2++; } if (needsResize) { VertLayout(g, 1); HorizLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } return n; } static void Write(XmLGridWidget g, FILE *file, int format, char delimiter, Boolean skipHidden, int row, int col, int nrow, int ncol) { int r, c, i, first, last; char *cs = NULL; Boolean set; XmString str; XmLGridColumn colp; XmLGridRow rowp; XmLGridCell cell; first = 1; for (r = row; r < row + nrow; r++) { rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (!rowp) continue; if (skipHidden == True && XmLGridRowIsHidden(rowp) == True) continue; if (first) first = 0; else fprintf(file, "\n"); for (c = col; c < col + ncol; c++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (!colp) continue; if (skipHidden == True && XmLGridColumnIsHidden(colp) == True) continue; cell = GetCell(g, r, c); if (!cell) continue; str = XmLGridCellGetString(cell); set = False; if (str) { cs = CvtXmStringToStr(str); if (cs) set = True; } if (set == False) cs = ""; fprintf(file, "%s", cs); last = 0; if (c == col + ncol - 1) last = 1; if (!last && format == XmFORMAT_DELIMITED) fprintf(file, "%c", delimiter); else if (!last && format == XmFORMAT_XL) fprintf(file, "\t"); else if (format == XmFORMAT_PAD) { if (colp->grid.sizePolicy == XmVARIABLE) for (i = 0; i < (int)(colp->grid.width - strlen(cs)); i++) fprintf(file, " "); } if (set == True) free(cs); } } } static char * CopyDataCreate(XmLGridWidget g, int selected, int row, int col, int nrow, int ncol) { XmLGridColumn colp; XmLGridRow rowp; XmLGridCell cell; char *buf, *cs = NULL; XmString str; Boolean set; int r, c, wroteStr, bufsize, buflen, len; if (selected) { row = 0; nrow = XmLArrayGetCount(g->grid.rowArray); col = 0; ncol = XmLArrayGetCount(g->grid.colArray); } bufsize = 1024; buflen = 0; buf = (char *)malloc(bufsize); for (r = row; r < row + nrow; r++) { wroteStr = 0; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (!rowp) continue; for (c = col; c < col + ncol; c++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (!colp) continue; cell = GetCell(g, r, c); if (!cell) continue; if (selected && XmLGridRowIsSelected(rowp) == False && XmLGridColumnIsSelected(colp) == False && XmLGridCellIsSelected(cell) == False) continue; str = XmLGridCellGetString(cell); set = False; if (str) { cs = CvtXmStringToStr(str); if (cs) set = True; } if (set == False) cs = ""; if (wroteStr) buf[buflen++] = '\t'; len = strlen(cs); /* allocate if string plus tab plus new-line plus 0 if too large */ while (len + buflen + 3 > bufsize) bufsize *= 2; buf = (char *)realloc(buf, bufsize); strcpy(&buf[buflen], cs); buflen += len; if (set == True) free(cs); wroteStr = 1; } if (wroteStr) buf[buflen++] = '\n'; } if (!buflen) { free((char *)buf); return 0; } buf[buflen - 1] = 0; return buf; } static Boolean Copy(XmLGridWidget g, Time time, int selected, int row, int col, int nrow, int ncol) { int i; long itemID; Display *dpy; Window win; XmString clipStr; char *buf; #ifdef MOTIF11 int dataID; #else long ldataID; #endif if (!XtIsRealized((Widget)g)) { XmLWarning((Widget)g, "Copy() - widget not realized"); return False; } dpy = XtDisplay((Widget)g); win = XtWindow((Widget)g); buf = CopyDataCreate(g, selected, row, col, nrow, ncol); if (!buf) return False; clipStr = XmStringCreateSimple("Grid Copy"); for (i = 0; i < 10000; i++) if (XmClipboardStartCopy(dpy, win, clipStr, time, NULL, NULL, &itemID) == ClipboardSuccess) break; XmStringFree(clipStr); if (i == 10000) { XmLWarning((Widget)g, "Copy() - start clipboard copy failed"); return False; } for (i = 0; i < 10000; i++) #ifdef MOTIF11 if (XmClipboardCopy(dpy, win, itemID, "STRING", buf, (long)strlen(buf) + 1, 0, &dataID) == ClipboardSuccess) #else if (XmClipboardCopy(dpy, win, itemID, "STRING", buf, (long)strlen(buf) + 1, 0, &ldataID) == ClipboardSuccess) #endif break; free((char *)buf); if (i == 10000) { XmLWarning((Widget)g, "Copy() - clipboard copy transfer failed"); return False; } for (i = 0; i < 10000; i++) if (XmClipboardEndCopy(dpy, win, itemID) == ClipboardSuccess) break; if (i == 10000) { XmLWarning((Widget)g, "Copy() - end clipboard copy failed"); return False; } return True; } static Boolean Paste(XmLGridWidget g, int row, int col) { Display *dpy; Window win; int i, res, done; unsigned long len, reclen; char *buf; if (!XtIsRealized((Widget)g)) { XmLWarning((Widget)g, "Paste() - widget not realized"); return False; } dpy = XtDisplay((Widget)g); win = XtWindow((Widget)g); for (i = 0; i < 10000; i++) if (XmClipboardInquireLength(dpy, win, "STRING", &len) == ClipboardSuccess) break; if (i == 10000) { XmLWarning((Widget)g, "Paste() - can't retrieve clipboard length"); return False; } if (!len) return False; buf = (char *)malloc((int)len); done = 0; while (!done) { res = XmClipboardRetrieve(dpy, win, "STRING", buf, len, &reclen, NULL); switch (res) { case ClipboardSuccess: done = 2; break; case ClipboardTruncate: case ClipboardNoData: done = 1; break; case ClipboardLocked: break; } } if (done != 2 || reclen != len) { free((char *)buf); XmLWarning((Widget)g, "Paste() - retrieve from clipboard failed"); return False; } Read(g, XmFORMAT_PASTE, 0, row, col, buf); free((char *)buf); return True; } /* Utility */ static void GetCoreBackground(Widget w, int offset, XrmValue *value) { value->addr = (caddr_t)&w->core.background_pixel; } static void GetManagerForeground(Widget w, int offset, XrmValue *value) { XmLGridWidget g; g = (XmLGridWidget)w; value->addr = (caddr_t)&g->manager.foreground; } static void ClipRectToReg(XmLGridWidget g, XRectangle *rect, GridReg *reg) { int i, st; XRectangle regRect; st = g->manager.shadow_thickness; if (!reg->width || !reg->height) i = XmLRectOutside; else { regRect.x = reg->x + st; regRect.y = reg->y + st; regRect.width = reg->width - st * 2; regRect.height = reg->height - st * 2; i = XmLRectIntersect(rect, ®Rect); } if (i == XmLRectInside) return; if (i == XmLRectOutside) { rect->width = 0; rect->height = 0; return; } if (rect->y + (int)rect->height - 1 >= reg->y + (int)reg->height - st) rect->height = reg->y + reg->height - rect->y - st; if (rect->x + (int)rect->width - 1 >= reg->x + (int)reg->width - st) rect->width = reg->x + reg->width - rect->x - st; if (rect->y < reg->y + st) { rect->height -= (reg->y + st) - rect->y; rect->y = reg->y + st; } if (rect->x < reg->x + st) { rect->width -= (reg->x + st) - rect->x; rect->x = reg->x + st; } } static char * FileToString(FILE *file) { long len, n; char *s; if (!file) return 0; fseek(file, 0L, 2); len = ftell(file); s = (char *)malloc((int)len + 1); if (!s) return 0; s[len] = 0; fseek(file, 0L, 0); n = fread(s, 1, (int)len, file); if (n != len) { free((char *)s); return 0; } return s; } static char * CvtXmStringToStr(XmString str) { XmStringContext context; XmStringCharSet charset; XmStringDirection dir; Boolean sep; char *text, *c; int len, size; if (!XmStringInitContext(&context, str)) return 0; size = 0; c = 0; while (XmStringGetNextSegment(context, &text, &charset, &dir, &sep)) { len = strlen(text); size += len + 3; if (!c) { c = (char *)malloc(size); *c = 0; } else c = (char *)realloc(c, size); strcat(c, text); if (sep == True) { len = strlen(c); c[len] = '\\'; c[len + 1] = 'n'; c[len + 2] = 0; } XtFree(text); XtFree(charset); } XmStringFreeContext(context); return c; } static XmLGridWidget WidgetToGrid(Widget w, char *funcname) { char buf[256]; if (!XmLIsGrid(w)) { sprintf(buf, "%s - widget not an XmLGrid", funcname); XmLWarning(w, buf); return 0; } return (XmLGridWidget)w; } /* Actions, Callbacks and Handlers */ static void ButtonMotion(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; XMotionEvent *me; char dragTimerSet; int row, col, x, y; if (event->type != MotionNotify) return; g = (XmLGridWidget)w; me = (XMotionEvent *)event; if (g->grid.inMode == InResize) { if (g->grid.resizeIsVert) DrawResizeLine(g, me->y, 0); else DrawResizeLine(g, me->x, 0); } /* drag scrolling */ dragTimerSet = 0; if (g->grid.inMode == InSelect) { if (g->grid.vsPolicy == XmCONSTANT) { y = g->grid.reg[4].y; if (g->grid.selectionPolicy == XmSELECT_CELL && g->grid.extendRow != -1 && g->grid.extendCol != -1 && RowPosToType(g, g->grid.extendRow) == XmHEADING) ; else if (me->y < y) dragTimerSet |= DragUp; y += g->grid.reg[4].height; if (me->y > y) dragTimerSet |= DragDown; } if (g->grid.hsPolicy == XmCONSTANT) { x = g->grid.reg[4].x; if (g->grid.selectionPolicy == XmSELECT_CELL && g->grid.extendCol != -1 && g->grid.extendRow != -1 && ColPosToType(g, g->grid.extendCol) == XmHEADING) ; else if (me->x < x) dragTimerSet |= DragLeft; x += g->grid.reg[4].width; if (me->x > x) dragTimerSet |= DragRight; } } if (!g->grid.dragTimerSet && dragTimerSet) g->grid.dragTimerId = XtAppAddTimeOut(XtWidgetToApplicationContext(w), 80, DragTimer, (caddr_t)g); else if (g->grid.dragTimerSet && !dragTimerSet) XtRemoveTimeOut(g->grid.dragTimerId); g->grid.dragTimerSet = dragTimerSet; /* Extend Selection */ if (g->grid.inMode == InSelect && XYToRowCol(g, me->x, me->y, &row, &col) != -1) { TextAction(g, TEXT_EDIT_CANCEL); if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW && RowPosToType(g, row) == XmCONTENT) ExtendSelect(g, event, False, row, col); else if (g->grid.selectionPolicy == XmSELECT_CELL) ExtendSelect(g, event, False, row, col); } if (g->grid.inMode == InSelect && g->grid.selectionPolicy == XmSELECT_BROWSE_ROW && XYToRowCol(g, me->x, me->y, &row, &col) != -1) { if (RowPosToType(g, row) == XmCONTENT) { if (!SetFocus(g, row, col, 0, 1)) SelectTypeArea(g, SelectRow, event, RowPosToTypePos(g, XmCONTENT, g->grid.focusRow), 0, True, True); } } } static void DragTimer(XtPointer clientData, XtIntervalId *intervalId) { Widget w; XmLGridWidget g; XRectangle rect; XmLGridRow rowp; XmLGridColumn colp; int r, c, min, max, inc, pi, ss, value, newValue; int extRow, extCol; g = (XmLGridWidget)clientData; w = (Widget)g; extRow = -1; extCol = -1; if (g->grid.vsPolicy == XmCONSTANT && ((g->grid.dragTimerSet & DragUp) || (g->grid.dragTimerSet & DragDown))) { XtVaGetValues(g->grid.vsb, XmNminimum, &min, XmNmaximum, &max, XmNvalue, &value, XmNsliderSize, &ss, XmNincrement, &inc, XmNpageIncrement, &pi, NULL); newValue = value; if (g->grid.dragTimerSet & DragUp) newValue--; else newValue++; if (newValue != value && newValue >= min && newValue <= (max - ss)) { XmScrollBarSetValues(g->grid.vsb, newValue, ss, inc, pi, True); r = g->grid.reg[4].row; if (g->grid.dragTimerSet & DragDown) r += g->grid.reg[4].nrow - 1; /* simple check to make sure row selected is totally visible */ if (g->grid.reg[4].nrow) { rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, r); if (rowp && !RowColToXY(g, r, 0, True, &rect)) { if (GetRowHeight(g, r) != rect.height) r--; } } if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW) { if (!SetFocus(g, r, g->grid.focusCol, -1, 1)) SelectTypeArea(g, SelectRow, (XEvent *)0, RowPosToTypePos(g, XmCONTENT, g->grid.focusRow), 0, True, True); } else if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW) ExtendSelect(g, (XEvent *)0, False, r, g->grid.focusCol); else if (g->grid.selectionPolicy == XmSELECT_CELL) { extRow = r; extCol = g->grid.extendToCol; } } } if (g->grid.hsPolicy == XmCONSTANT && ((g->grid.dragTimerSet & DragLeft) || (g->grid.dragTimerSet & DragRight))) { XtVaGetValues(g->grid.hsb, XmNminimum, &min, XmNmaximum, &max, XmNvalue, &value, XmNsliderSize, &ss, XmNincrement, &inc, XmNpageIncrement, &pi, NULL); newValue = value; if (g->grid.dragTimerSet & DragLeft) newValue--; else newValue++; if (newValue != value && newValue >= min && newValue <= (max - ss)) { XmScrollBarSetValues(g->grid.hsb, newValue, ss, inc, pi, True); c = g->grid.reg[4].col; if (g->grid.dragTimerSet & DragRight) c += g->grid.reg[4].ncol - 1; if (g->grid.selectionPolicy == XmSELECT_CELL) { /* simple check to make sure col selected is totally visible */ if (g->grid.reg[4].ncol) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, c); if (colp && !RowColToXY(g, c, 0, True, &rect)) { if (GetColWidth(g, c) != rect.width) c--; } } if (extRow == -1) extRow = g->grid.extendToRow; extCol = c; } } } if (extRow != -1 && extCol != -1) ExtendSelect(g, (XEvent *)0, False, extRow, extCol); g->grid.dragTimerId = XtAppAddTimeOut(XtWidgetToApplicationContext(w), 80, DragTimer, (caddr_t)g); } /*----------------------------------------------------------------------*/ static void CursorMotion(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; XMotionEvent *me; int isVert, row, col; char defineCursor; if (event->type != MotionNotify) return; g = (XmLGridWidget)w; me = (XMotionEvent *)event; defineCursor = CursorNormal; { int motionRow; int motionCol; int newMotionRow = -1; int newMotionCol = -1; Boolean invokeEnterCellCallback = False; if (XYToRowCol(g,me->x,me->y,&motionRow,&motionCol) != -1) { if (motionRow != g->grid.lastCursorMotionRow || motionCol != g->grid.lastCursorMotionCol) { newMotionRow = motionRow; newMotionCol = motionCol; invokeEnterCellCallback = True; } } if (g->grid.lastCursorMotionRow != -1 && g->grid.lastCursorMotionCol != -1) { /* Invoke XmNleaveCellCallback */ GridInvokeCellCrossingCallbacks(w, g->grid.leaveCellCallback, XmCR_LEAVE_CELL, event, g->grid.lastCursorMotionRow, g->grid.lastCursorMotionCol); } if (invokeEnterCellCallback) { /* Invoke XmNenterCellCallback */ GridInvokeCellCrossingCallbacks(w, g->grid.enterCellCallback, XmCR_ENTER_CELL, event, newMotionRow, newMotionCol); } g->grid.lastCursorMotionRow = newMotionRow; g->grid.lastCursorMotionCol = newMotionCol; } if (PosIsResize(g, me->x, me->y, &row, &col, &isVert)) { if (isVert) defineCursor = CursorVResize; else defineCursor = CursorHResize; } DefineCursor(g, defineCursor); } /*----------------------------------------------------------------------*/ static void Edit(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; g = (XmLGridWidget)XtParent(w); TextAction(g, TEXT_EDIT_INSERT); } static void EditCancel(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; g = (XmLGridWidget)XtParent(w); TextAction(g, TEXT_EDIT_CANCEL); } static void EditComplete(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; g = (XmLGridWidget)XtParent(w); TextAction(g, TEXT_EDIT_COMPLETE); if (*nparam == 1) Traverse(w, event, params, nparam); } #ifndef MOTIF11 extern Widget _XmGetTextualDragIcon(Widget); #endif static void DragStart(Widget w, XEvent *event, String *params, Cardinal *nparam) { #ifndef MOTIF11 XmLGridWidget g; Widget dragIcon; Atom exportTargets[1]; Arg args[10]; char *data; XButtonEvent *be; int row, col; XmLGridColumn colp; XmLGridRow rowp; XmLGridCell cell; static XtCallbackRec dragFinish[2] = { { DragFinish, NULL }, { NULL, NULL } }; g = (XmLGridWidget)w; be = (XButtonEvent *)event; if (!g->grid.allowDrag || !be) return; if (XYToRowCol(g, be->x, be->y, &row, &col) == -1) return; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col); cell = GetCell(g, row, col); if (!rowp || !colp || !cell) return; if (XmLGridRowIsSelected(rowp) == False && XmLGridColumnIsSelected(colp) == False && XmLGridCellIsSelected(cell) == False) return; data = CopyDataCreate(g, 1, 0, 0, 0, 0); if (!data) return; dragIcon = _XmGetTextualDragIcon((Widget)w); exportTargets[0] = XA_STRING; dragFinish[0].closure = (XtPointer)data; XtSetArg(args[0], XmNconvertProc, DragConvert); XtSetArg(args[1], XmNexportTargets, exportTargets); XtSetArg(args[2], XmNnumExportTargets, 1); XtSetArg(args[3], XmNdragOperations, XmDROP_COPY); XtSetArg(args[4], XmNsourceCursorIcon, dragIcon); XtSetArg(args[4], XmNclientData, (XtPointer)data); XtSetArg(args[5], XmNdragDropFinishCallback, dragFinish); XmDragStart(w, event, args, 6); #endif } static Boolean DragConvert(Widget w, Atom *selection, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format) { #ifdef MOTIF11 return FALSE; #else Atom targetsA, timestampA, multipleA, *exportTargets; int n; char *data, *dataCopy; if (!XmIsDragContext(w)) return FALSE; targetsA = XInternAtom(XtDisplay(w), "TARGETS", FALSE); timestampA = XInternAtom(XtDisplay(w), "TIMESTAMP", FALSE); multipleA = XInternAtom(XtDisplay(w), "MULTIPLE", FALSE); if (*target == targetsA) { n = 4; exportTargets = (Atom *)XtMalloc(sizeof(Atom) * n); exportTargets[0] = XA_STRING; exportTargets[1] = targetsA; exportTargets[2] = multipleA; exportTargets[3] = timestampA; *type = XA_ATOM; *value = (XtPointer)exportTargets; *format = 32; *length = (n * sizeof(Atom)) >> 2; return TRUE; } else if (*target == XA_STRING) { XtVaGetValues(w, XmNclientData, &data, NULL); *type = XA_STRING; dataCopy = XtMalloc(strlen(data)); strncpy(dataCopy, data, strlen(data)); *value = (XtPointer)dataCopy; *length = strlen(data); *format = 8; return TRUE; } return FALSE; #endif } static void DragFinish(Widget w, XtPointer clientData, XtPointer callData) { free ((char *)clientData); } static void DropRegister(XmLGridWidget g, Boolean set) { #ifndef MOTIF11 Atom importTargets[1]; Arg args[4]; if (set == True) { importTargets[0] = XA_STRING; XtSetArg(args[0], XmNdropSiteOperations, XmDROP_COPY); XtSetArg(args[1], XmNimportTargets, importTargets); XtSetArg(args[2], XmNnumImportTargets, 1); XtSetArg(args[3], XmNdropProc, DropStart); XmDropSiteRegister((Widget)g, args, 4); } else XmDropSiteUnregister((Widget)g); #endif } static void DropStart(Widget w, XtPointer clientData, XtPointer callData) { #ifndef MOTIF11 XmLGridWidget g; XmDropProcCallbackStruct *cbs; XmDropTransferEntryRec te[2]; Atom *exportTargets; Arg args[10]; int row, col, i, n, valid; g = (XmLGridWidget)w; cbs = (XmDropProcCallbackStruct *)callData; if (g->grid.allowDrop == False || cbs->dropAction == XmDROP_HELP) { cbs->dropSiteStatus = XmINVALID_DROP_SITE; return; } valid = 0; if (XYToRowCol(g, cbs->x, cbs->y, &row, &col) != -1 && cbs->dropAction == XmDROP && cbs->operation == XmDROP_COPY) { XtVaGetValues(cbs->dragContext, XmNexportTargets, &exportTargets, XmNnumExportTargets, &n, NULL); for (i = 0; i < n; i++) if (exportTargets[i] == XA_STRING) valid = 1; } if (!valid) { cbs->operation = (long)XmDROP_NOOP; cbs->dropSiteStatus = XmINVALID_DROP_SITE; XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE); XtSetArg(args[1], XmNnumDropTransfers, 0); XmDropTransferStart(cbs->dragContext, args, 2); return; } g->grid.dropLoc.row = row; g->grid.dropLoc.col = col; cbs->operation = (long)XmDROP_COPY; te[0].target = XA_STRING; te[0].client_data = (XtPointer)g; XtSetArg(args[0], XmNdropTransfers, te); XtSetArg(args[1], XmNnumDropTransfers, 1); XtSetArg(args[2], XmNtransferProc, DropTransfer); XmDropTransferStart(cbs->dragContext, args, 3); #endif } static void DropTransfer(Widget w, XtPointer clientData, Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format) { #ifndef MOTIF11 XmLGridWidget g; char *buf; int len; if (!value) return; g = (XmLGridWidget)clientData; len = (int)*length; if (len < 0) return; buf = (char *)malloc(len + 1); strncpy(buf, (char *)value, len); XtFree((char *)value); buf[len] = 0; Read(g, XmFORMAT_DROP, 0, g->grid.dropLoc.row, g->grid.dropLoc.col, buf); free((char *)buf); #endif } static void Select(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; Display *dpy; Window win; static XrmQuark qACTIVATE, qBEGIN, qEXTEND, qEND; static XrmQuark qTOGGLE; static int quarksValid = 0; XrmQuark q; int isVert; int row, col, resizeRow, resizeCol; XButtonEvent *be; XRectangle rect; XmLGridRow rowp; XmLGridCell cellp; XmLGridColumn colp; XmLGridCallbackStruct cbs; Boolean flag; if (*nparam != 1) return; if (XmLIsGrid(w)) g = (XmLGridWidget)w; else g = (XmLGridWidget)XtParent(w); dpy = XtDisplay(g); win = XtWindow(g); if (!quarksValid) { qACTIVATE = XrmStringToQuark("ACTIVATE"); qBEGIN = XrmStringToQuark("BEGIN"); qEXTEND = XrmStringToQuark("EXTEND"); qEND = XrmStringToQuark("END"); qTOGGLE = XrmStringToQuark("TOGGLE"); } q = XrmStringToQuark(params[0]); be = 0; if (event->type == KeyPress || event->type == KeyRelease) { row = g->grid.focusRow; col = g->grid.focusCol; } else /* Button */ { be = (XButtonEvent *)event; if (XYToRowCol(g, be->x, be->y, &row, &col) == -1) { row = -1; col = -1; } } /* double click activate check */ if (q == qBEGIN && be) { if (row != -1 && col != -1 && row == g->grid.lastSelectRow && col == g->grid.lastSelectCol) { int doubleClickTime = XtGetMultiClickTime(dpy); Time timeSinceLastClick = be->time - g->grid.lastSelectTime; if (timeSinceLastClick < doubleClickTime) { /* Clear inplace editing if some other event happens */ if (g->grid.editTimerSet) { XtRemoveTimeOut(g->grid.editTimerId); g->grid.editTimerSet = 0; } /* Second click came within double click time */ q = qACTIVATE; } else if (!g->grid.editTimerSet && g->grid.lastSelectTime != 0) { /* Only begin an edit when we are sure we don't * have a double click */ if (!g->grid.singleClickActivation) { g->grid.editTimerId = XtAppAddTimeOut(XtWidgetToApplicationContext(w), doubleClickTime*2, EditTimer, (caddr_t)g); g->grid.editTimerSet = 1; } } } g->grid.lastSelectRow = row; g->grid.lastSelectCol = col; g->grid.lastSelectTime = be->time; } else if (q == qBEGIN) g->grid.lastSelectTime = 0; if (q == qBEGIN && be && PosIsResize(g, be->x, be->y, &resizeRow, &resizeCol, &isVert)) { g->grid.resizeIsVert = isVert; g->grid.inMode = InResize; g->grid.resizeLineXY = -1; g->grid.resizeRow = resizeRow; g->grid.resizeCol = resizeCol; if (isVert) { DrawResizeLine(g, be->y, 0); DefineCursor(g, CursorVResize); } else { DrawResizeLine(g, be->x, 0); DefineCursor(g, CursorHResize); } } else if (q == qBEGIN || q == qEXTEND || q == qTOGGLE) { if (g->grid.inMode != InNormal) return; if (row == -1 || col == -1) return; if (RowPosToType(g, row) == XmCONTENT && ColPosToType(g, col) == XmCONTENT) { TextAction(g, TEXT_EDIT_COMPLETE); if (q != qEXTEND) { SetFocus(g, row, col, 0, 1); ExtendSelect(g, event, False, -1, -1); } XmProcessTraversal(g->grid.text, XmTRAVERSE_CURRENT); } if (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW && RowPosToType(g, row) == XmCONTENT) { flag = True; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); #if 0 /* Don't want single click to unselect something. -slamm */ if (q == qBEGIN && rowp && XmLGridRowIsSelected(rowp) == True) flag = False; #endif /* 0 -slamm */ if (q == qTOGGLE && rowp && XmLGridRowIsSelected(rowp) == True) flag = False; if (q == qBEGIN) SelectTypeArea(g, SelectRow, event, -1, 0, False, True); if (be && q == qEXTEND) ExtendSelect(g, event, False, row, col); else SelectTypeArea(g, SelectRow, event, RowPosToTypePos(g, XmCONTENT, row), 0, flag, True); } if (g->grid.selectionPolicy == XmSELECT_CELL) { if (q == qBEGIN) { SelectTypeArea(g, SelectCell, event, -1, -1, False, True); SelectTypeArea(g, SelectRow, event, -1, 0, False, True); SelectTypeArea(g, SelectCol, event, 0, -1, False, True); } else if (q == qTOGGLE) ExtendSelect(g, event, False, -1, -1); if (RowPosToType(g, row) == XmFOOTER || ColPosToType(g, col) == XmFOOTER) ExtendSelect(g, event, False, -1, -1); if (be && q == qEXTEND) ExtendSelect(g, event, False, row, col); else if (RowPosToType(g, row) == XmCONTENT && ColPosToType(g, col) == XmCONTENT) { flag = True; cellp = GetCell(g, row, col); if (q == qTOGGLE && cellp && XmLGridCellIsSelected(cellp) == True) flag = False; SelectTypeArea(g, SelectCell, event, RowPosToTypePos(g, XmCONTENT, row), ColPosToTypePos(g, XmCONTENT, col), flag, True); } else if (RowPosToType(g, row) == XmHEADING && ColPosToType(g, col) == XmCONTENT) { if (q == qTOGGLE) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, col); if (colp && XmLGridColumnIsSelected(colp) == True) g->grid.extendSelect = False; } ExtendSelect(g, event, True, row, col); } else if (ColPosToType(g, col) == XmHEADING && RowPosToType(g, row) == XmCONTENT) { if (q == qTOGGLE) { rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (rowp && XmLGridRowIsSelected(rowp) == True) g->grid.extendSelect = False; } ExtendSelect(g, event, True, row, col); } } if (g->grid.selectionPolicy == XmSELECT_SINGLE_ROW && RowPosToType(g, row) == XmCONTENT) { flag = True; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (rowp && XmLGridRowIsSelected(rowp) == True) flag = False; SelectTypeArea(g, SelectRow, event, RowPosToTypePos(g, XmCONTENT, row), 0, flag, True); } if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW && RowPosToType(g, row) == XmCONTENT) SelectTypeArea(g, SelectRow, event, RowPosToTypePos(g, XmCONTENT, row), 0, True, True); if (g->grid.selectionPolicy == XmSELECT_NONE || (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW && RowPosToType(g, row) != XmCONTENT) || (g->grid.selectionPolicy == XmSELECT_SINGLE_ROW && RowPosToType(g, row) != XmCONTENT) || (g->grid.selectionPolicy == XmSELECT_MULTIPLE_ROW && RowPosToType(g, row) != XmCONTENT) ) { cbs.reason = XmCR_SELECT_CELL; cbs.event = event; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XtCallCallbackList((Widget)g, g->grid.selectCallback, (XtPointer)&cbs); } g->grid.inMode = InSelect; } else if (q == qEND && g->grid.inMode == InResize) { int r, c, width, height; r = g->grid.resizeRow; c = g->grid.resizeCol; g->grid.resizeRow = -1; g->grid.resizeCol = -1; if (!RowColToXY(g, r, c, False, &rect)) { if (g->grid.resizeIsVert) { cbs.rowType = RowPosToType(g, r); cbs.row = RowPosToTypePos(g, cbs.rowType, r); height = 0; if (g->grid.resizeLineXY > rect.y) height = g->grid.resizeLineXY - rect.y - (rect.height - GetRowHeight(g, r)); if (height < 6 && g->grid.allowRowHide == False) height = 6; XtVaSetValues((Widget)g, XmNrowType, cbs.rowType, XmNrow, cbs.row, XmNrowHeight, height, XmNrowSizePolicy, XmCONSTANT, NULL); cbs.reason = XmCR_RESIZE_ROW; } else { cbs.columnType = ColPosToType(g, c); cbs.column = ColPosToTypePos(g, cbs.columnType, c); width = 0; if (g->grid.resizeLineXY > rect.x) width = g->grid.resizeLineXY - rect.x - (rect.width - GetColWidth(g, c)); if (width < 6 && g->grid.allowColHide == False) width = 6; if (g->grid.hsPolicy == XmRESIZE_IF_POSSIBLE) { /* Resize all columns to the right */ XmLGridColumn colp; colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, cbs.column); colp->grid.width = width; SizeColumnsToFit(g, cbs.column + 1); HorizLayout(g, 0); DrawArea(g, DrawAll, 0, 0); } XtVaSetValues((Widget)g, XmNcolumnType, cbs.columnType, XmNcolumn, cbs.column, XmNcolumnWidth, width, XmNcolumnSizePolicy, XmCONSTANT, NULL); cbs.reason = XmCR_RESIZE_COLUMN; } XtCallCallbackList((Widget)g, g->grid.resizeCallback, (XtPointer)&cbs); } DrawResizeLine(g, 0, 2); DefineCursor(g, CursorNormal); g->grid.inMode = InNormal; } else if (q == qEND) { g->grid.inMode = InNormal; if (g->grid.dragTimerSet) XtRemoveTimeOut(g->grid.dragTimerId); g->grid.dragTimerSet = 0; /* XFE Additions to handle button up events in menus - they generate activate events */ { if (XmIsMenuShell(XmLShellOfWidget((Widget)g))) { cbs.reason = XmCR_ACTIVATE; cbs.event = event; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XtCallCallbackList((Widget)g, g->grid.activateCallback, (XtPointer)&cbs); } } } if (q == qBEGIN && g->grid.singleClickActivation) { cbs.reason = XmCR_ACTIVATE; cbs.event = event; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XtCallCallbackList((Widget)g, g->grid.activateCallback, (XtPointer)&cbs); } if (q == qACTIVATE) { cbs.reason = XmCR_ACTIVATE; cbs.event = event; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XtCallCallbackList((Widget)g, g->grid.activateCallback, (XtPointer)&cbs); } } /* * Selection policy when posting a context menu. * If over a current selection, leave the selection alone. * Otherwise, change the selection the same as Select(), * except do not allow dragging to extend the selection. */ static void PopupSelect(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; int row, col; XButtonEvent *be; XmLGridRow rowp; XmLGridCallbackStruct cbs; if (*nparam != 1) return; if (XmLIsGrid(w)) g = (XmLGridWidget)w; else g = (XmLGridWidget)XtParent(w); be = 0; if (event->type == KeyPress || event->type == KeyRelease) { row = g->grid.focusRow; col = g->grid.focusCol; } else /* Button */ { be = (XButtonEvent *)event; if (XYToRowCol(g, be->x, be->y, &row, &col) == -1) { row = -1; col = -1; } } if (RowPosToType(g, row) == XmCONTENT) { XmLGridRow rowp; rowp = (XmLGridRow)XmLArrayGet(g->grid.rowArray, row); if (rowp && !XmLGridRowIsSelected(rowp)) { String end_params[1]; end_params[0] = "END"; Select(w, event, params, nparam); Select(w, event, end_params, nparam); } } if (XtHasCallbacks(w, XmNpopupCallback) == XtCallbackHasSome) { cbs.reason = XmCR_SHOW_POPUP; cbs.event = event; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); XtCallCallbackList((Widget)g, g->grid.popupCallback, (XtPointer)&cbs); } } static void Traverse(Widget w, XEvent *event, String *params, Cardinal *nparam) { XmLGridWidget g; static XrmQuark qDOWN, qEXTEND_DOWN, qEXTEND_LEFT; static XrmQuark qEXTEND_PAGE_DOWN, qEXTEND_PAGE_LEFT; static XrmQuark qEXTEND_PAGE_RIGHT, qEXTEND_PAGE_UP; static XrmQuark qEXTEND_RIGHT, qEXTEND_UP, qLEFT, qPAGE_DOWN; static XrmQuark qPAGE_LEFT, qPAGE_RIGHT, qPAGE_UP, qRIGHT; static XrmQuark qTO_BOTTOM, qTO_BOTTOM_RIGHT, qTO_LEFT; static XrmQuark qTO_RIGHT, qTO_TOP, qTO_TOP_LEFT, qUP; static int quarksValid = 0; int extend, focusRow, focusCol, rowDir, colDir; int rowLoc, colLoc, prevRowLoc, prevColLoc; int scrollRow, scrollCol, prevScrollRow, prevScrollCol; XrmQuark q; g = (XmLGridWidget)XtParent(w); if (*nparam != 1) return; if (!quarksValid) { qDOWN = XrmStringToQuark("DOWN"); qEXTEND_DOWN = XrmStringToQuark("EXTEND_DOWN"); qEXTEND_LEFT = XrmStringToQuark("EXTEND_LEFT"); qEXTEND_PAGE_DOWN = XrmStringToQuark("EXTEND_PAGE_DOWN"); qEXTEND_PAGE_LEFT = XrmStringToQuark("EXTEND_PAGE_LEFT"); qEXTEND_PAGE_RIGHT = XrmStringToQuark("EXTEND_PAGE_RIGHT"); qEXTEND_PAGE_UP = XrmStringToQuark("EXTEND_PAGE_UP"); qEXTEND_RIGHT = XrmStringToQuark("EXTEND_RIGHT"); qEXTEND_UP = XrmStringToQuark("EXTEND_UP"); qLEFT = XrmStringToQuark("LEFT"); qPAGE_DOWN = XrmStringToQuark("PAGE_DOWN"); qPAGE_LEFT = XrmStringToQuark("PAGE_LEFT"); qPAGE_RIGHT = XrmStringToQuark("PAGE_RIGHT"); qPAGE_UP = XrmStringToQuark("PAGE_UP"); qRIGHT = XrmStringToQuark("RIGHT"); qTO_BOTTOM = XrmStringToQuark("TO_BOTTOM"); qTO_BOTTOM_RIGHT = XrmStringToQuark("TO_BOTTOM_RIGHT"); qTO_LEFT = XrmStringToQuark("TO_LEFT"); qTO_RIGHT = XrmStringToQuark("TO_RIGHT"); qTO_TOP = XrmStringToQuark("TO_TOP"); qTO_TOP_LEFT = XrmStringToQuark("TO_TOP_LEFT"); qUP = XrmStringToQuark("UP"); quarksValid = 1; } q = XrmStringToQuark(params[0]); extend = 0; /* map the extends to their counterparts and set extend flag */ if (q == qEXTEND_DOWN) { q = qDOWN; extend = 1; } else if (q == qEXTEND_LEFT) { q = qLEFT; extend = 1; } else if (q == qEXTEND_PAGE_DOWN) { q = qPAGE_DOWN; extend = 1; } else if (q == qEXTEND_PAGE_LEFT) { q = qPAGE_LEFT; extend = 1; } else if (q == qEXTEND_PAGE_RIGHT) { q = qPAGE_RIGHT; extend = 1; } else if (q == qEXTEND_PAGE_UP) { q = qPAGE_UP; extend = 1; } else if (q == qEXTEND_RIGHT) { q = qRIGHT; extend = 1; } else if (q == qEXTEND_UP) { q = qUP; extend = 1; } if (extend && g->grid.selectionPolicy != XmSELECT_MULTIPLE_ROW && g->grid.selectionPolicy != XmSELECT_CELL) return; if (extend && g->grid.extendRow != -1 && g->grid.extendCol != -1) { focusRow = g->grid.extendToRow; focusCol = g->grid.extendToCol; } else { focusRow = g->grid.focusRow; focusCol = g->grid.focusCol; } rowDir = 0; colDir = 0; if (focusRow < g->grid.topFixedCount) prevRowLoc = 0; else if (focusRow >= XmLArrayGetCount(g->grid.rowArray) - g->grid.bottomFixedCount) prevRowLoc = 2; else prevRowLoc = 1; if (focusCol < g->grid.leftFixedCount) prevColLoc = 0; else if (focusCol >= XmLArrayGetCount(g->grid.colArray) - g->grid.rightFixedCount) prevColLoc = 2; else prevColLoc = 1; /* calculate new focus row, col and walk direction */ if (q == qDOWN) { focusRow++; rowDir = 1; } else if (q == qLEFT) { focusCol--; colDir = -1; } else if (q == qPAGE_DOWN) { if (prevRowLoc == 1) focusRow = g->grid.reg[4].row + g->grid.reg[4].nrow - 1; if (focusRow == g->grid.focusRow) focusRow += 4; rowDir = 1; } else if (q == qPAGE_LEFT) { if (prevColLoc == 1) focusCol = g->grid.reg[4].col - 1; if (focusCol == g->grid.focusCol) focusCol -= 4; colDir = -1; } else if (q == qPAGE_RIGHT) { if (prevColLoc == 1) focusCol = g->grid.reg[4].col + g->grid.reg[4].ncol - 1; if (focusCol == g->grid.focusCol) focusCol += 4; colDir = 1; } else if (q == qPAGE_UP) { if (prevRowLoc == 1) focusRow = g->grid.reg[4].row - 1; if (focusRow == g->grid.focusRow) focusRow -= 4; rowDir = -1; } else if (q == qRIGHT) { focusCol++; colDir = 1; } else if (q == qTO_BOTTOM) { focusRow = XmLArrayGetCount(g->grid.rowArray) - 1; rowDir = -1; } else if (q == qTO_BOTTOM_RIGHT) { focusCol = XmLArrayGetCount(g->grid.colArray) - 1; focusRow = XmLArrayGetCount(g->grid.rowArray) - 1; rowDir = -1; colDir = -1; } else if (q == qTO_LEFT) { focusCol = 0; colDir = 1; } else if (q == qTO_RIGHT) { focusCol = XmLArrayGetCount(g->grid.colArray) - 1; colDir = -1; } else if (q == qTO_TOP) { focusRow = 0; rowDir = 1; } else if (q == qTO_TOP_LEFT) { focusCol = 0; focusRow = 0; rowDir = 1; colDir = 1; } else if (q == qUP) { focusRow -= 1; rowDir = -1; } if (!rowDir && !colDir) return; if (extend) { if (FindNextFocus(g, focusRow, focusCol, rowDir, colDir, &focusRow, &focusCol) == -1) return; ExtendSelect(g, event, False, focusRow, focusCol); } else { if (SetFocus(g, focusRow, focusCol, rowDir, colDir) == -1) return; ExtendSelect(g, event, False, -1, -1); focusRow = g->grid.focusRow; focusCol = g->grid.focusCol; if (g->grid.selectionPolicy == XmSELECT_CELL) { SelectTypeArea(g, SelectRow, event, -1, 0, False, True); SelectTypeArea(g, SelectCol, event, 0, -1, False, True); SelectTypeArea(g, SelectCell, event, -1, -1, False, True); SelectTypeArea(g, SelectCell, event, RowPosToTypePos(g, XmCONTENT, focusRow), ColPosToTypePos(g, XmCONTENT, focusCol), True, True); } else if (g->grid.selectionPolicy == XmSELECT_BROWSE_ROW) SelectTypeArea(g, SelectRow, event, RowPosToTypePos(g, XmCONTENT, focusRow), 0, True, True); } scrollRow = -1; scrollCol = -1; if (q == qPAGE_UP) scrollRow = ScrollRowBottomPos(g, focusRow); else if (q == qPAGE_DOWN) scrollRow = focusRow; else if (q == qPAGE_LEFT) scrollCol = ScrollColRightPos(g, focusCol); else if (q == qPAGE_RIGHT) scrollCol = focusCol; else { if (focusRow < g->grid.topFixedCount) rowLoc = 0; else if (focusRow >= XmLArrayGetCount(g->grid.rowArray) - g->grid.bottomFixedCount) rowLoc = 2; else rowLoc = 1; if (prevRowLoc != 0 && rowLoc == 0) scrollRow = g->grid.reg[0].nrow; else if (prevRowLoc != 2 && rowLoc == 2) scrollRow = g->grid.reg[6].row - 1; if (focusCol < g->grid.leftFixedCount) colLoc = 0; else if (focusCol >= XmLArrayGetCount(g->grid.colArray) - g->grid.rightFixedCount) colLoc = 2; else colLoc = 1; if (prevColLoc != 0 && colLoc == 0) scrollCol = g->grid.reg[0].ncol; else if (prevColLoc != 2 && colLoc == 2) scrollCol = g->grid.reg[2].col - 1; } if (g->grid.vsPolicy == XmVARIABLE) ; else if (scrollRow != -1) { prevScrollRow = g->grid.scrollRow; g->grid.scrollRow = scrollRow; VertLayout(g, 0); if (g->grid.scrollRow != prevScrollRow) DrawArea(g, DrawVScroll, 0, 0); } else MakeRowVisible(g, focusRow); if (g->grid.hsPolicy == XmVARIABLE) ; else if (scrollCol != -1) { prevScrollCol = g->grid.scrollCol; g->grid.scrollCol = scrollCol; HorizLayout(g, 0); if (g->grid.scrollCol != prevScrollCol) DrawArea(g, DrawHScroll, 0, 0); } else MakeColVisible(g, focusCol); } static void TextActivate(Widget w, XtPointer clientData, XtPointer callData) { XmLGridWidget g; XmAnyCallbackStruct *cbs; String params[1]; Cardinal nparam; cbs = (XmAnyCallbackStruct *)callData; g = (XmLGridWidget)XtParent(w); if (g->grid.inEdit) { nparam = 0; EditComplete(w, cbs->event, params, &nparam); } else { params[0] = "ACTIVATE"; nparam = 1; Select(XtParent(w), cbs->event, params, &nparam); } } static void TextFocus(Widget w, XtPointer clientData, XtPointer callData) { XmLGridWidget g; XmAnyCallbackStruct *cbs; int focusRow, focusCol; cbs = (XmAnyCallbackStruct *)callData; g = (XmLGridWidget)XtParent(w); if (cbs->reason == XmCR_FOCUS) g->grid.focusIn = 1; else g->grid.focusIn = 0; focusRow = g->grid.focusRow; focusCol = g->grid.focusCol; if (focusRow != -1 && focusCol != -1) { if (g->grid.highlightRowMode == True) DrawArea(g, DrawRow, focusRow, 0); else DrawArea(g, DrawCell, focusRow, focusCol); } } static void TextMapped(Widget w, XtPointer clientData, XEvent *event, Boolean *con) { XmLGridWidget g; g = (XmLGridWidget)(XtParent(w)); if (event->type != MapNotify) return; if (g->grid.textHidden) XtUnmapWidget(g->grid.text); } static void TextModifyVerify(Widget w, XtPointer clientData, XtPointer callData) { XmLGridWidget g; XmTextVerifyCallbackStruct *cbs; g = (XmLGridWidget)XtParent(w); cbs = (XmTextVerifyCallbackStruct *)callData; if (!cbs->event || g->grid.ignoreModifyVerify || g->grid.inEdit) return; TextAction(g, TEXT_EDIT); if (!g->grid.inEdit) cbs->doit = False; } /* XmLGridRow */ static XmLGridRow XmLGridRowNew(Widget grid) { return XmLGridClassPartOfWidget(grid).rowNewProc(grid); } /* Only to be called through Grid class */ static XmLGridRow _GridRowNew(Widget grid) { XmLGridWidget g; XmLGridRow row; int size; g = (XmLGridWidget)grid; size = XmLGridClassPartOfWidget(grid).rowRecSize; row = (XmLGridRow)malloc(size); row->grid.grid = grid; row->grid.heightInPixels = 0; row->grid.heightInPixelsValid = 0; row->grid.height = 1; row->grid.selected = False; row->grid.sizePolicy = XmVARIABLE; row->grid.userData = 0; row->grid.cellArray = XmLArrayNew(0, 0); return row; } static void XmLGridRowFree(Widget grid, XmLGridRow row) { XmLGridClassPartOfWidget(grid).rowFreeProc(row); } /* Only to be called through Grid class */ static void _GridRowFree(XmLGridRow row) { int i, count; count = XmLArrayGetCount(row->grid.cellArray); for (i = 0; i < count; i++) XmLGridCellFree(row->grid.grid, (XmLGridCell)XmLArrayGet(row->grid.cellArray, i)); XmLArrayFree(row->grid.cellArray); free ((char *)row); } static XmLArray XmLGridRowCells(XmLGridRow row) { return row->grid.cellArray; } static int XmLGridRowGetPos(XmLGridRow row) { return row->grid.pos; } static int XmLGridRowGetVisPos(XmLGridRow row) { return row->grid.visPos; } static Boolean XmLGridRowIsHidden(XmLGridRow row) { if (!row->grid.height) return True; return False; } static Boolean XmLGridRowIsSelected(XmLGridRow row) { return row->grid.selected; } static void XmLGridRowSetSelected(XmLGridRow row, Boolean selected) { row->grid.selected = selected; } static void XmLGridRowSetVisPos(XmLGridRow row, int visPos) { row->grid.visPos = visPos; } static int XmLGridRowHeightInPixels(XmLGridRow row) { int i, count; Dimension height, maxHeight; XmLGridWidget g; XmLGridCell cell; XmLGridCallbackStruct cbs; XmLGridCellRefValues *cellValues; if (row->grid.sizePolicy == XmCONSTANT) return row->grid.height; if (!row->grid.height) return 0; if (!row->grid.heightInPixelsValid) { g = (XmLGridWidget)row->grid.grid; count = XmLArrayGetCount(row->grid.cellArray); if (!count) { cellValues = g->grid.defCellValues; maxHeight = 4 + row->grid.height * cellValues->fontHeight + cellValues->topMargin + cellValues->bottomMargin; } else maxHeight = 0; for (i = 0; i < count; i++) { cell = (XmLGridCell)XmLArrayGet(row->grid.cellArray, i); cbs.reason = XmCR_PREF_HEIGHT; cbs.rowType = RowPosToType(g, row->grid.pos); cbs.row = RowPosToTypePos(g, cbs.rowType, row->grid.pos); cbs.columnType = ColPosToType(g, i); cbs.column = ColPosToTypePos(g, cbs.columnType, i); cbs.object = (void *)row; height = XmLGridCellAction(cell, (Widget)g, &cbs); if (height > maxHeight) maxHeight = height; } row->grid.heightInPixels = maxHeight; row->grid.heightInPixelsValid = 1; } return row->grid.heightInPixels; } static void XmLGridRowHeightChanged(XmLGridRow row) { row->grid.heightInPixelsValid = 0; } /* XmLGridColumn */ static XmLGridColumn XmLGridColumnNew(Widget grid) { return XmLGridClassPartOfWidget(grid).columnNewProc(grid); } /* Only to be called through Grid class */ static XmLGridColumn _GridColumnNew(Widget grid) { XmLGridWidget g; XmLGridColumn column; int size; g = (XmLGridWidget)grid; size = XmLGridClassPartOfWidget(grid).columnRecSize; column = (XmLGridColumn)malloc(size); column->grid.grid = grid; column->grid.widthInPixels = 0; column->grid.widthInPixelsValid = 0; column->grid.defCellValues = 0; column->grid.selected = False; column->grid.sizePolicy = XmVARIABLE; column->grid.width = 8; column->grid.userData = 0; column->grid.resizable = True; column->grid.hidden = 0; return column; } static void XmLGridColumnFree(Widget grid, XmLGridColumn column) { XmLGridClassPartOfWidget(grid).columnFreeProc(column); } /* Only to be called through Grid class */ static void _GridColumnFree(XmLGridColumn column) { if (column->grid.defCellValues) XmLGridCellDerefValues(column->grid.defCellValues); free((char *)column); } static int XmLGridColumnGetPos(XmLGridColumn column) { return column->grid.pos; } static int XmLGridColumnGetVisPos(XmLGridColumn column) { return column->grid.visPos; } static Boolean XmLGridColumnIsHidden(XmLGridColumn column) { return column->grid.width == 0 || column->grid.hidden; } static Boolean XmLGridColumnIsSelected(XmLGridColumn column) { return column->grid.selected; } static void XmLGridColumnSetSelected(XmLGridColumn column, Boolean selected) { column->grid.selected = selected; } static void XmLGridColumnSetVisPos(XmLGridColumn column, int visPos) { column->grid.visPos = visPos; } static int XmLGridColumnWidthInPixels(XmLGridColumn column) { int i, count; Dimension width, maxWidth; XmLGridCell cell; XmLGridWidget g; XmLGridCallbackStruct cbs; XmLGridCellRefValues *cellValues; if (column->grid.sizePolicy == XmCONSTANT) return column->grid.width; if (!column->grid.width) return 0; if (!column->grid.widthInPixelsValid) { g = (XmLGridWidget)column->grid.grid; count = XmLArrayGetCount(g->grid.rowArray); if (!count) { cellValues = g->grid.defCellValues; maxWidth = 4 + column->grid.width * cellValues->fontWidth + cellValues->leftMargin + cellValues->rightMargin; } else maxWidth = 0; for (i = 0; i < count; i++) { cell = GetCell(g, i, column->grid.pos); cbs.reason = XmCR_PREF_WIDTH; cbs.rowType = RowPosToType(g, i); cbs.row = RowPosToTypePos(g, cbs.rowType, i); cbs.columnType = ColPosToType(g, column->grid.pos); cbs.column = ColPosToTypePos(g, cbs.columnType, column->grid.pos); cbs.object = (void *)column; width = XmLGridCellAction(cell, (Widget)g, &cbs); if (width > maxWidth) maxWidth = width; } column->grid.widthInPixels = maxWidth; column->grid.widthInPixelsValid = 1; } return column->grid.widthInPixels; } static void XmLGridColumnWidthChanged(XmLGridColumn column) { column->grid.widthInPixelsValid = 0; } /* XmLGridCell */ static XmLGridCell XmLGridCellNew(void) { XmLGridCell c; c = (XmLGridCell)malloc(sizeof(struct _XmLGridCellRec)); c->cell.refValues = 0; c->cell.flags = 0; return c; } static void XmLGridCellFree(Widget grid, XmLGridCell cell) { XmLGridCallbackStruct cbs; cbs.reason = XmCR_FREE_VALUE; XmLGridCellAction(cell, grid, &cbs); XmLGridCellDerefValues(cell->cell.refValues); free((char *)cell); } static int XmLGridCellAction(XmLGridCell cell, Widget w, XmLGridCallbackStruct *cbs) { return XmLGridClassPartOfWidget(w).cellActionProc(cell, w, cbs); } /* Only to be called through Grid class */ static int _GridCellAction(XmLGridCell cell, Widget w, XmLGridCallbackStruct *cbs) { int ret; ret = 0; switch (cbs->reason) { case XmCR_CELL_DRAW: _XmLGridCellDrawBackground(cell, w, cbs->clipRect, cbs->drawInfo); _XmLGridCellDrawValue(cell, w, cbs->clipRect, cbs->drawInfo); _XmLGridCellDrawBorders(cell, w, cbs->clipRect, cbs->drawInfo); break; case XmCR_CELL_FOCUS_IN: break; case XmCR_CELL_FOCUS_OUT: break; case XmCR_CONF_TEXT: _XmLGridCellConfigureText(cell, w, cbs->clipRect); break; case XmCR_EDIT_BEGIN: ret = _XmLGridCellBeginTextEdit(cell, w, cbs->clipRect); break; case XmCR_EDIT_CANCEL: break; case XmCR_EDIT_COMPLETE: _XmLGridCellCompleteTextEdit(cell, w); break; case XmCR_EDIT_INSERT: ret = _XmLGridCellBeginTextEdit(cell, w, cbs->clipRect); if (ret) _XmLGridCellInsertText(cell, w); break; case XmCR_FREE_VALUE: _XmLGridCellFreeValue(cell); break; case XmCR_PREF_HEIGHT: ret = _XmLGridCellGetHeight(cell, w,(XmLGridRow)cbs->object); break; case XmCR_PREF_WIDTH: ret = _XmLGridCellGetWidth(cell, w,(XmLGridColumn)cbs->object); break; } return ret; } static XmLGridCellRefValues * XmLGridCellGetRefValues(XmLGridCell cell) { return cell->cell.refValues; } static void XmLGridCellSetRefValues(XmLGridCell cell, XmLGridCellRefValues *values) { values->refCount++; XmLGridCellDerefValues(cell->cell.refValues); cell->cell.refValues = values; } static void XmLGridCellDerefValues(XmLGridCellRefValues *values) { if (!values) return; values->refCount--; if (!values->refCount) { XmFontListFree(values->fontList); free((char *)values); } } static Boolean XmLGridCellInRowSpan(XmLGridCell cell) { if (cell->cell.flags & XmLGridCellInRowSpanFlag) return True; return False; } static Boolean XmLGridCellInColumnSpan(XmLGridCell cell) { if (cell->cell.flags & XmLGridCellInColumnSpanFlag) return True; return False; } static Boolean XmLGridCellIsSelected(XmLGridCell cell) { if (cell->cell.flags & XmLGridCellSelectedFlag) return True; return False; } static Boolean XmLGridCellIsValueSet(XmLGridCell cell) { if (cell->cell.flags & XmLGridCellValueSetFlag) return True; return False; } static void XmLGridCellSetValueSet(XmLGridCell cell, Boolean set) { cell->cell.flags |= XmLGridCellValueSetFlag; if (set != True) cell->cell.flags ^= XmLGridCellValueSetFlag; } static void XmLGridCellSetInRowSpan(XmLGridCell cell, Boolean set) { cell->cell.flags |= XmLGridCellInRowSpanFlag; if (set != True) cell->cell.flags ^= XmLGridCellInRowSpanFlag; } static void XmLGridCellSetInColumnSpan(XmLGridCell cell, Boolean set) { cell->cell.flags |= XmLGridCellInColumnSpanFlag; if (set != True) cell->cell.flags ^= XmLGridCellInColumnSpanFlag; } static void XmLGridCellSetSelected(XmLGridCell cell, Boolean selected) { cell->cell.flags |= XmLGridCellSelectedFlag; if (selected != True) cell->cell.flags ^= XmLGridCellSelectedFlag; } static void XmLGridCellAllocIcon(XmLGridCell cell) { XmLGridCellIcon *icon; icon = (XmLGridCellIcon *)malloc(sizeof(XmLGridCellIcon)); icon->pix.pixmap = XmUNSPECIFIED_PIXMAP; icon->pix.pixmask = XmUNSPECIFIED_PIXMAP; icon->pix.width = 0; icon->pix.height = 0; icon->string = 0; cell->cell.value = (void *)icon; XmLGridCellSetValueSet(cell, True); } static void XmLGridCellAllocPixmap(XmLGridCell cell) { XmLGridCellPixmap *pix; pix = (XmLGridCellPixmap *)malloc(sizeof(XmLGridCellPixmap)); pix->width = 0; pix->height = 0; pix->pixmap = XmUNSPECIFIED_PIXMAP; pix->pixmask = XmUNSPECIFIED_PIXMAP; cell->cell.value = (void *)pix; XmLGridCellSetValueSet(cell, True); } static void XmLGridCellSetString(XmLGridCell cell, XmString string, Boolean copy) { XmLGridCellIcon *icon; if (cell->cell.refValues->type == XmSTRING_CELL) { _XmLGridCellFreeValue(cell); if (string) { if (copy == True) cell->cell.value = (void *)XmStringCopy(string); else cell->cell.value = (void *)string; XmLGridCellSetValueSet(cell, True); } else XmLGridCellSetValueSet(cell, False); } else if (cell->cell.refValues->type == XmICON_CELL) { if (XmLGridCellIsValueSet(cell) == False) XmLGridCellAllocIcon(cell); icon = (XmLGridCellIcon *)cell->cell.value; if (icon->string) XmStringFree(icon->string); if (string && copy == True) icon->string = XmStringCopy(string); else icon->string = string; } else if (string && copy == False) XmStringFree(string); } static XmString XmLGridCellGetString(XmLGridCell cell) { XmString str; str = 0; if (cell->cell.refValues->type == XmSTRING_CELL) { if (XmLGridCellIsValueSet(cell) == True) str = (XmString)cell->cell.value; } else if (cell->cell.refValues->type == XmICON_CELL) { if (XmLGridCellIsValueSet(cell) == True) str = ((XmLGridCellIcon *)cell->cell.value)->string; } return str; } static void XmLGridCellSetToggle(XmLGridCell cell, Boolean state) { if (cell->cell.refValues->type == XmTOGGLE_CELL) { if (state) cell->cell.value = (void *)1; else cell->cell.value = (void *)0; XmLGridCellSetValueSet(cell, True); } } static Boolean XmLGridCellGetToggle(XmLGridCell cell) { Boolean toggled; toggled = False; if (cell->cell.refValues->type == XmTOGGLE_CELL) { if (XmLGridCellIsValueSet(cell) == True && cell->cell.value == (void *)1) toggled = True; } return toggled; } static void XmLGridCellSetPixmap(XmLGridCell cell, Pixmap pixmap, Dimension width, Dimension height) { XmLGridCellPixmap *pix; pix = 0; if (cell->cell.refValues->type == XmPIXMAP_CELL) { if (XmLGridCellIsValueSet(cell) == False) XmLGridCellAllocPixmap(cell); pix = (XmLGridCellPixmap *)cell->cell.value; } else if (cell->cell.refValues->type == XmICON_CELL) { if (XmLGridCellIsValueSet(cell) == False) XmLGridCellAllocIcon(cell); pix = &((XmLGridCellIcon *)cell->cell.value)->pix; } if (!pix) return; pix->pixmap = pixmap; pix->height = height; pix->width = width; } static void XmLGridCellSetPixmask(XmLGridCell cell, Pixmap pixmask) { XmLGridCellPixmap *pix; if (XmLGridCellIsValueSet(cell) == False) { fprintf(stderr, "XmLGridCellSetPixmask: pixmap must be set "); fprintf(stderr, "before pixmask\n"); return; } pix = 0; if (cell->cell.refValues->type == XmPIXMAP_CELL) pix = (XmLGridCellPixmap *)cell->cell.value; else if (cell->cell.refValues->type == XmICON_CELL) pix = &((XmLGridCellIcon *)cell->cell.value)->pix; if (!pix) return; pix->pixmask = pixmask; } static XmLGridCellPixmap * XmLGridCellGetPixmap(XmLGridCell cell) { XmLGridCellPixmap *pix; pix = 0; if (cell->cell.refValues->type == XmPIXMAP_CELL) { if (XmLGridCellIsValueSet(cell) == True) pix = (XmLGridCellPixmap *)cell->cell.value; } else if (cell->cell.refValues->type == XmICON_CELL) { if (XmLGridCellIsValueSet(cell) == True) pix = &((XmLGridCellIcon *)cell->cell.value)->pix; } return pix; } /* Only to be called by XmLGridCellAction() */ void _XmLGridCellDrawBackground(XmLGridCell cell, Widget w, XRectangle *clipRect, XmLGridDrawStruct *ds) { Display *dpy; Window win; dpy = XtDisplay(w); win = XtWindow(w); if (ds->drawSelected == True) XSetForeground(dpy, ds->gc, ds->selectBackground); else XSetForeground(dpy, ds->gc, ds->background); XFillRectangle(dpy, win, ds->gc, clipRect->x, clipRect->y, clipRect->width, clipRect->height); } /* Only to be called by XmLGridCellAction() */ void _XmLGridCellDrawBorders(XmLGridCell cell, Widget w, XRectangle *clipRect, XmLGridDrawStruct *ds) { XmLGridWidget g; Display *dpy; Window win; GC gc; Pixel black, white; int x1, x2, y1, y2, loff, roff; int drawLeft, drawRight, drawBot, drawTop; XRectangle *cellRect; unsigned char borderType; g = (XmLGridWidget)w; dpy = XtDisplay(w); win = XtWindow(w); gc = ds->gc; cellRect = ds->cellRect; black = BlackPixelOfScreen(XtScreen(w)); white = WhitePixelOfScreen(XtScreen(w)); x1 = clipRect->x; x2 = clipRect->x + clipRect->width - 1; y1 = clipRect->y; y2 = clipRect->y + clipRect->height - 1; drawLeft = 1; drawRight = 1; drawBot = 1; drawTop = 1; if (cellRect->x != clipRect->x) drawLeft = 0; if (cellRect->x + cellRect->width != clipRect->x + clipRect->width) drawRight = 0; if (cellRect->y != clipRect->y) drawTop = 0; if (cellRect->y + cellRect->height != clipRect->y + clipRect->height) drawBot = 0; borderType = cell->cell.refValues->rightBorderType; if (borderType != XmBORDER_NONE && drawRight) { if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter); XSetForeground(dpy, gc, cell->cell.refValues->rightBorderColor); XDrawLine(dpy, win, gc, x2, y1, x2, y2); if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter); } borderType = cell->cell.refValues->bottomBorderType; if (borderType != XmBORDER_NONE && drawBot) { if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter); XSetForeground(dpy, gc, cell->cell.refValues->bottomBorderColor); XDrawLine(dpy, win, gc, x1, y2, x2, y2); if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter); } borderType = cell->cell.refValues->topBorderType; if (borderType != XmBORDER_NONE && drawTop) { if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter); XSetForeground(dpy, gc, cell->cell.refValues->topBorderColor); XDrawLine(dpy, win, gc, x1, y1, x2, y1); if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter); } borderType = cell->cell.refValues->leftBorderType; if (borderType != XmBORDER_NONE && drawLeft) { if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineOnOffDash, CapButt, JoinMiter); XSetForeground(dpy, gc, cell->cell.refValues->leftBorderColor); XDrawLine(dpy, win, gc, x1, y1, x1, y2); if (borderType == XmBORDER_DASH) XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinMiter); } if (ds->drawFocusType == XmDRAW_FOCUS_NONE) return; if (ds->drawFocusType == XmDRAW_FOCUS_LEFT) drawRight = 0; else if (ds->drawFocusType == XmDRAW_FOCUS_RIGHT) drawLeft = 0; else if (ds->drawFocusType == XmDRAW_FOCUS_MID) { drawLeft = 0; drawRight = 0; } if (!drawLeft) loff = 0; else loff = 2; if (!drawRight) roff = 0; else roff = 2; if (g->grid.highlightThickness < 2) return; XSetForeground(dpy, gc, g->manager.highlight_color); if (drawTop) XDrawLine(dpy, win, gc, x1, y1, x2, y1); if (drawLeft) XDrawLine(dpy, win, gc, x1, y1 + 2, x1, y2); if (drawRight) XDrawLine(dpy, win, gc, x2, y1 + 2, x2, y2); if (drawBot) XDrawLine(dpy, win, gc, x1 + loff, y2, x2 - roff, y2); if (drawTop && clipRect->height > 1) XDrawLine(dpy, win, gc, x1, y1 + 1, x2, y1 + 1); if (drawBot && (int)clipRect->height > 1 && (int)clipRect->width > roff && (int)clipRect->width > loff) XDrawLine(dpy, win, gc, x1 + loff, y2 - 1, x2 - roff, y2 - 1); if (clipRect->width > 1 && clipRect->height > 2) { if (drawLeft) XDrawLine(dpy, win, gc, x1 + 1, y1 + 2, x1 + 1, y2); if (drawRight) XDrawLine(dpy, win, gc, x2 - 1, y1 + 2, x2 - 1, y2); } } /* Only to be called by XmLGridCellAction() */ void _XmLGridCellDrawValue(XmLGridCell cell, Widget w, XRectangle *clipRect, XmLGridDrawStruct *ds) { XmLGridWidget g; Display *dpy; XmLGridCellPixmap *pix; XmLGridCellIcon *icon; XRectangle cellRect; XmLGridCellRefValues *cellValues; int type, horizMargin, vertMargin, xoff; g = (XmLGridWidget)w; cellRect = *ds->cellRect; cellValues = cell->cell.refValues; horizMargin = ds->leftMargin + ds->rightMargin; vertMargin = ds->topMargin + ds->bottomMargin; if (horizMargin >= (int)cellRect.width || vertMargin >= (int)cellRect.height) return; type = cellValues->type; cellRect.x += ds->leftMargin; cellRect.y += ds->topMargin; cellRect.width -= horizMargin; cellRect.height -= vertMargin; dpy = XtDisplay(w); if (type == XmSTRING_CELL && XmLGridCellIsValueSet(cell) == True) { if (ds->drawSelected == True) XSetForeground(dpy, ds->gc, ds->selectForeground); else XSetForeground(dpy, ds->gc, ds->foreground); XmLStringDraw(w, (XmString)cell->cell.value, ds->stringDirection, ds->fontList, ds->alignment, ds->gc, &cellRect, clipRect); } if (type == XmPIXMAP_CELL && XmLGridCellIsValueSet(cell) == True) { pix = (XmLGridCellPixmap *)cell->cell.value; XmLPixmapDraw(w, pix->pixmap, pix->pixmask, pix->width, pix->height, ds->alignment, ds->gc, &cellRect, clipRect); } if (type == XmICON_CELL && XmLGridCellIsValueSet(cell) == True) { icon = (XmLGridCellIcon *)cell->cell.value; if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP) { XmLPixmapDraw(w, icon->pix.pixmap, icon->pix.pixmask, icon->pix.width, icon->pix.height, ds->alignment, ds->gc, &cellRect, clipRect); xoff = icon->pix.width + g->grid.iconSpacing; cellRect.x += xoff; if (xoff < (int)cellRect.width) cellRect.width -= xoff; else cellRect.width = 0; } if (cellRect.width && icon->string) { if (ds->drawSelected == True) XSetForeground(dpy, ds->gc, ds->selectForeground); else XSetForeground(dpy, ds->gc, ds->foreground); XmLStringDraw(w, icon->string, ds->stringDirection, ds->fontList, ds->alignment, ds->gc, &cellRect, clipRect); } } if (type == XmTOGGLE_CELL) XmLDrawToggle(w, XmLGridCellGetToggle(cell), g->grid.toggleSize, ds->alignment, ds->gc, ds->background, g->grid.toggleTopColor, g->grid.toggleBotColor, ds->foreground, &cellRect, clipRect); } /* Only to be called by XmLGridCellAction() */ static int _XmLGridCellConfigureText(XmLGridCell cell, Widget w, XRectangle *rect) { XmLGridWidget g; g = (XmLGridWidget)w; XtConfigureWidget(g->grid.text, rect->x, rect->y, rect->width, rect->height, 0); return(0); } /* Only to be called by XmLGridCellAction() */ static int _XmLGridCellBeginTextEdit(XmLGridCell cell, Widget w, XRectangle *clipRect) { XmLGridWidget g = (XmLGridWidget)w; Widget text; if ((cell->cell.refValues->type != XmSTRING_CELL && cell->cell.refValues->type != XmICON_CELL) || cell->cell.refValues->editable != True || g->grid.useTextWidget != True) return 0; XtVaGetValues(w, XmNtextWidget, &text, NULL); XtVaSetValues(text, XmNfontList, cell->cell.refValues->fontList, NULL); return 1; } /* Only to be called by XmLGridCellAction() */ static void _XmLGridCellCompleteTextEdit(XmLGridCell cell, Widget w) { XmLGridWidget g = (XmLGridWidget)w; Widget text; char *s; int i, len; if ((cell->cell.refValues->type != XmSTRING_CELL && cell->cell.refValues->type != XmICON_CELL) || cell->cell.refValues->editable != True || g->grid.useTextWidget != True) return; XtVaGetValues(w, XmNtextWidget, &text, NULL); s = XmTextGetString(text); len = strlen(s); for (i = 0; i < len - 1; i++) if (s[i] == '\\' && s[i + 1] == 'n') { s[i] = '\n'; strcpy(&s[i + 1], &s[i + 2]); } XmLGridCellSetString(cell, XmStringCreateLtoR(s, XmSTRING_DEFAULT_CHARSET), False); #if 0 if (XmLGridCellIsValueSet(cell) == True) XmStringFree((XmString)cell->cell.value); if (strlen(s)) { cell->cell.value = (void *)XmStringCreateLtoR(s, XmSTRING_DEFAULT_CHARSET); XmLGridCellSetValueSet(cell, True); } else XmLGridCellSetValueSet(cell, False); #endif /*0*/ XtFree(s); } /* Only to be called by XmLGridCellAction() */ static void _XmLGridCellInsertText(XmLGridCell cell, Widget w) { XmLGridWidget g = (XmLGridWidget)w; char *s; Widget text = NULL; if ((cell->cell.refValues->type != XmSTRING_CELL && cell->cell.refValues->type != XmICON_CELL) || cell->cell.refValues->editable != True || g->grid.useTextWidget != True) return; XtVaGetValues(w, XmNtextWidget, &text, NULL); s = 0; if (XmLGridCellIsValueSet(cell) == True) s = CvtXmStringToStr(XmLGridCellGetString(cell)); if (s) { XmTextSetString(text, s); free(s); } else XmTextSetString(text, ""); XmTextSetInsertionPosition(text, XmTextGetLastPosition(text)); XmProcessTraversal(text, XmTRAVERSE_CURRENT); } /* Only to be called by XmLGridCellAction() */ static int _XmLGridCellGetHeight(XmLGridCell cell, Widget w, XmLGridRow row) { XmLGridCellPixmap *pix; XmLGridCellIcon *icon; XmLGridCellRefValues *cellValues; int height, pixHeight; cellValues = cell->cell.refValues; height = -1; if (cellValues->type == XmPIXMAP_CELL) { if (XmLGridCellIsValueSet(cell) == True) { pix = (XmLGridCellPixmap *)cell->cell.value; if (pix->height) height = 4 + pix->height + cellValues->topMargin + cellValues->bottomMargin; } } else if (cellValues->type == XmICON_CELL) { pixHeight = 0; if (XmLGridCellIsValueSet(cell) == True) { icon = (XmLGridCellIcon *)cell->cell.value; if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP && icon->pix.height) pixHeight = 4 + icon->pix.height + cellValues->topMargin + cellValues->bottomMargin; } height = 4 + row->grid.height * cellValues->fontHeight + cellValues->topMargin + cellValues->bottomMargin; if (pixHeight > height) height = pixHeight; } else if (cellValues->type == XmTOGGLE_CELL) height = 4 + 16 + cellValues->topMargin + cellValues->bottomMargin; else if (cellValues->type == XmSTRING_CELL) { height = 4 + row->grid.height * cellValues->fontHeight + cellValues->topMargin + cellValues->bottomMargin; } if (height < 0 || cellValues->rowSpan) height = 4; return height; } /* Only to be called by XmLGridCellAction() */ static int _XmLGridCellGetWidth(XmLGridCell cell, Widget w, XmLGridColumn col) { XmLGridWidget g = (XmLGridWidget)w; XmLGridCellPixmap *pix; XmLGridCellIcon *icon; XmLGridCellRefValues *cellValues; int width; cellValues = cell->cell.refValues; width = -1; if (cellValues->type == XmPIXMAP_CELL) { if (XmLGridCellIsValueSet(cell) == True) { pix = (XmLGridCellPixmap *)cell->cell.value; if (pix->width) width = 4 + pix->width + cellValues->leftMargin + cellValues->rightMargin; } } else if (cellValues->type == XmICON_CELL) { width = 4 + col->grid.width * cellValues->fontWidth + cellValues->leftMargin + cellValues->rightMargin; if (XmLGridCellIsValueSet(cell) == True) { icon = (XmLGridCellIcon *)cell->cell.value; if (icon->pix.pixmap != XmUNSPECIFIED_PIXMAP && icon->pix.width) width += icon->pix.width + g->grid.iconSpacing; } } else if (cellValues->type == XmTOGGLE_CELL) width = 4 + 16 + cellValues->leftMargin + cellValues->rightMargin; else if (cellValues->type == XmSTRING_CELL) width = 4 + col->grid.width * cellValues->fontWidth + cellValues->leftMargin + cellValues->rightMargin; if (width < 0 || cellValues->columnSpan) width = 4; return width; } /* Only to be called by XmLGridCellAction() */ static void _XmLGridCellFreeValue(XmLGridCell cell) { int type; XmLGridCellIcon *icon; if (XmLGridCellIsValueSet(cell) == False) return; type = cell->cell.refValues->type; if (type == XmSTRING_CELL) XmStringFree((XmString)cell->cell.value); else if (type == XmPIXMAP_CELL) free((char *)cell->cell.value); else if (type == XmICON_CELL) { icon = (XmLGridCellIcon *)cell->cell.value; if (icon->string) XmStringFree(icon->string); free((char *)icon); } XmLGridCellSetValueSet(cell, False); } /* Public Functions */ Widget XmLCreateGrid(Widget parent, char *name, ArgList arglist, Cardinal argcount) { return XtCreateWidget(name, xmlGridWidgetClass, parent, arglist, argcount); } void XmLGridAddColumns(Widget w, unsigned char type, int position, int count) { XmLGridWidget g; XmLGridColumn col; XmLGridRow row; XmLGridCell cell; XmLGridCallbackStruct cbs; int i, j, rowCount, hasAddCB, redraw; g = WidgetToGrid(w, "AddColumns()"); if (!g) return; if (count <= 0) return; redraw = 0; position = ColTypePosToPos(g, type, position, 1); if (position < 0) position = ColTypePosToPos(g, type, -1, 1); /* adjust count */ if (type == XmHEADING) { g->grid.headingColCount += count; g->grid.leftFixedCount += count; redraw = 1; } else if (type == XmFOOTER) { g->grid.footerColCount += count; g->grid.rightFixedCount += count; redraw = 1; } else /* XmCONTENT */ g->grid.colCount += count; hasAddCB = 0; if (XtHasCallbacks(w, XmNaddCallback) == XtCallbackHasSome) hasAddCB = 1; /* add columns */ XmLArrayAdd(g->grid.colArray, position, count); for (i = 0; i < count; i++) { col = 0; if (hasAddCB) { cbs.reason = XmCR_ADD_COLUMN; cbs.columnType = type; cbs.object = 0; XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs); col = (XmLGridColumn)cbs.object; } if (!col) col = XmLGridColumnNew(w); XmLArraySet(g->grid.colArray, position + i, col); } /* add cells */ rowCount = XmLArrayGetCount(g->grid.rowArray); for (j = 0; j < rowCount; j++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, j); XmLArrayAdd(XmLGridRowCells(row), position, count); for (i = position; i < position + count; i++) { cell = 0; if (hasAddCB) { cbs.reason = XmCR_ADD_CELL; cbs.rowType = RowPosToType(g, j); cbs.columnType = type; cbs.object = 0; XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs); cell = (XmLGridCell)cbs.object; } if (!cell) cell = XmLGridCellNew(); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); if (col->grid.defCellValues) XmLGridCellSetRefValues(cell, col->grid.defCellValues); else XmLGridCellSetRefValues(cell, g->grid.defCellValues); XmLArraySet(XmLGridRowCells(row), i, cell); } XmLGridRowHeightChanged(row); } for (i = position; i < position + count; i++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); XmLGridColumnWidthChanged(col); } /* sanity check */ if (XmLArrayGetCount(g->grid.colArray) != g->grid.headingColCount + g->grid.colCount + g->grid.footerColCount) XmLWarning(w, "AddColumns() - count sanity check failed"); /* maintain scroll and focus position */ if (g->grid.hsPolicy == XmCONSTANT) { if (type == XmCONTENT && g->grid.colCount == count) g->grid.scrollCol = 0; else if (position <= g->grid.scrollCol) g->grid.scrollCol += count; } if (position <= g->grid.focusCol) g->grid.focusCol += count; VisPosChanged(g, 0); HorizLayout(g, 1); VertLayout(g, 1); if (g->grid.focusCol == -1 && type == XmCONTENT) { if (g->grid.focusRow != -1) SetFocus(g, g->grid.focusRow, position, 0, 0); else g->grid.focusCol = position; } for (i = position; i < position + count; i++) redraw |= ColIsVisible(g, i); if (redraw) DrawArea(g, DrawAll, 0, 0); } void XmLGridAddRows(Widget w, unsigned char type, int position, int count) { XmLGridWidget g; XmLGridRow row; XmLGridColumn col; XmLGridCell cell; XmLGridCallbackStruct cbs; int i, j, hasAddCB, redraw, colCount; g = WidgetToGrid(w, "AddRows()"); if (!g) return; if (count <= 0) return; redraw = 0; position = RowTypePosToPos(g, type, position, 1); if (position < 0) position = RowTypePosToPos(g, type, -1, 1); /* adjust count */ if (type == XmHEADING) { g->grid.headingRowCount += count; g->grid.topFixedCount += count; redraw = 1; } else if (type == XmFOOTER) { g->grid.footerRowCount += count; g->grid.bottomFixedCount += count; redraw = 1; } else /* XmCONTENT */ g->grid.rowCount += count; /* add rows and cells */ XmLArrayAdd(g->grid.rowArray, position, count); colCount = XmLArrayGetCount(g->grid.colArray); hasAddCB = 0; if (XtHasCallbacks(w, XmNaddCallback) == XtCallbackHasSome) hasAddCB = 1; for (i = 0; i < count; i++) { row = 0; if (hasAddCB) { cbs.reason = XmCR_ADD_ROW; cbs.rowType = type; cbs.object = 0; XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs); row = (XmLGridRow)cbs.object; } if (!row) row = XmLGridRowNew(w); XmLArraySet(g->grid.rowArray, position + i, row); XmLArrayAdd(XmLGridRowCells(row), 0, colCount); for (j = 0; j < colCount; j++) { cell = 0; if (hasAddCB) { cbs.reason = XmCR_ADD_CELL; cbs.rowType = type; cbs.columnType = ColPosToType(g, j); cbs.object = 0; XtCallCallbackList(w, g->grid.addCallback, (XtPointer)&cbs); cell = (XmLGridCell)cbs.object; } if (!cell) cell = XmLGridCellNew(); col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, j); if (col->grid.defCellValues) XmLGridCellSetRefValues(cell, col->grid.defCellValues); else XmLGridCellSetRefValues(cell, g->grid.defCellValues); XmLArraySet(XmLGridRowCells(row), j, cell); } XmLGridRowHeightChanged(row); } for (j = 0; j < colCount; j++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, j); XmLGridColumnWidthChanged(col); } /* sanity check */ if (XmLArrayGetCount(g->grid.rowArray) != g->grid.headingRowCount + g->grid.rowCount + g->grid.footerRowCount) XmLWarning(w, "AddRows() - count sanity check failed"); /* maintain scroll and focus position */ if (g->grid.vsPolicy == XmCONSTANT) { if (type == XmCONTENT && g->grid.rowCount == count) g->grid.scrollRow = 0; else if (position <= g->grid.scrollRow) g->grid.scrollRow += count; } if (position <= g->grid.focusRow) g->grid.focusRow += count; VisPosChanged(g, 1); HorizLayout(g, 1); VertLayout(g, 1); if (g->grid.focusRow == -1 && type == XmCONTENT) { if (g->grid.focusCol != -1) SetFocus(g, position, g->grid.focusCol, 0, 0); else g->grid.focusRow = position; } for (i = position; i < position + count; i++) redraw |= RowIsVisible(g, i); if (redraw) DrawArea(g, DrawAll, 0, 0); #ifdef XmLEVAL if (g->grid.rowCount > 100) { fprintf(stderr, "XmL: evaluation version only supports <= 100 rows\n"); exit(0); } #endif } void XmLGridDeleteAllColumns(Widget w, unsigned char type) { XmLGridWidget g; int n; g = WidgetToGrid(w, "DeleteAllColumns()"); if (!g) return; if (type == XmHEADING) n = g->grid.headingColCount; else if (type == XmCONTENT) n = g->grid.colCount; else if (type == XmFOOTER) n = g->grid.footerColCount; else { XmLWarning(w, "DeleteAllColumns() - invalid type"); return; } if (!n) return; XmLGridDeleteColumns(w, type, 0, n); } void XmLGridDeleteAllRows(Widget w, unsigned char type) { XmLGridWidget g; int n; g = WidgetToGrid(w, "DeleteAllRows()"); if (!g) return; if (type == XmHEADING) n = g->grid.headingRowCount; else if (type == XmCONTENT) n = g->grid.rowCount; else if (type == XmFOOTER) n = g->grid.footerRowCount; else { XmLWarning(w, "DeleteAllRows() - invalid type"); return; } if (!n) return; XmLGridDeleteRows(w, type, 0, n); } void XmLGridDeselectAllRows(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectAllRows()"); if (!g) return; SelectTypeArea(g, SelectRow, (XEvent *)0, -1, 0, False, notify); } void XmLGridDeselectAllColumns(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectAllColumns()"); if (!g) return; SelectTypeArea(g, SelectCol, (XEvent *)0, 0, -1, False, notify); } void XmLGridDeselectAllCells(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectAllCells()"); if (!g) return; SelectTypeArea(g, SelectCell, (XEvent *)0, -1, -1, False, notify); } void XmLGridDeselectCell(Widget w, int row, int column, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectCell()"); if (!g) return; SelectTypeArea(g, SelectCell, (XEvent *)0, row, column, False, notify); } void XmLGridDeselectColumn(Widget w, int column, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectColumn()"); if (!g) return; SelectTypeArea(g, SelectCol, (XEvent *)0, 0, column, False, notify); } void XmLGridDeselectRow(Widget w, int row, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "DeselectRow()"); if (!g) return; SelectTypeArea(g, SelectRow, (XEvent *)0, row, 0, False, notify); } void XmLGridDeleteColumns(Widget w, unsigned char type, int position, int count) { XmLGridWidget g; XmLGridRow row; XmLGridColumn col; XmLGridCallbackStruct cbs; int changeFocus, i, j, rowCount, lastPos, redraw; g = WidgetToGrid(w, "DeleteColumns()"); if (!g) return; if (count <= 0) return; lastPos = ColTypePosToPos(g, type, position + count - 1, 0); position = ColTypePosToPos(g, type, position, 0); if (position < 0 || lastPos < 0) { XmLWarning(w, "DeleteColumns() - invalid position"); return; } changeFocus = 0; if (position <= g->grid.focusCol && lastPos >= g->grid.focusCol) { /* deleting focus col */ TextAction(g, TEXT_EDIT_CANCEL); ChangeFocus(g, g->grid.focusRow, -1); changeFocus = 1; } redraw = 0; if (XtHasCallbacks(w, XmNdeleteCallback) == XtCallbackHasSome) for (i = position; i < position + count; i++) { rowCount = XmLArrayGetCount(g->grid.rowArray); for (j = 0; j < rowCount; j++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, j); cbs.reason = XmCR_DELETE_CELL; cbs.rowType = RowPosToType(g, j); cbs.row = RowPosToTypePos(g, cbs.rowType, i); cbs.columnType = type; cbs.column = RowPosToTypePos(g, cbs.columnType, j); cbs.object = XmLArrayGet(XmLGridRowCells(row), i); XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs); } cbs.reason = XmCR_DELETE_COLUMN; cbs.columnType = type; cbs.column = RowPosToTypePos(g, cbs.columnType, i); cbs.object = XmLArrayGet(g->grid.colArray, i); XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs); } /* adjust count */ if (type == XmHEADING) { g->grid.headingColCount -= count; g->grid.leftFixedCount -= count; redraw = 1; } else if (type == XmFOOTER) { g->grid.footerColCount -= count; g->grid.rightFixedCount -= count; redraw = 1; } else /* XmCONTENT */ g->grid.colCount -= count; for (i = position; i < position + count; i++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); if (XmLGridColumnIsHidden(col) == True) g->grid.hiddenColCount--; redraw |= ColIsVisible(g, i); } /* delete columns */ for (i = position; i < position + count; i++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); XmLGridColumnFree(w, col); } XmLArrayDel(g->grid.colArray, position, count); /* delete cells */ rowCount = XmLArrayGetCount(g->grid.rowArray); for (i = 0; i < rowCount; i++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i); for (j = position; j < position + count; j++) XmLGridCellFree(w, (XmLGridCell)XmLArrayGet(XmLGridRowCells(row), j)); XmLArrayDel(XmLGridRowCells(row), position, count); XmLGridRowHeightChanged(row); } /* sanity check */ if (XmLArrayGetCount(g->grid.colArray) != g->grid.headingColCount + g->grid.colCount + g->grid.footerColCount) XmLWarning(w, "DeleteColumns() - count sanity check failed"); /* maintain scroll and focus position */ if (g->grid.hsPolicy == XmCONSTANT) { if (lastPos < g->grid.scrollCol) g->grid.scrollCol -= count; else if (position <= g->grid.scrollCol) g->grid.scrollCol = position; } if (lastPos < g->grid.focusCol) g->grid.focusCol -= count; VisPosChanged(g, 0); HorizLayout(g, 1); VertLayout(g, 1); if (changeFocus) { SetFocus(g, g->grid.focusRow, position, 0, 1); if (g->grid.focusCol == -1) SetFocus(g, g->grid.focusRow, position, 0, -1); } if (redraw) DrawArea(g, DrawAll, 0, 0); } void XmLGridDeleteRows(Widget w, unsigned char type, int position, int count) { XmLGridWidget g; XmLGridRow row; XmLGridColumn col; XmLGridCallbackStruct cbs; int changeFocus, i, j, colCount, lastPos, redraw; g = WidgetToGrid(w, "DeleteRows()"); if (!g) return; if (count <= 0) return; lastPos = RowTypePosToPos(g, type, position + count - 1, 0); position = RowTypePosToPos(g, type, position, 0); if (position < 0 || lastPos < 0) { XmLWarning(w, "DeleteRows() - invalid position"); return; } changeFocus = 0; if (position <= g->grid.focusRow && lastPos >= g->grid.focusRow) { /* deleting focus row */ TextAction(g, TEXT_EDIT_CANCEL); ChangeFocus(g, -1, g->grid.focusCol); changeFocus = 1; } redraw = 0; if (XtHasCallbacks(w, XmNdeleteCallback) == XtCallbackHasSome) for (i = position; i < position + count; i++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i); colCount = XmLArrayGetCount(g->grid.colArray); for (j = 0; j < colCount; j++) { cbs.reason = XmCR_DELETE_CELL; cbs.rowType = type; cbs.row = RowPosToTypePos(g, cbs.rowType, i); cbs.columnType = ColPosToType(g, j); cbs.column = ColPosToTypePos(g, cbs.columnType, j); cbs.object = XmLArrayGet(XmLGridRowCells(row), j); XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs); } cbs.reason = XmCR_DELETE_ROW; cbs.rowType = type; cbs.row = RowPosToTypePos(g, cbs.rowType, i); cbs.object = (void *)row; XtCallCallbackList(w, g->grid.deleteCallback, (XtPointer)&cbs); } /* adjust count */ if (type == XmHEADING) { g->grid.headingRowCount -= count; g->grid.topFixedCount -= count; redraw = 1; } else if (type == XmFOOTER) { g->grid.footerRowCount -= count; g->grid.bottomFixedCount -= count; redraw = 1; } else /* XmCONTENT */ g->grid.rowCount -= count; for (i = position; i < position + count; i++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i); if (XmLGridRowIsHidden(row) == True) g->grid.hiddenRowCount--; redraw |= RowIsVisible(g, i); } /* delete rows and cells */ for (i = position; i < position + count; i++) { row = (XmLGridRow)XmLArrayGet(g->grid.rowArray, i); XmLGridRowFree(w, row); } XmLArrayDel(g->grid.rowArray, position, count); colCount = XmLArrayGetCount(g->grid.colArray); for (i = 0; i < colCount; i++) { col = (XmLGridColumn)XmLArrayGet(g->grid.colArray, i); XmLGridColumnWidthChanged(col); } /* sanity check */ if (XmLArrayGetCount(g->grid.rowArray) != g->grid.headingRowCount + g->grid.rowCount + g->grid.footerRowCount) XmLWarning(w, "DeleteRows() - count sanity check failed"); /* maintain scroll and focus position */ if (g->grid.vsPolicy == XmCONSTANT) { if (lastPos < g->grid.scrollRow) g->grid.scrollRow -= count; else if (position <= g->grid.scrollRow) g->grid.scrollRow = position; } if (lastPos < g->grid.focusRow) g->grid.focusRow -= count; VisPosChanged(g, 1); HorizLayout(g, 1); VertLayout(g, 1); if (changeFocus) { SetFocus(g, position, g->grid.focusCol, 1, 0); if (g->grid.focusRow == -1) SetFocus(g, position, g->grid.focusCol, -1, 0); } if (redraw) DrawArea(g, DrawAll, 0, 0); } void XmLGridGetFocus(Widget w, int *row, int *column, Boolean *focusIn) { XmLGridWidget g; unsigned char rowType, colType; g = WidgetToGrid(w, "GetFocus()"); if (!g) return; if (g->grid.focusIn) *focusIn = True; else *focusIn = False; if (g->grid.focusRow < 0 || g->grid.focusCol < 0) { *row = -1; *column = -1; return; } rowType = RowPosToType(g, g->grid.focusRow); colType = ColPosToType(g, g->grid.focusCol); if (rowType != XmCONTENT || colType != XmCONTENT) { *row = -1; *column = -1; XmLWarning(w, "GetFocus() - focus row/column invalid\n"); return; } *row = RowPosToTypePos(g, XmCONTENT, g->grid.focusRow); *column = ColPosToTypePos(g, XmCONTENT, g->grid.focusCol); } XmLGridRow XmLGridGetRow(Widget w, unsigned char rowType, int row) { XmLGridWidget g; XmLGridRow r; int pos; g = WidgetToGrid(w, "GetRow()"); if (!g) return 0; pos = RowTypePosToPos(g, rowType, row, 0); r = (XmLGridRow)XmLArrayGet(g->grid.rowArray, pos); if (!r) XmLWarning(w, "GetRow() - invalid row"); return r; } int XmLGridEditBegin(Widget w, Boolean insert, int row, int column) { XmLGridWidget g; int r, c; XRectangle rect; g = WidgetToGrid(w, "EditBegin()"); if (!g) return -1; if (column < 0 || column >= g->grid.colCount) { XmLWarning(w, "EditBegin() - invalid column"); return -1; } if (row < 0 || row >= g->grid.rowCount) { XmLWarning(w, "EditBegin() - invalid row"); return -1; } r = RowTypePosToPos(g, XmCONTENT, row, 0); c = ColTypePosToPos(g, XmCONTENT, column, 0); if (RowColToXY(g, r, c, True, &rect) == -1) { XmLWarning(w, "EditBegin() - cell must be visible to begin edit"); return -1; } if (SetFocus(g, r, c, 0, 0) == -1) { XmLWarning(w, "EditBegin() - can't set focus to cell"); return -1; } if (insert == False) TextAction(g, TEXT_EDIT); else TextAction(g, TEXT_EDIT_INSERT); return 0; } void XmLGridEditCancel(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "EditCancel()"); if (!g) return; TextAction(g, TEXT_EDIT_CANCEL); } void XmLGridEditComplete(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "EditComplete()"); if (!g) return; TextAction(g, TEXT_EDIT_COMPLETE); } XmLGridColumn XmLGridGetColumn(Widget w, unsigned char columnType, int column) { XmLGridWidget g; XmLGridColumn c; int pos; g = WidgetToGrid(w, "GetColumn()"); if (!g) return 0; pos = ColTypePosToPos(g, columnType, column, 0); c = (XmLGridColumn)XmLArrayGet(g->grid.colArray, pos); if (!c) XmLWarning(w, "GetColumn() - invalid column"); return c; } int XmLGridGetSelectedCellCount(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "GetSelectedCellCount()"); if (!g) return -1; return GetSelectedArea(g, SelectCell, 0, 0, 0); } int XmLGridGetSelectedCells(Widget w, int *rowPositions, int *columnPositions, int count) { XmLGridWidget g; int n; g = WidgetToGrid(w, "GetSelectedCells()"); if (!g) return -1; n = GetSelectedArea(g, SelectCell, rowPositions, columnPositions, count); if (count != n) { XmLWarning(w, "GetSelectedCells() - count is incorrect"); return -1; } return 0; } int XmLGridGetSelectedColumnCount(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "GetSelectedColumnCount()"); if (!g) return -1; return GetSelectedArea(g, SelectCol, 0, 0, 0); } int XmLGridGetSelectedColumns(Widget w, int *positions, int count) { XmLGridWidget g; int n; g = WidgetToGrid(w, "GetSelectedColumns()"); if (!g) return -1; n = GetSelectedArea(g, SelectCol, 0, positions, count); if (count != n) { XmLWarning(w, "GetSelectedColumns() - count is incorrect"); return -1; } return 0; } int XmLGridGetSelectedRow(Widget w) { XmLGridWidget g; int n, pos; g = WidgetToGrid(w, "GetSelectedRow()"); if (!g) return -1; n = GetSelectedArea(g, SelectRow, &pos, 0, 1); if (n != 1) return -1; return pos; } int XmLGridGetSelectedRowCount(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "GetSelectedRowCount()"); if (!g) return -1; return GetSelectedArea(g, SelectRow, 0, 0, 0); } int XmLGridGetSelectedRows(Widget w, int *positions, int count) { XmLGridWidget g; int n; g = WidgetToGrid(w, "GetSelectedRows()"); if (!g) return -1; n = GetSelectedArea(g, SelectRow, positions, 0, count); if (count != n) { XmLWarning(w, "GetSelectedRows() - count is incorrect"); return -1; } return 0; } Boolean XmLGridColumnIsVisible(Widget w, int col) { XmLGridWidget g; g = WidgetToGrid(w, "ColumnIsVisible()"); if (!g) return -1; if (!ColIsVisible(g, g->grid.headingColCount + col)) return False; return True; } void XmLGridMoveColumns(Widget w, int newPosition, int position, int count) { XmLGridWidget g; XmLGridRow row; int i, np, p, rowCount; g = WidgetToGrid(w, "MoveColumns()"); if (!g) return; np = ColTypePosToPos(g, XmCONTENT, newPosition, 0); p = ColTypePosToPos(g, XmCONTENT, position, 0); if (XmLArrayMove(g->grid.colArray, np, p, count) == -1) { XmLWarning(w, "MoveColumns() - invalid position"); return; } rowCount = XmLArrayGetCount(g->grid.rowArray); for (i = 0; i < rowCount; i++) { row = XmLArrayGet(g->grid.rowArray, i); XmLArrayMove(XmLGridRowCells(row), np, p, count); } VisPosChanged(g, 0); HorizLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } void XmLGridMoveRows(Widget w, int newPosition, int position, int count) { XmLGridWidget g; int np, p; g = WidgetToGrid(w, "MoveRows()"); if (!g) return; np = RowTypePosToPos(g, XmCONTENT, newPosition, 0); p = RowTypePosToPos(g, XmCONTENT, position, 0); if (XmLArrayMove(g->grid.rowArray, np, p, count) == -1) { XmLWarning(w, "MoveRows() - invalid position/count"); return; } VisPosChanged(g, 1); VertLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } void XmLGridReorderColumns(Widget w, int *newPositions, int position, int count) { XmLGridWidget g; XmLGridRow row; int i, *np, p, rowCount, status; g = WidgetToGrid(w, "ReorderColumns()"); if (!g) return; if (count <= 0) return; p = ColTypePosToPos(g, XmCONTENT, position, 0); np = (int *)malloc(sizeof(int) * count); for (i = 0; i < count; i++) np[i] = ColTypePosToPos(g, XmCONTENT, newPositions[i], 0); status = XmLArrayReorder(g->grid.colArray, np, p, count); if (status < 0) { free((char *)np); XmLWarning(w, "ReorderColumns() - invalid position/count"); return; } rowCount = XmLArrayGetCount(g->grid.rowArray); for (i = 0; i < rowCount; i++) { row = XmLArrayGet(g->grid.rowArray, i); XmLArrayReorder(XmLGridRowCells(row), np, p, count); } free((char *)np); VisPosChanged(g, 0); HorizLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } void XmLGridReorderRows(Widget w, int *newPositions, int position, int count) { XmLGridWidget g; int i, *np, p, status; g = WidgetToGrid(w, "ReorderRows()"); if (!g) return; if (count <= 0) return; p = RowTypePosToPos(g, XmCONTENT, position, 0); np = (int *)malloc(sizeof(int) * count); for (i = 0; i < count; i++) np[i] = RowTypePosToPos(g, XmCONTENT, newPositions[i], 0); status = XmLArrayReorder(g->grid.rowArray, np, p, count); free((char *)np); if (status == -1) { XmLWarning(w, "ReorderRows() - invalid position/count"); return; } VisPosChanged(g, 1); VertLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } int XmLGridRowColumnToXY(Widget w, unsigned char rowType, int row, unsigned char columnType, int column, Boolean clipped, XRectangle *rect) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "RowColumnToXY()"); if (!g) return -1; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); if (r < 0 || r >= XmLArrayGetCount(g->grid.rowArray) || c < 0 || c >= XmLArrayGetCount(g->grid.colArray)) { /* XmLWarning(w, "RowColumnToXY() - invalid position");*/ return -1; } return RowColToXY(g, r, c, clipped, rect); } Boolean XmLGridRowIsVisible(Widget w, int row) { XmLGridWidget g; g = WidgetToGrid(w, "RowIsVisible()"); if (!g) return -1; if (!RowIsVisible(g, g->grid.headingRowCount + row)) return False; return True; } void XmLGridSelectAllRows(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectAllRows()"); if (!g) return; SelectTypeArea(g, SelectRow, (XEvent *)0, -1, 0, True, notify); } void XmLGridSelectAllColumns(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectAllColumns()"); if (!g) return; SelectTypeArea(g, SelectCol, (XEvent *)0, 0, -1, True, notify); } void XmLGridSelectAllCells(Widget w, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectAllCells()"); if (!g) return; SelectTypeArea(g, SelectCell, (XEvent *)0, -1, -1, True, notify); } void XmLGridSelectCell(Widget w, int row, int column, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectCell()"); if (!g) return; SelectTypeArea(g, SelectCell, (XEvent *)0, row, column, True, notify); } void XmLGridSelectColumn(Widget w, int column, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectColumn()"); if (!g) return; SelectTypeArea(g, SelectCol, (XEvent *)0, 0, column, True, notify); } void XmLGridSelectRow(Widget w, int row, Boolean notify) { XmLGridWidget g; g = WidgetToGrid(w, "SelectRow()"); if (!g) return; SelectTypeArea(g, SelectRow, (XEvent *)0, row, 0, True, notify); } int XmLGridSetFocus(Widget w, int row, int column) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "SetFocus()"); if (!g) return -1; if (row < 0 || row >= g->grid.rowCount) { XmLWarning(w, "SetFocus() - invalid row"); return -1; } if (column < 0 || column >= g->grid.colCount) { XmLWarning(w, "SetFocus() - invalid column"); return -1; } r = RowTypePosToPos(g, XmCONTENT, row, 0); c = ColTypePosToPos(g, XmCONTENT, column, 0); return SetFocus(g, r, c, 0, 0); } int XmLGridXYToRowColumn(Widget w, int x, int y, unsigned char *rowType, int *row, unsigned char *columnType, int *column) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "XYToRowColumn()"); if (!g) return -1; if (XYToRowCol(g, x, y, &r, &c) == -1) return -1; *rowType = RowPosToType(g, r); *row = RowPosToTypePos(g, *rowType, r); *columnType = ColPosToType(g, c); *column = ColPosToTypePos(g, *columnType, c); return 0; } void XmLGridRedrawAll(Widget w) { XmLGridWidget g; g = WidgetToGrid(w, "RedrawAll()"); if (!g) return; DrawArea(g, DrawAll, 0, 0); } void XmLGridRedrawCell(Widget w, unsigned char rowType, int row, unsigned char columnType, int column) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "RedrawCell()"); if (!g) return; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); DrawArea(g, DrawCell, r, c); } void XmLGridRedrawColumn(Widget w, unsigned char type, int column) { XmLGridWidget g; int c; g = WidgetToGrid(w, "RedrawColumn()"); if (!g) return; c = ColTypePosToPos(g, type, column, 0); DrawArea(g, DrawCol, 0, c); } void XmLGridRedrawRow(Widget w, unsigned char type, int row) { XmLGridWidget g; int r; g = WidgetToGrid(w, "RedrawRow()"); if (!g) return; r = RowTypePosToPos(g, type, row, 0); DrawArea(g, DrawRow, r, 0); } int XmLGridRead(Widget w, FILE *file, int format, char delimiter) { XmLGridWidget g; char *data; int n; g = WidgetToGrid(w, "Read()"); if (!g) return 0; if (!file) { XmLWarning(w, "Read() - file is NULL"); return 0; } data = FileToString(file); if (!data) { XmLWarning(w, "Read() - error loading file"); return 0; } n = Read(g, format, delimiter, 0, 0, data); free((char *)data); return n; } int XmLGridReadPos(Widget w, FILE *file, int format, char delimiter, unsigned char rowType, int row, unsigned char columnType, int column) { XmLGridWidget g; char *data; int r, c, n; g = WidgetToGrid(w, "ReadPos()"); if (!g) return 0; if (!file) { XmLWarning(w, "ReadPos() - file is NULL"); return 0; } data = FileToString(file); if (!data) { XmLWarning(w, "ReadPos() - error loading file"); return 0; } r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); n = Read(g, format, delimiter, r, c, data); free((char *)data); return n; } int XmLGridSetStrings(Widget w, char *data) { XmLGridWidget g; g = WidgetToGrid(w, "SetStrings()"); if (!g) return 0; return Read(g, XmFORMAT_DELIMITED, '|', 0, 0, data); } int XmLGridSetStringsPos(Widget w, unsigned char rowType, int row, unsigned char columnType, int column, char *data) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "SetStringsPos()"); if (!g) return 0; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); return Read(g, XmFORMAT_DELIMITED, '|', r, c, data); } int XmLGridWrite(Widget w, FILE *file, int format, char delimiter, Boolean skipHidden) { XmLGridWidget g; int nrow, ncol; g = WidgetToGrid(w, "Write()"); if (!g) return 0; nrow = XmLArrayGetCount(g->grid.rowArray); ncol = XmLArrayGetCount(g->grid.colArray); Write(g, file, format, delimiter, skipHidden, 0, 0, nrow, ncol); return 0; } int XmLGridWritePos(Widget w, FILE *file, int format, char delimiter, Boolean skipHidden, unsigned char rowType, int row, unsigned char columnType, int column, int nrow, int ncolumn) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "WritePos()"); if (!g) return 0; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); Write(g, file, format, delimiter, skipHidden, r, c, nrow, ncolumn); return 0; } Boolean XmLGridCopyPos(Widget w, Time time, unsigned char rowType, int row, unsigned char columnType, int column, int nrow, int ncolumn) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "CopyPos()"); if (!g) return False; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); return Copy(g, time, 0, r, c, nrow, ncolumn); } Boolean XmLGridCopySelected(Widget w, Time time) { XmLGridWidget g; g = WidgetToGrid(w, "CopySelected()"); if (!g) return False; return Copy(g, time, 1, 0, 0, 0, 0); } Boolean XmLGridPaste(Widget w) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "Paste()"); if (!g) return False; r = g->grid.focusRow; c = g->grid.focusCol; if (r < 0 || c < 0) { XmLWarning(w, "Paste() - no cell has focus"); return False; } return Paste(g, r, c); } Boolean XmLGridPastePos(Widget w, unsigned char rowType, int row, unsigned char columnType, int column) { XmLGridWidget g; int r, c; g = WidgetToGrid(w, "PastePos()"); if (!g) return False; r = RowTypePosToPos(g, rowType, row, 0); c = ColTypePosToPos(g, columnType, column, 0); return Paste(g, r, c); } /* XFE Additions below here */ static void EditTimer(XtPointer clientData, XtIntervalId *intervalId) { XmLGridWidget g; g = (XmLGridWidget)clientData; g->grid.editTimerSet = 0; g->grid.lastSelectTime = 0; TextAction(g,TEXT_EDIT_INSERT); } void XmLGridSetVisibleColumnCount(Widget w, int new_num_visible) { XmLGridWidget g = (XmLGridWidget)w; int ii, num_columns, visible_count; XmLGridColumn colp; visible_count = 0; num_columns = XmLArrayGetCount(g->grid.colArray); if (new_num_visible == 0) return; for (ii = 0; ii < num_columns; ii ++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, ii); if (colp->grid.hidden && visible_count < new_num_visible) { colp->grid.hidden = False; } else if (!colp->grid.hidden && visible_count >= new_num_visible) { colp->grid.hidden = True; } if (!colp->grid.hidden) visible_count++; } if (visible_count < num_columns) g->grid.visibleCols = visible_count; else g->grid.visibleCols = 0; setHideUnhideSensitivity(w); HorizLayout(g, 1); DrawArea(g, DrawAll, 0, 0); } static void HideColumn(Widget w, XtPointer clientData, XtPointer callData) { Widget g = (Widget) clientData; XmLGridHideRightColumn(g); } static void UnhideColumn(Widget w, XtPointer clientData, XtPointer callData) { Widget g = (Widget) clientData; XmLGridUnhideRightColumn(g); } static void CreateHideUnhideButtons(XmLGridWidget g) { if (!g->grid.hideUnhideButtons) { XmLWarning((Widget)g,"CreateHideUnhideButtons - Creating buttons when XmNhideUnhideButtons is False."); return; } g->grid.hideButton = XtVaCreateWidget( "hide", xmDrawnButtonWidgetClass, (Widget)g, XmNhighlightThickness, 0, XmNshadowThickness, 1, XmNtraversalOn, False, XmNbackground, g->core.background_pixel, XmNforeground, g->manager.foreground, XmNtopShadowColor, g->manager.top_shadow_color, XmNbottomShadowColor, g->manager.bottom_shadow_color, NULL); g->grid.unhideButton = XtVaCreateWidget( "unhide", xmDrawnButtonWidgetClass, (Widget)g, XmNhighlightThickness, 0, XmNshadowThickness, 1, XmNtraversalOn, False, XmNbackground, g->core.background_pixel, XmNforeground, g->manager.foreground, XmNtopShadowColor, g->manager.top_shadow_color, XmNbottomShadowColor, g->manager.bottom_shadow_color, NULL); XmLDrawnButtonSetType(g->grid.hideButton, XmDRAWNB_SMALLARROW, XmDRAWNB_RIGHT); XmLDrawnButtonSetType(g->grid.unhideButton, XmDRAWNB_SMALLARROW, XmDRAWNB_LEFT); XtAddCallback(g->grid.hideButton, XmNactivateCallback, HideColumn, (XtPointer)g); XtAddCallback(g->grid.unhideButton, XmNactivateCallback, UnhideColumn, (XtPointer)g); #if 0 XtOverrideTranslations(g->grid.unhideButton, g->grid.unhideButtonTrans); XtOverrideTranslations(g->grid.hideButton, g->grid.hideButtonTrans); #endif /*0*/ } static void HideAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLGridHideRightColumn(w); } static void UnhideAction(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLGridUnhideRightColumn(w); } static void setHideUnhideSensitivity(Widget w) { XmLGridWidget g = (XmLGridWidget)w; int total_columns = XmLArrayGetCount(g->grid.colArray); Boolean can_unhide, can_hide; if (!g->grid.hideUnhideButtons) return; /* If visibleCols is zero, that means all the columns are visible. */ if (g->grid.visibleCols == 0) { can_unhide = 0; can_hide = (total_columns > 1); } else { can_unhide = (g->grid.visibleCols < total_columns); can_hide = (g->grid.visibleCols > 1); } XtSetSensitive(g->grid.unhideButton, can_unhide); XtSetSensitive(g->grid.hideButton, can_hide); } void XmLGridHideRightColumn(Widget w) { XmLGridWidget g = (XmLGridWidget)w; int total_columns = XmLArrayGetCount(g->grid.colArray); if (total_columns <= 1) return; /* If visibleCols is zero, that means all the columns are visible. */ if (g->grid.visibleCols == 0 || g->grid.visibleCols > total_columns) XmLGridSetVisibleColumnCount(w, total_columns - 1); else XmLGridSetVisibleColumnCount(w, g->grid.visibleCols - 1); } void XmLGridUnhideRightColumn(Widget w) { XmLGridWidget g = (XmLGridWidget)w; int total_columns = XmLArrayGetCount(g->grid.colArray); /* If visibleCols is zero, that means all the columns are visible. */ if ( g->grid.visibleCols != 0 && g->grid.visibleCols < total_columns) XmLGridSetVisibleColumnCount(w, g->grid.visibleCols + 1); } static void MenuArm(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLGridWidget g = (XmLGridWidget)w; SelectTypeArea(g, SelectRow, (XEvent *)0, g->grid.lastSelectRow, 0, False, False); g->grid.inMode = InSelect; } static void MenuDisarm(Widget w, XEvent *event, String *params, Cardinal *num_params) { XmLGridWidget g = (XmLGridWidget)w; g->grid.inMode = InNormal; } static int SizeColumnsToFit(XmLGridWidget g, int starting_at) { int resizable_width = 0; int delta = 0; float hidden_col_adjust; int ii, num_columns; XmLGridColumn colp; /* Total the width of the columns and also total how much of that can be resized */ delta = g->core.width; delta -= g->manager.shadow_thickness * 2; #if 0 if (g->grid.hideUnhideButtons) { delta -= 24; } if (XtIsManaged(g->grid.vsb)) { delta -= g->grid.vsb->core.width; } #endif num_columns = g->grid.colCount + g->grid.headingColCount + g->grid.footerColCount; for (ii = 0; ii < num_columns; ii ++) { colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, ii); if (colp->grid.sizePolicy != XmCONSTANT) { if (g->grid.debugLevel) XmLWarning((Widget)g, "SizeColumnsToFit() - only valid for XmNcolumnSizePolicy == XmCONSTANT"); colp->grid.sizePolicy = XmCONSTANT; } if (!g->grid.visibleCols || ii < g->grid.visibleCols) { delta -= colp->grid.width; if (ii >= starting_at && colp->grid.resizable) resizable_width += colp->grid.width; } } if (delta == 0 || resizable_width <= 0) return delta; if (g->grid.debugLevel) { fprintf(stderr,"Applying delta(%d) from %d to %d (%d resizable)\n", delta, starting_at, num_columns - 1, resizable_width); } hidden_col_adjust = (float)delta / resizable_width; /* Adjust each column to fit based on its percentage of the total width */ for (ii = starting_at; ii < num_columns ; ii ++) { int col_width; int col_delta; Dimension new_col_width; colp = (XmLGridColumn)XmLArrayGet(g->grid.colArray, ii); col_width = colp->grid.width; if (!colp->grid.resizable || col_width == 0) continue; if (colp->grid.hidden) col_delta = (int)(hidden_col_adjust * col_width); else if (col_width < resizable_width && resizable_width > 0) col_delta = delta * ((float)col_width / resizable_width); else col_delta = delta; new_col_width = col_width + col_delta; if (new_col_width < g->grid.minColWidth) { new_col_width = g->grid.minColWidth; col_delta = col_width - new_col_width; } if (!colp->grid.hidden) { delta -= col_delta; resizable_width -= col_width; } colp->grid.width = new_col_width; if (g->grid.debugLevel) fprintf (stderr, "Column %d, width %d -> %d, new delta %d, new resizable width %d\n", ii, col_width, new_col_width, delta, resizable_width); } return delta; } /*----------------------------------------------------------------------*/ static void GridInvokeCallbacks(Widget w, XtCallbackList list, int reason, XEvent * event) { XmLGridWidget g = (XmLGridWidget)w; /* Make sure widget is alive and callback list is not NULL */ if (!g->core.being_destroyed && list) { XmAnyCallbackStruct cbs; cbs.event = event; cbs.reason = reason; /* Invoke the Callback List */ XtCallCallbackList(w,list,&cbs); } } /*----------------------------------------------------------------------*/ static void GridInvokeCellCrossingCallbacks(Widget w, XtCallbackList list, int reason, XEvent * event, int row, int col) { XmLGridWidget g = (XmLGridWidget)w; /* Make sure widget is alive and callback list is not NULL */ if (!g->core.being_destroyed && list) { if (row != -1 && col != -1) { XmLGridCell cell; XmLGridCallbackStruct cbs; cell = GetCell(g, row, col); if (cell) { cbs.reason = XmCR_CELL_FOCUS_OUT; cbs.columnType = ColPosToType(g, col); cbs.column = ColPosToTypePos(g, cbs.columnType, col); cbs.rowType = RowPosToType(g, row); cbs.row = RowPosToTypePos(g, cbs.rowType, row); /* XmLGridCellAction(cell, (Widget)g, &cbs); */ /* Invoke the Callback List */ XtCallCallbackList(w,list,&cbs); } } } } /*----------------------------------------------------------------------*/ static void GridCrossingEH(Widget w, XtPointer closure, XEvent * event, Boolean * ctd) { XmLGridWidget g = (XmLGridWidget)w; if (event) { if (event->type == EnterNotify) { /* Invoke XmNenterGridCallback */ GridInvokeCallbacks(w, g->grid.enterGridCallback, XmCR_ENTER_GRID, event); /* printf("Enter(%s)\n",XtName(w)); */ } else if (event->type == LeaveNotify) { g->grid.lastCursorMotionRow = -1; g->grid.lastCursorMotionCol = -1; /* Invoke XmNleaveGridCallback */ GridInvokeCallbacks(w, g->grid.leaveGridCallback, XmCR_LEAVE_GRID, event); /* printf("Leave(%s)\n",XtName(w)); */ } } *ctd = True; } /*----------------------------------------------------------------------*/