/* Copyright (c) 1999 Alexander Yukhimets. All rights reserved. */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/StringDefs.h>
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
#include<XmAxy/ListP.h>
#include<XmAxy/Util.h>
#include <Xm/XmP.h>
#include <Xm/DrawP.h>
#include <Xm/DragIcon.h>
#include <Xm/DragC.h>
#define RESIZE_STRIP_WITH_HIDDEN_LABELS 4
#define RESIZE_MARGIN 3
#define COL_MIN_SIZE 8
#define CLICK_INTERVAL(w) \
(((XmAxyListWidget)(w))->list.click_interval)
#define CLICK_COUNT(w) \
(((XmAxyListWidget)(w))->list.click_count)
#define CLICK_TIME(w) \
(((XmAxyListWidget)(w))->list.click_time)
#define SELECTION_DRAG(w) \
(((XmAxyListWidget)(w))->list.selection_drag)
#define SCROLL_DIRECTION(w) \
(((XmAxyListWidget)(w))->list.scroll_direction)
#define SCROLL_TIMER_ID(w) \
(((XmAxyListWidget)(w))->list.scroll_timer_id)
#define SCROLL_TIMER_SET(w) \
(((XmAxyListWidget)(w))->list.scroll_timer_set)
#define LAST_SELECTED_ROW(w) \
(((XmAxyListWidget)(w))->list.last_selected_row)
#define ANCHOR(w) \
(((XmAxyListWidget)(w))->list.anchor)
#define SELECTED_ROWS(w) \
(((XmAxyListWidget)(w))->list.selected_row)
#define SELECTED_ROW(w,i) (SELECTED_ROWS(w)[i])
#define SELECTED_ROW_COUNT(w) \
(((XmAxyListWidget)(w))->list.selected_row_count)
#define ROW_IS_SELECTED(w,i) (ROW_IS_SELECTED_ARRAY(w)[i])
#define ROW_IS_SELECTED_ARRAY(w) \
(((XmAxyListWidget)(w))->list.row_is_selected)
#define RESIZE_CURSOR(w) \
(((XmAxyListWidget)(w))->list.resize_cursor)
#define COL_RESIZE_AREA(w) \
(((XmAxyListWidget)(w))->list.col_resize_area)
#define COL_RESIZE_UNDERWAY(w) \
(((XmAxyListWidget)(w))->list.col_resize_underway)
#define COL_RESIZE_NUM(w) \
(((XmAxyListWidget)(w))->list.col_resize_num)
#define COL_RESIZE_X(w) \
(((XmAxyListWidget)(w))->list.col_resize_x)
#define EHT(w) (HIGHLIGHT_THICKNESS(w)?(HIGHLIGHT_THICKNESS(w)+(Dimension)1):\
(Dimension)0)
#define MARGIN_WIDTH(w) \
(((XmAxyListWidget)(w))->list.margin_width)
#define MARGIN_HEIGHT(w) \
(((XmAxyListWidget)(w))->list.margin_height)
#define CELL_MARGIN_WIDTH(w) \
(((XmAxyListWidget)(w))->list.cell_margin_width)
#define CELL_MARGIN_HEIGHT(w) \
(((XmAxyListWidget)(w))->list.cell_margin_height)
#define LABEL_MARGIN_WIDTH(w) \
(((XmAxyListWidget)(w))->list.label_margin_width)
#define LABEL_MARGIN_HEIGHT(w) \
(((XmAxyListWidget)(w))->list.label_margin_height)
#define FONT(w) \
(((XmAxyListWidget)(w))->list.font)
#define FONT_FID(w) \
(((XmAxyListWidget)(w))->list.font_fid)
#define FONT_STRUCT(w) \
(((XmAxyListWidget)(w))->list.font_struct)
#define FONT_SET(w) \
(((XmAxyListWidget)(w))->list.font_set)
#define FONT_WIDTH(w) \
(((XmAxyListWidget)(w))->list.font_width)
#define FONT_HEIGHT(w) \
(((XmAxyListWidget)(w))->list.font_height)
#define FONT_Y(w) \
(((XmAxyListWidget)(w))->list.font_y)
#define LABEL_FONT(w) \
(((XmAxyListWidget)(w))->list.font)
#define LABEL_FONT_FID(w) \
(((XmAxyListWidget)(w))->list.label_font_fid)
#define LABEL_FONT_STRUCT(w) \
(((XmAxyListWidget)(w))->list.label_font_struct)
#define LABEL_FONT_SET(w) \
(((XmAxyListWidget)(w))->list.label_font_set)
#define LABEL_FONT_WIDTH(w) \
(((XmAxyListWidget)(w))->list.label_font_width)
#define LABEL_FONT_HEIGHT(w) \
(((XmAxyListWidget)(w))->list.label_font_height)
#define LABEL_FONT_Y(w) \
(((XmAxyListWidget)(w))->list.label_font_y)
#define BOLD_LABELS(w) \
(((XmAxyListWidget)(w))->list.bold_labels)
#define SHOW_LABELS(w) \
(((XmAxyListWidget)(w))->list.show_labels)
#define ACTIVE_LABELS(w) \
(((XmAxyListWidget)(w))->list.active_labels)
#define LABEL_SHADOW_THICKNESS(w) \
(((XmAxyListWidget)(w))->list.label_shadow_thickness)
#define LABEL_BACKGROUND(w) \
(((XmAxyListWidget)(w))->list.label_background)
#define LABEL_FOREGROUND(w) \
(((XmAxyListWidget)(w))->list.label_foreground)
#define LABEL_TOP_SHADOW_COLOR(w) \
(((XmAxyListWidget)(w))->list.label_top_shadow_color)
#define LABEL_BOTTOM_SHADOW_COLOR(w) \
(((XmAxyListWidget)(w))->list.label_bottom_shadow_color)
#define LABEL_TOP_SHADOW_PIXMAP(w) \
(((XmAxyListWidget)(w))->list.label_top_shadow_pixmap)
#define LABEL_BOTTOM_SHADOW_PIXMAP(w) \
(((XmAxyListWidget)(w))->list.label_bottom_shadow_pixmap)
#define CELL_BACKGROUND(w) \
(((XmAxyListWidget)(w))->list.cell_background)
#define CELL_FOREGROUND(w) \
(((XmAxyListWidget)(w))->list.cell_foreground)
#define SELECTED_BACKGROUND(w) \
(((XmAxyListWidget)(w))->list.selected_background)
#define SELECTED_FOREGROUND(w) \
(((XmAxyListWidget)(w))->list.selected_foreground)
#define BACKGROUND_GC(w) \
(((XmAxyListWidget)(w))->list.background_gc)
#define LABEL_BACKGROUND_GC(w) \
(((XmAxyListWidget)(w))->list.label_background_gc)
#define LABEL_TOP_SHADOW_GC(w) \
(((XmAxyListWidget)(w))->list.label_top_shadow_gc)
#define LABEL_BOTTOM_SHADOW_GC(w) \
(((XmAxyListWidget)(w))->list.label_bottom_shadow_gc)
#define LABEL_DRAW_GC(w) \
(((XmAxyListWidget)(w))->list.label_draw_gc)
#define CELL_BACKGROUND_GC(w) \
(((XmAxyListWidget)(w))->list.cell_background_gc)
#define DRAW_GC(w) \
(((XmAxyListWidget)(w))->list.draw_gc)
#define SELECTED_BACKGROUND_GC(w) \
(((XmAxyListWidget)(w))->list.selected_background_gc)
#define SELECTED_DRAW_GC(w) \
(((XmAxyListWidget)(w))->list.selected_draw_gc)
#define STRING_DIR(w) \
(((XmAxyListWidget)(w))->list.string_dir)
#define ROW_COUNT(w) \
(((XmAxyListWidget)(w))->list.row_count)
#define VISIBLE_ROW_COUNT(w) \
(((XmAxyListWidget)(w))->list.visible_row_count)
#define ROW_SPACING(w) \
(((XmAxyListWidget)(w))->list.row_spacing)
#define ROW_OFFSET(w,i) \
(SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w)+\
(SHOW_LABELS(w)?LABEL_HEIGHT(w):0)+EHT(w)+\
(ROW_HEIGHT(w)+EHT(w)+ROW_SPACING(w))*(i))
#define ROW_HEIGHT(w) \
(CELL_MARGIN_HEIGHT(w)*2+FONT_HEIGHT(w))
#define LABEL_HEIGHT(w) \
(LABEL_SHADOW_THICKNESS(w)*2+EHT(w)*2+LABEL_MARGIN_HEIGHT(w)*2+FONT_HEIGHT(w))
#define COLUMN_COUNT(w) \
(((XmAxyListWidget)(w))->list.column_count)
#define COLUMN_LABELS(w) \
(((XmAxyListWidget)(w))->list.column_labels)
#define COLUMN_LABEL(w,i) \
(((XmAxyListWidget)(w))->list.column_labels[(i)])
#define COLUMN_WIDTHS(w) \
(((XmAxyListWidget)(w))->list.column_widths)
#define COLUMN_WIDTH(w,i) \
(COLUMN_WIDTHS(w)[(i)])
#define COLUMN_ALIGNMENTS(w) \
(((XmAxyListWidget)(w))->list.column_alignments)
#define COLUMN_ALIGNMENT(w,i) \
(((XmAxyListWidget)(w))->list.column_alignments[(i)])
#define COLUMN_LABEL_ALIGNMENTS(w) \
(((XmAxyListWidget)(w))->list.column_label_alignments)
#define COLUMN_LABEL_ALIGNMENT(w,i) \
(((XmAxyListWidget)(w))->list.column_label_alignments[(i)])
#define COLUMN_OFFSETS(w) \
(((XmAxyListWidget)(w))->list.column_offsets)
#define COLUMN_OFFSET(w,i) \
(((XmAxyListWidget)(w))->list.column_offsets[(i)])
#define SELECTION_POLICY(w) \
(((XmAxyListWidget)(w))->list.selection_policy)
#define SIZE_POLICY(w) \
(((XmAxyListWidget)(w))->list.size_policy)
#define SB_DISPLAY_POLICY(w) \
(((XmAxyListWidget)(w))->list.sb_display_policy)
#define HOR_SHIFT(w) \
(((XmAxyListWidget)(w))->list.hor_shift)
#define VERT_SHIFT(w) \
(((XmAxyListWidget)(w))->list.vert_shift)
#define HOR_MAX(w) \
(((XmAxyListWidget)(w))->list.hor_max)
#define VERT_MAX(w) \
(((XmAxyListWidget)(w))->list.vert_max)
#define HOR_PAGE(w) \
(((XmAxyListWidget)(w))->list.hor_page)
#define VERT_PAGE(w) \
(((XmAxyListWidget)(w))->list.vert_page)
#define HOR_SLIDER(w) \
(((XmAxyListWidget)(w))->list.hor_slider)
#define VERT_SLIDER(w) \
(((XmAxyListWidget)(w))->list.vert_slider)
#define RESIZING(w) \
(((XmAxyListWidget)(w))->list.resizing)
#define RESIZING_VSB(w) \
(((XmAxyListWidget)(w))->list.resizing_vsb)
#define RESIZING_HSB(w) \
(((XmAxyListWidget)(w))->list.resizing_hsb)
#define RESIZE_TIMER_ID(w) \
(((XmAxyListWidget)(w))->list.resize_timer_id)
#define RESIZE_TIMER_STARTED(w) \
(((XmAxyListWidget)(w))->list.resize_timer_started)
#define RESIZE_TIMER_SET(w) \
(((XmAxyListWidget)(w))->list.resize_timer_set)
#define SINGLE_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.single_callback)
#define MULTIPLE_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.multiple_callback)
#define EXTENDED_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.extended_callback)
#define BROWSE_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.browse_callback)
#define DEFAULT_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.default_callback)
#define LABEL_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.label_callback)
#define DRAW_CB_LIST(w) \
(((XmAxyListWidget)(w))->list.draw_cell_callback)
#define VERT_SB(w) \
(((XmAxyListWidget)(w))->list.vert_sb)
#define HOR_SB(w) \
(((XmAxyListWidget)(w))->list.hor_sb)
#define SCROLLED_WINDOW(w) \
(((XmAxyListWidget)(w))->list.scrolled_window)
#define BUFFER(w) \
(((XmAxyListWidget)(w))->list.buffer)
#define REDRAW_BUFFER(w) \
(((XmAxyListWidget)(w))->list.redraw_buffer)
#define HIGHLIGHTED(w) \
(((XmPrimitiveWidget)(w))->primitive.highlighted)
#define HIGHLIGHT_THICKNESS(w) \
(((XmPrimitiveWidget)(w))->primitive.highlight_thickness)
#define SHADOW_THICKNESS(w) \
(((XmPrimitiveWidget)(w))->primitive.shadow_thickness)
#define FOREGROUND(w) \
(((XmPrimitiveWidget)(w))->primitive.foreground)
#define TOP_SHADOW_GC(w) \
(((XmPrimitiveWidget)(w))->primitive.top_shadow_GC)
#define BOTTOM_SHADOW_GC(w) \
(((XmPrimitiveWidget)(w))->primitive.bottom_shadow_GC)
#define HIGHLIGHT_GC(w) \
(((XmPrimitiveWidget)(w))->primitive.highlight_GC)
#define BEING_DESTROYED(w) \
(((CoreWidget)(w))->core.being_destroyed)
#define X(w) \
(((CoreWidget)(w))->core.x)
#define Y(w) \
(((CoreWidget)(w))->core.y)
#define WIDTH(w) \
(((CoreWidget)(w))->core.width)
#define HEIGHT(w) \
(((CoreWidget)(w))->core.height)
#define BORDER(w) \
(((CoreWidget)(w))->core.border_width)
#define DEPTH(w) \
(((CoreWidget)(w))->core.depth)
#define COLORMAP(w) \
(((CoreWidget)(w))->core.colormap)
#define BACKGROUND(w) \
(((CoreWidget)(w))->core.background_pixel)
/* class methods */
static void ClassInitialize(void);
static void ClassPartInitialize(WidgetClass widget_class);
static void Initialize(Widget request, Widget new_w,
ArgList args, Cardinal *num_args);
static void Destroy(Widget w);
static void Resize(Widget w);
static void Redisplay(Widget w, XEvent *event, Region region);
static Boolean SetValues(Widget current, Widget request, Widget new_w,
ArgList args, Cardinal *num_args);
static XtGeometryResult QueryGeometry(Widget w,
XtWidgetGeometry *proposed,
XtWidgetGeometry *answer);
/* action routines */
static void ButtonDown(Widget, XEvent *, String *, Cardinal *);
static void ButtonUp(Widget, XEvent *, String *, Cardinal *);
static void ButtonMotion(Widget, XEvent *, String *, Cardinal *);
static void PointerMotion(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListBeginSelect(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListEndSelect(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListBeginToggle(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListEndToggle(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListBeginExtend(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListEndExtend(Widget, XEvent *, String *, Cardinal *);
static void _XmAxyListButtonMotion(Widget, XEvent *, String *, Cardinal *);
/* local functions */
static Dimension preferredWidth(Widget);
static Dimension preferredHeight(Widget);
static void copyWidths(Widget);
static void copyColumnAlignments(Widget);
static void copyColumnLabelAlignments(Widget);
static void copyColumnLabels(Widget);
static void createBackgroundGC(Widget);
static void createLabelBackgroundGC(Widget);
static void createLabelTopShadowGC(Widget);
static void createLabelBottomShadowGC(Widget);
static void createLabelDrawGC(Widget);
static void createCellBackgroundGC(Widget);
static void createDrawGC(Widget);
static void createSelectedBackgroundGC(Widget);
static void createSelectedDrawGC(Widget);
static void createGCs(Widget);
static void destroy_parent_cb(Widget,XtPointer,XtPointer);
static void hor_sb_cb(Widget,XtPointer,XtPointer);
static void vert_sb_cb(Widget,XtPointer,XtPointer);
static void redrawList(Widget,Drawable,XRectangle*);
static void drawLabels(Widget,Drawable,XRectangle*);
static void drawLabel(Widget,Drawable,XRectangle*,int);
static void drawCells(Widget,Drawable,XRectangle*);
static void drawCell(Widget,Drawable,XRectangle*,int,int);
static void drawResizeLine(Widget,Position);
static void installFont(Widget);
static void installLabelFont(Widget);
static void handleVertSB(Widget,Boolean*);
static void handleHorSB(Widget,Boolean*);
static void resizeLater(XtPointer,XtIntervalId*);
static void scrollTimer(XtPointer,XtIntervalId*);
static int figureColToResize(Widget,Position,Position);
static void doColResize(Widget);
static void select_row(Widget,int);
static void deselect_all(Widget);
static void deselect_row(Widget,int);
static int XYToRow(Widget,int,int);
static int XYToCol(Widget,int,int);
static void drawSelection(Widget,Drawable,XRectangle*,int,int);
static void change_select_range(Widget,int);
static void deselect_current_range(Widget);
static char defaultTranslations[]="\
<Btn1Motion>: XmAxyListColumnResizeButtonMotion()\
XmAxyListButtonMotion()\n\
s ~m ~a <Btn1Down>: XmAxyListColumnResizeButtonDown()\
XmAxyListBeginExtend()\n\
s ~m ~a <Btn1Up>: XmAxyListColumnResizeButtonUp()\
XmAxyListEndExtend()\n\
c ~s ~m ~a <Btn1Down>: XmAxyListColumnResizeButtonDown()\
XmAxyListBeginToggle()\n\
c ~s ~m ~a <Btn1Up>: XmAxyListColumnResizeButtonUp()\
XmAxyListEndToggle()\n\
~c ~s ~m ~a <Btn1Down>: XmAxyListColumnResizeButtonDown()\
XmAxyListBeginSelect()\n\
~c ~s ~m ~a <Btn1Up>: XmAxyListColumnResizeButtonUp()\
XmAxyListEndSelect()\n\
<Btn1Down>: XmAxyListColumnResizeButtonDown()\n\
<Btn1Up>: XmAxyListColumnResizeButtonUp()\n\
<MotionNotify>: XmAxyListColumnResizePointerMotion()\n\
";
static XtActionsRec actions[] = {
{"XmAxyListColumnResizeButtonDown", ButtonDown},
{"XmAxyListColumnResizeButtonUp", ButtonUp},
{"XmAxyListColumnResizeButtonMotion", ButtonMotion},
{"XmAxyListColumnResizePointerMotion", PointerMotion},
{"XmAxyListBeginSelect", _XmAxyListBeginSelect},
{"XmAxyListEndSelect", _XmAxyListEndSelect},
{"XmAxyListBeginToggle", _XmAxyListBeginToggle},
{"XmAxyListEndToggle", _XmAxyListEndToggle},
{"XmAxyListBeginExtend", _XmAxyListBeginExtend},
{"XmAxyListEndExtend", _XmAxyListEndExtend},
{"XmAxyListButtonMotion", _XmAxyListButtonMotion},
};
#define Offset(field) XtOffsetOf(XmAxyListRec, list.field)
static XtResource resources[] = {
{XmNdoubleClickInterval, XmCDoubleClickInterval,
XmRInt, sizeof(int),
Offset(click_interval),XmRImmediate,
(XtPointer)XmUNSPECIFIED},
{XmNlistMarginWidth, XmCListMarginWidth,
XmRHorizontalDimension, sizeof(Dimension),
Offset(margin_width),XmRImmediate,
(XtPointer)0},
{XmNlistMarginHeight, XmCListMarginHeight,
XmRVerticalDimension, sizeof(Dimension),
Offset(margin_height),XmRImmediate,
(XtPointer)0},
{XmNcellMarginWidth, XmCCellMarginWidth,
XmRHorizontalDimension, sizeof(Dimension),
Offset(cell_margin_width),XmRImmediate,
(XtPointer)2},
{XmNcellMarginHeight, XmCCellMarginHeight,
XmRVerticalDimension, sizeof(Dimension),
Offset(cell_margin_height),XmRImmediate,
(XtPointer)2},
{XmNlabelMarginWidth, XmCLabelMarginWidth,
XmRHorizontalDimension, sizeof(Dimension),
Offset(label_margin_width),XmRImmediate,
(XtPointer)2},
{XmNlabelMarginHeight, XmCLabelMarginHeight,
XmRVerticalDimension, sizeof(Dimension),
Offset(label_margin_height),XmRImmediate,
(XtPointer)2},
{XmNstringDirection, XmCStringDirection,
XmRStringDirection, sizeof(XmStringDirection),
Offset(string_dir),XmRImmediate,
(XtPointer)XmSTRING_DIRECTION_L_TO_R},
{XmNfontList, XmCFontList,
XmRFontList, sizeof(XmFontList),
Offset(font),XmRString,
(XtPointer)NULL},
{XmNlabelFontList, XmCFontList,
XmRFontList, sizeof(XmFontList),
Offset(label_font),XmRImmediate,
(XtPointer)NULL},
{XmNboldLabels, XmCBoldLabels,
XmRBoolean, sizeof(Boolean),
Offset(bold_labels),XmRImmediate,
(XtPointer)FALSE},
{XmNshowLabels, XmCShowLabels,
XmRBoolean, sizeof(Boolean),
Offset(show_labels),XmRImmediate,
(XtPointer)TRUE},
{XmNactiveLabels, XmCActiveLabels,
XmRBoolean, sizeof(Boolean),
Offset(active_labels),XmRImmediate,
(XtPointer)FALSE},
{XmNlabelShadowThickness, XmCShadowThickness,
XmRHorizontalDimension, sizeof(Dimension),
Offset(label_shadow_thickness),XmRImmediate,
(XtPointer)2},
{XmNlabelBackground, XmCLabelBackground,
XmRPixel, sizeof(Pixel),
Offset(label_background),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNlabelForeground, XmCLabelForeground,
XmRPixel, sizeof(Pixel),
Offset(label_foreground),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNlabelBottomShadowColor, XmCLabelBottomShadowColor,
XmRPixel, sizeof(Pixel),
Offset(label_bottom_shadow_color),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNlabelTopShadowColor, XmCLabelTopShadowColor,
XmRPixel, sizeof(Pixel),
Offset(label_top_shadow_color),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNlabelBottomShadowPixmap, XmCLabelBottomShadowPixmap,
XmRPixmap, sizeof(Pixmap),
Offset(label_bottom_shadow_pixmap),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXMAP},
{XmNlabelTopShadowPixmap, XmCLabelTopShadowPixmap,
XmRPixmap, sizeof(Pixmap),
Offset(label_top_shadow_pixmap),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXMAP},
{XmNcellBackground, XmCCellBackground,
XmRPixel, sizeof(Pixel),
Offset(cell_background),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNcellForeground, XmCCellForeground,
XmRPixel, sizeof(Pixel),
Offset(cell_foreground),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNselectedBackground, XmCSelectedBackground,
XmRPixel, sizeof(Pixel),
Offset(selected_background),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNselectedForeground, XmCSelectedForeground,
XmRPixel, sizeof(Pixel),
Offset(selected_foreground),XmRImmediate,
(XtPointer)XmUNSPECIFIED_PIXEL},
{XmNrowCount, XmCRowCount,
XmRInt, sizeof(int),
Offset(row_count), XmRImmediate,
(XtPointer)0},
{XmNrowSpacing, XmCRowSpacing,
XmRVerticalDimension, sizeof(Dimension),
Offset(row_spacing), XmRImmediate,
(XtPointer)0},
{XmNcolumnCount, XmCColumnCount,
XmRInt, sizeof(int),
Offset(column_count), XmRImmediate,
(XtPointer)0},
{XmNcolumnLabels, XmCColumnLabels,
XmRStringArray, sizeof(String *),
Offset(column_labels), XmRImmediate,
(XtPointer)NULL},
{XmNcolumnWidths, XmCColumnWidths,
XmRWidthArray, sizeof(short*),
Offset(column_widths), XmRImmediate,
(XtPointer)NULL},
{XmNcolumnAlignments, XmCColumnAlignments,
XmRAlignmentArray, sizeof(unsigned char*),
Offset(column_alignments), XmRImmediate,
(XtPointer)NULL},
{XmNcolumnLabelAlignments, XmCColumnAlignments,
XmRAlignmentArray, sizeof(unsigned char*),
Offset(column_label_alignments), XmRImmediate,
(XtPointer)NULL},
{XmNscrollBarDisplayPolicy, XmCScrollBarDisplayPolicy,
XmRScrollBarDisplayPolicy, sizeof(unsigned char),
Offset(sb_display_policy),XmRImmediate,
(XtPointer)XmAS_NEEDED},
{XmNselectionPolicy, XmCSelectionPolicy,
XmRSelectionPolicy, sizeof(unsigned char),
Offset(selection_policy),XmRImmediate,
(XtPointer)XmEXTENDED_SELECT},
{XmNsingleSelectionCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(single_callback), XmRCallback, (XtPointer)NULL},
{XmNmultipleSelectionCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(multiple_callback), XmRCallback, (XtPointer)NULL},
{XmNextendedSelectionCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(extended_callback), XmRCallback, (XtPointer)NULL},
{XmNbrowseSelectionCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(browse_callback), XmRCallback,
(XtPointer)NULL},
{XmNdefaultActionCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(default_callback), XmRCallback, (XtPointer)NULL},
{XmNlabelActivateCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(label_callback), XmRCallback, (XtPointer)NULL},
{XmNdrawCellCallback, XmCCallback,
XmRCallback, sizeof(XtCallbackList),
Offset(draw_cell_callback), XmRCallback, (XtPointer)NULL},
{XmNhorizontalScrollBar, XmCHorizontalScrollBar,
XmRWidget, sizeof(Widget),
Offset(hor_sb), XmRImmediate,
(XtPointer)NULL},
{XmNverticalScrollBar, XmCVerticalScrollBar,
XmRWidget, sizeof(Widget),
Offset(vert_sb), XmRImmediate,
(XtPointer)NULL},
};
static XmSyntheticResource syn_resources[] = {
{XmNrowSpacing, sizeof(Dimension), Offset(row_spacing),
_XmFromVerticalPixels, _XmToVerticalPixels},
{XmNlistMarginWidth, sizeof(Dimension), Offset(margin_width),
_XmFromHorizontalPixels, _XmToHorizontalPixels},
{XmNlistMarginHeight, sizeof(Dimension), Offset(margin_height),
_XmFromVerticalPixels, _XmToVerticalPixels},
{XmNcellMarginWidth, sizeof(Dimension), Offset(cell_margin_width),
_XmFromHorizontalPixels, _XmToHorizontalPixels},
{XmNcellMarginHeight, sizeof(Dimension), Offset(cell_margin_height),
_XmFromVerticalPixels, _XmToVerticalPixels},
{XmNlabelMarginWidth, sizeof(Dimension), Offset(label_margin_width),
_XmFromHorizontalPixels, _XmToHorizontalPixels},
{XmNlabelMarginHeight, sizeof(Dimension), Offset(label_margin_height),
_XmFromVerticalPixels, _XmToVerticalPixels},
{XmNlabelShadowThickness, sizeof(Dimension), Offset(label_shadow_thickness),
_XmFromHorizontalPixels, _XmToHorizontalPixels},
};
#undef Offset
externaldef (xmaxylistclassrec) XmAxyListClassRec xmAxyListClassRec = {
/* Core class part */
{
/* superclass */ (WidgetClass) &xmPrimitiveClassRec,
/* class_name */ "XmAxyList",
/* widget_size */ sizeof(XmAxyListRec),
/* class_initialize */ ClassInitialize,
/* class_part_initialize */ ClassPartInitialize,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actions,
/* num_actions */ XtNumber(actions),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ XtExposeCompressMaximal,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ defaultTranslations,
/* query_geometry */ QueryGeometry,
/* display_accelerator */ NULL,
/* extension */ NULL,
},
/* Primitive Class part */
{
/* border_highlight */ NULL,/*XmInheritBorderHighlight,*/
/* border_unhighlight */ NULL,/*XmInheritBorderUnhighlight,*/
/* translations */ XtInheritTranslations,
/* arm_and_activate */ NULL,
/* syn_resources */ syn_resources,
/* num_syn_resources */ XtNumber(syn_resources),
/* extension */ NULL,
},
/* List Class part */
{
/* extension */ NULL,
}
};
externaldef (xmaxylistwidgetclass) WidgetClass xmAxyListWidgetClass =
(WidgetClass)&xmAxyListClassRec;
static void ClassInitialize(void) {
}
static void ClassPartInitialize(WidgetClass widget_class) {
}
static void Initialize(Widget req_w, Widget new_w,
ArgList args, Cardinal *num_args) {
int i;
RESIZE_CURSOR(new_w)=
XCreateFontCursor(XtDisplay(new_w), XC_sb_h_double_arrow);
COL_RESIZE_AREA(new_w)=FALSE;
COL_RESIZE_UNDERWAY(new_w)=FALSE;
COL_RESIZE_NUM(new_w)=0;
COL_RESIZE_X(new_w)=0;
if(FONT(new_w)==NULL){
FONT(new_w)=XmFontListCopy(
_XmGetDefaultFontList(new_w,XmLABEL_FONTLIST));
} else {
FONT(new_w)=XmFontListCopy(FONT(new_w));
}
installFont(new_w);
if(LABEL_FONT(new_w)==NULL){
LABEL_FONT(new_w)=XmFontListCopy(FONT(new_w));
} else {
LABEL_FONT(new_w)=XmFontListCopy(LABEL_FONT(new_w));
}
installLabelFont(new_w);
/*
xms=XmStringCreateSimple("W");
XmStringExtent(FONT(new_w),xms,
&FONT_WIDTH(new_w), &FONT_HEIGHT(new_w));
XmStringFree(xms);
*/
if(CELL_BACKGROUND(new_w)==XmUNSPECIFIED_PIXEL){
/*CELL_BACKGROUND(new_w)=BACKGROUND(new_w);*/
CELL_BACKGROUND(new_w)=WhitePixelOfScreen(XtScreen(new_w));
}
if(CELL_FOREGROUND(new_w)==XmUNSPECIFIED_PIXEL){
Pixel top,bot,sel;
XmGetColors(XtScreen(new_w),COLORMAP(new_w),CELL_BACKGROUND(new_w),
&CELL_FOREGROUND(new_w),&top,&bot,&sel);
}
if(SELECTED_BACKGROUND(new_w)==XmUNSPECIFIED_PIXEL){
SELECTED_BACKGROUND(new_w)=CELL_FOREGROUND(new_w);
}
if(SELECTED_FOREGROUND(new_w)==XmUNSPECIFIED_PIXEL){
SELECTED_FOREGROUND(new_w)=CELL_BACKGROUND(new_w);
}
if(LABEL_BACKGROUND(new_w)==XmUNSPECIFIED_PIXEL){
LABEL_BACKGROUND(new_w)=BACKGROUND(new_w);
}
if(LABEL_TOP_SHADOW_COLOR(new_w)==XmUNSPECIFIED_PIXEL ||
LABEL_BOTTOM_SHADOW_COLOR(new_w)==XmUNSPECIFIED_PIXEL ||
LABEL_FOREGROUND(new_w)==XmUNSPECIFIED_PIXEL){
Pixel fg,top,bot,sel;
XmGetColors(XtScreen(new_w),COLORMAP(new_w),LABEL_BACKGROUND(new_w),
&fg,&top,&bot,&sel);
if(LABEL_FOREGROUND(new_w)==XmUNSPECIFIED_PIXEL){
LABEL_FOREGROUND(new_w)=fg;
}
if(LABEL_TOP_SHADOW_COLOR(new_w)==XmUNSPECIFIED_PIXEL){
LABEL_TOP_SHADOW_COLOR(new_w)=top;
}
if(LABEL_BOTTOM_SHADOW_COLOR(new_w)==XmUNSPECIFIED_PIXEL){
LABEL_BOTTOM_SHADOW_COLOR(new_w)=bot;
}
}
if(ROW_COUNT(new_w)<0){
ROW_COUNT(new_w)=0;
}
if(COLUMN_COUNT(new_w)<0){
COLUMN_COUNT(new_w)=0;
}
if(COLUMN_WIDTHS(new_w)==NULL && COLUMN_COUNT(new_w)>0){
int space=sizeof(short)*COLUMN_COUNT(new_w);
COLUMN_WIDTHS(new_w)=
(short*)XtMalloc(space);
for(i=0;i<COLUMN_COUNT(new_w);i++){
COLUMN_WIDTHS(new_w)[i]=
(COLUMN_LABELS(new_w)!=NULL)?(strlen(COLUMN_LABELS(new_w)[i])):3;
}
} else {
copyWidths(new_w);
}
if(COLUMN_LABELS(new_w)!=NULL){
copyColumnLabels(new_w);
}
if(COLUMN_ALIGNMENTS(new_w)!=NULL){
copyColumnAlignments(new_w);
} else {
COLUMN_ALIGNMENTS(new_w)=
(unsigned char*)XtMalloc(sizeof(unsigned char)*COLUMN_COUNT(new_w));
for(i=0;i<COLUMN_COUNT(new_w);i++)
COLUMN_ALIGNMENT(new_w,i)=XmALIGNMENT_BEGINNING;
}
if(COLUMN_LABEL_ALIGNMENTS(new_w)!=NULL){
copyColumnLabelAlignments(new_w);
} else {
COLUMN_LABEL_ALIGNMENTS(new_w)=
(unsigned char*)XtMalloc(sizeof(unsigned char)*COLUMN_COUNT(new_w));
for(i=0;i<COLUMN_COUNT(new_w);i++)
COLUMN_LABEL_ALIGNMENT(new_w,i)=XmALIGNMENT_CENTER;
}
BORDER(new_w)=0;
HOR_SHIFT(new_w)=0;
VERT_SHIFT(new_w)=0;
VERT_SLIDER(new_w)=6;
VERT_MAX(new_w)=VERT_SLIDER(new_w);
if(CLICK_INTERVAL(new_w)==XmUNSPECIFIED){
CLICK_INTERVAL(new_w)=XtGetMultiClickTime(XtDisplay(new_w));
}
CLICK_COUNT(new_w)=0;
CLICK_TIME(new_w)=0;
COLUMN_OFFSETS(new_w)=(int*)XtMalloc(sizeof(int)*(COLUMN_COUNT(new_w)+1));
COLUMN_OFFSET(new_w,0)=SHADOW_THICKNESS(new_w)+MARGIN_WIDTH(new_w);
for(i=0;i<COLUMN_COUNT(new_w);i++){
COLUMN_OFFSET(new_w,i+1)=COLUMN_OFFSET(new_w,i)+
LABEL_FONT_WIDTH(new_w)*COLUMN_WIDTHS(new_w)[i]+
LABEL_MARGIN_WIDTH(new_w)*2+LABEL_SHADOW_THICKNESS(new_w)*2+
+EHT(new_w)*2+(Dimension)(BOLD_LABELS(new_w)?1:0);
}
ROW_IS_SELECTED_ARRAY(new_w)=
(Boolean*)XtMalloc(sizeof(Boolean)*ROW_COUNT(new_w));
SELECTED_ROWS(new_w)=(int*)XtMalloc(sizeof(int)*ROW_COUNT(new_w));
for(i=0;i<ROW_COUNT(new_w);i++){
ROW_IS_SELECTED(new_w,i)=FALSE;
SELECTED_ROW(new_w,i)=-1;
}
SELECTED_ROW_COUNT(new_w)=0;
ANCHOR(new_w)=-1;
LAST_SELECTED_ROW(new_w)=-1;
SCROLL_TIMER_SET(new_w)=FALSE;
SELECTION_DRAG(new_w)=FALSE;
if(WIDTH(req_w)==0){
WIDTH(new_w)=preferredWidth(new_w);
}
if(HEIGHT(req_w)==0){
HEIGHT(new_w)=preferredHeight(new_w);
}
VISIBLE_ROW_COUNT(new_w)=(HEIGHT(new_w)-
(SHOW_LABELS(new_w)?LABEL_HEIGHT(new_w):0)-
SHADOW_THICKNESS(new_w)*2-MARGIN_HEIGHT(new_w)*2)/(ROW_HEIGHT(new_w)+
ROW_SPACING(new_w)+EHT(new_w));
if(VISIBLE_ROW_COUNT(new_w)<0) VISIBLE_ROW_COUNT(new_w)=0;
if(XmIsScrolledWindow(XtParent(new_w))){
SCROLLED_WINDOW(new_w)=(XmScrolledWindowWidget)XtParent(new_w);
VERT_SB(new_w)=(XmScrollBarWidget)XtVaCreateWidget("VertScrollBar",
xmScrollBarWidgetClass, (Widget)SCROLLED_WINDOW(new_w),
XmNincrement,ROW_HEIGHT(new_w)+ROW_SPACING(new_w)+EHT(new_w),NULL);
XtSetMappedWhenManaged((Widget)VERT_SB(new_w),TRUE);
XtAddCallback((Widget)VERT_SB(new_w), XmNdecrementCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNdragCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNincrementCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNpageDecrementCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNpageIncrementCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNtoBottomCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNtoTopCallback,
vert_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)VERT_SB(new_w), XmNvalueChangedCallback,
vert_sb_cb, (XtPointer)new_w);
HOR_SB(new_w)=(XmScrollBarWidget)XtVaCreateWidget("HorScrollBar",
xmScrollBarWidgetClass, (Widget)SCROLLED_WINDOW(new_w),
XmNincrement,ROW_HEIGHT(new_w)+ROW_SPACING(new_w)+EHT(new_w),
XmNorientation, XmHORIZONTAL, NULL);
XtSetMappedWhenManaged((Widget)HOR_SB(new_w),TRUE);
XtAddCallback((Widget)HOR_SB(new_w), XmNdecrementCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNdragCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNincrementCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNpageDecrementCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNpageIncrementCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNtoBottomCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNtoTopCallback,
hor_sb_cb, (XtPointer)new_w);
XtAddCallback((Widget)HOR_SB(new_w), XmNvalueChangedCallback,
hor_sb_cb, (XtPointer)new_w);
XmScrolledWindowSetAreas((Widget)SCROLLED_WINDOW(new_w),
(Widget)HOR_SB(new_w),(Widget)VERT_SB(new_w),(Widget)new_w);
/*
XtAddEventHandler((Widget)SCROLLED_WINDOW(new_w),ExposureMask,FALSE,
resizeHelper, (XtPointer)new_w);
*/
}
RESIZING(new_w)=0;
RESIZING_VSB(new_w)=FALSE;
RESIZING_HSB(new_w)=FALSE;
RESIZE_TIMER_STARTED(new_w)=FALSE;
RESIZE_TIMER_SET(new_w)=FALSE;
createGCs(new_w);
BUFFER(new_w)=0;
}
static void Destroy(Widget w) {
int i;
XmFontListFree(FONT(w));
XmFontListFree(LABEL_FONT(w));
XFreeGC(XtDisplay(w),BACKGROUND_GC(w));
XFreeGC(XtDisplay(w),LABEL_BACKGROUND_GC(w));
XFreeGC(XtDisplay(w),LABEL_TOP_SHADOW_GC(w));
XFreeGC(XtDisplay(w),LABEL_BOTTOM_SHADOW_GC(w));
XFreeGC(XtDisplay(w),LABEL_DRAW_GC(w));
XFreeGC(XtDisplay(w),CELL_BACKGROUND_GC(w));
XFreeGC(XtDisplay(w),DRAW_GC(w));
XFreeGC(XtDisplay(w),SELECTED_BACKGROUND_GC(w));
XFreeGC(XtDisplay(w),SELECTED_DRAW_GC(w));
XtFree((char*)COLUMN_WIDTHS(w));
XtFree((char*)COLUMN_OFFSETS(w));
XtFree((char*)COLUMN_ALIGNMENTS(w));
XtFree((char*)COLUMN_LABEL_ALIGNMENTS(w));
XtFree((char*)SELECTED_ROWS(w));
XtFree((char*)ROW_IS_SELECTED_ARRAY(w));
for(i=0;i<COLUMN_COUNT(w);i++){
XtFree((char*)COLUMN_LABELS(w)[i]);
}
XtFree((char*)COLUMN_LABELS(w));
if(RESIZE_TIMER_SET(w)){
XtRemoveTimeOut(RESIZE_TIMER_ID(w));
}
if(BUFFER(w)){
XFreePixmap(XtDisplay(w),BUFFER(w));
}
if(SCROLLED_WINDOW(w) && (!BEING_DESTROYED(SCROLLED_WINDOW(w)))){
XtDestroyWidget((Widget)SCROLLED_WINDOW(w));
}
}
static void Resize(Widget w) {
Boolean hor_mc,vert_mc;
hor_mc=FALSE;
vert_mc=FALSE;
/*printf("In Resize() with %dx%d\n",WIDTH(w),HEIGHT(w));*/
/*
if(RESIZING(w)==0 &&
(XtIsManaged((Widget)HOR_SB(w)) || XtIsManaged((Widget)VERT_SB(w)))){
XtUnmanageChild((Widget)HOR_SB(w));
XtUnmanageChild((Widget)VERT_SB(w));
SCROLLED_WINDOW(w)->core.widget_class->core_class.resize(
(Widget)SCROLLED_WINDOW(w));
}
*/
RESIZING(w)++;
/*printf("RECURSIVITY=%d\n",RESIZING(w));*/
handleHorSB(w,&hor_mc);
handleVertSB(w,&vert_mc);
/*printf("In Resize: hor_mc=%d vert_mc=%d\n",hor_mc,vert_mc);*/
if(!RESIZE_TIMER_SET(w) || ((hor_mc || vert_mc) &&
RESIZE_TIMER_STARTED(w))){
RESIZE_TIMER_SET(w)=TRUE;
/*printf("Setting Time Out\n");*/
RESIZE_TIMER_ID(w)=XtAppAddTimeOut(XtWidgetToApplicationContext(w),0,resizeLater,
(XtPointer)w);
}
if(BUFFER(w)){
XFreePixmap(XtDisplay(w),BUFFER(w));
BUFFER(w)=0;
}
RESIZING(w)--;
}
static void Redisplay(Widget w, XEvent *event, Region region) {
XRectangle cr;
if(!XtIsRealized(w)) return;
if(!BUFFER(w)){
BUFFER(w)=XCreatePixmap(XtDisplay(w),RootWindowOfScreen(XtScreen(w)),
WIDTH(w),HEIGHT(w),DEPTH(w));
REDRAW_BUFFER(w)=TRUE;
}
if(REDRAW_BUFFER(w)) {
redrawList(w,BUFFER(w),NULL);
REDRAW_BUFFER(w)=FALSE;
}
if(region) XClipBox(region,&cr);
else {cr.x=0;cr.y=0;cr.width=WIDTH(w);cr.height=HEIGHT(w);}
XCopyArea(XtDisplay(w),BUFFER(w),XtWindow(w),BACKGROUND_GC(w),cr.x,cr.y,
cr.width,cr.height,cr.x,cr.y);
}
#define NE(field) \
(((XmAxyListWidget)wcur)->field != ((XmAxyListWidget)wnew)->field)
#define NB(field) \
((((XmAxyListWidget)wcur)->field && !((XmAxyListWidget)wnew)->field) ||\
(!((XmAxyListWidget)wcur)->field && ((XmAxyListWidget)wnew)->field))
static Boolean SetValues(Widget wcur, Widget wreq, Widget wnew,
ArgList args, Cardinal *num_args) {
Boolean redraw=FALSE;
Boolean layout=FALSE;
if(NE(list.font)){
FONT(wnew)=XmFontListCopy(FONT(wnew));
installFont(wnew);
layout=TRUE;
redraw=TRUE;
}
if(NE(list.label_font)){
LABEL_FONT(wnew)=XmFontListCopy(LABEL_FONT(wnew));
installLabelFont(wnew);
layout=TRUE;
redraw=TRUE;
}
if(NE(primitive.highlight_GC) || NE(primitive.top_shadow_GC) ||
NE(primitive.bottom_shadow_GC)){
redraw=TRUE;
}
if(NE(core.background_pixel)){
XFreeGC(XtDisplay(wnew),BACKGROUND_GC(wnew));
createBackgroundGC(wnew);
redraw=TRUE;
}
if(NE(list.label_background)){
XFreeGC(XtDisplay(wnew),LABEL_BACKGROUND_GC(wnew));
createLabelBackgroundGC(wnew);
redraw=TRUE;
}
if(NE(list.label_background) || NE(list.label_top_shadow_color) ||
NE(list.label_top_shadow_pixmap)){
XFreeGC(XtDisplay(wnew),LABEL_TOP_SHADOW_GC(wnew));
createLabelTopShadowGC(wnew);
redraw=TRUE;
}
if(NE(list.label_background) || NE(list.label_bottom_shadow_color) ||
NE(list.label_bottom_shadow_pixmap)){
XFreeGC(XtDisplay(wnew),LABEL_BOTTOM_SHADOW_GC(wnew));
createLabelBottomShadowGC(wnew);
redraw=TRUE;
}
if(NE(list.label_background) || NE(list.label_foreground) ||
NE(list.label_font_fid)){
XFreeGC(XtDisplay(wnew),LABEL_DRAW_GC(wnew));
createLabelDrawGC(wnew);
redraw=TRUE;
}
if(NE(list.cell_background)){
XFreeGC(XtDisplay(wnew),CELL_BACKGROUND_GC(wnew));
createCellBackgroundGC(wnew);
redraw=TRUE;
}
if(NE(list.cell_background) || NE(list.cell_foreground) ||
NE(list.font_fid)){
XFreeGC(XtDisplay(wnew),DRAW_GC(wnew));
createDrawGC(wnew);
redraw=TRUE;
}
if(NE(list.selected_background)){
XFreeGC(XtDisplay(wnew),SELECTED_BACKGROUND_GC(wnew));
createSelectedBackgroundGC(wnew);
redraw=TRUE;
}
if(NE(list.selected_background) || NE(list.selected_foreground) ||
NE(list.font_fid)){
XFreeGC(XtDisplay(wnew),SELECTED_DRAW_GC(wnew));
createSelectedDrawGC(wnew);
redraw=TRUE;
}
if(NE(list.margin_width) || NE(list.margin_height) ||
NE(list.cell_margin_width) || NE(list.cell_margin_height) ||
NE(list.label_margin_width) || NE(list.label_margin_height) ||
NE(list.label_shadow_thickness) || NE(list.row_spacing) ||
NE(primitive.highlight_thickness) || NE(primitive.shadow_thickness)){
layout=TRUE;
redraw=TRUE;
}
if(NE(list.string_dir)){
redraw=TRUE;
}
if(NB(list.bold_labels) || NB(list.show_labels)){
layout=TRUE;
redraw=TRUE;
}
if(NE(list.row_count)){
int i;
XtFree((char*)SELECTED_ROWS(wnew));
XtFree((char*)ROW_IS_SELECTED_ARRAY(wnew));
ROW_IS_SELECTED_ARRAY(wnew)=
(Boolean*)XtMalloc(sizeof(Boolean)*ROW_COUNT(wnew));
SELECTED_ROWS(wnew)=(int*)XtMalloc(sizeof(int)*ROW_COUNT(wnew));
for(i=0;i<ROW_COUNT(wnew);i++){
ROW_IS_SELECTED(wnew,i)=FALSE;
SELECTED_ROW(wnew,i)=-1;
}
SELECTED_ROW_COUNT(wnew)=0;
ANCHOR(wnew)=-1;
LAST_SELECTED_ROW(wnew)=-1;
SELECTION_DRAG(wnew)=FALSE;
layout=TRUE;
redraw=TRUE;
}
if(NE(list.column_widths)){
copyWidths(wnew);
layout=TRUE;
redraw=TRUE;
}
if(NE(list.column_labels)){
copyColumnLabels(wnew);
redraw=TRUE;
}
if(NE(list.column_alignments)){
copyColumnAlignments(wnew);
redraw=TRUE;
}
if(NE(list.column_label_alignments)){
copyColumnLabelAlignments(wnew);
redraw=TRUE;
}
if(NE(list.column_count)){
XtFree((char*)COLUMN_OFFSETS(wnew));
COLUMN_OFFSETS(wnew)=(int*)XtMalloc(sizeof(int)*(COLUMN_COUNT(wnew)+1));
layout=TRUE;
redraw=TRUE;
}
BORDER(wnew)=0;
if(layout){
int i;
int width=WIDTH(wnew),height=HEIGHT(wnew);
if(HEIGHT(wcur)==HEIGHT(wnew)) {
height=preferredHeight(wnew);
}
if(WIDTH(wcur)==WIDTH(wnew)) width=preferredWidth(wnew);
HOR_SHIFT(wnew)=0;
VERT_SHIFT(wnew)=0;
VISIBLE_ROW_COUNT(wnew)=(HEIGHT(wnew)-
(SHOW_LABELS(wnew)?LABEL_HEIGHT(wnew):0)-
SHADOW_THICKNESS(wnew)*2-MARGIN_HEIGHT(wnew)*2)/(ROW_HEIGHT(wnew)+
ROW_SPACING(wnew)+EHT(wnew));
if(VISIBLE_ROW_COUNT(wnew)<0) VISIBLE_ROW_COUNT(wnew)=0;
COLUMN_OFFSET(wnew,0)=SHADOW_THICKNESS(wnew)+MARGIN_WIDTH(wnew);
for(i=0;i<COLUMN_COUNT(wnew);i++){
COLUMN_OFFSET(wnew,i+1)=COLUMN_OFFSET(wnew,i)+
LABEL_FONT_WIDTH(wnew)*COLUMN_WIDTHS(wnew)[i]+
LABEL_MARGIN_WIDTH(wnew)*2+LABEL_SHADOW_THICKNESS(wnew)*2+
+EHT(wnew)*2+(Dimension)(BOLD_LABELS(wnew)?1:0);
}
if(VERT_SB(wnew))
XtVaSetValues((Widget)VERT_SB(wnew),
XmNincrement,ROW_HEIGHT(wnew)+ROW_SPACING(wnew)+EHT(wnew),NULL);
if(HOR_SB(wnew))
XtVaSetValues((Widget)HOR_SB(wnew),
XmNincrement,ROW_HEIGHT(wnew)+ROW_SPACING(wnew)+EHT(wnew),NULL);
WIDTH(wnew)=WIDTH(wcur);
HEIGHT(wnew)=HEIGHT(wcur);
Resize(wnew);
WIDTH(wnew)=width;
HEIGHT(wnew)=height;
redraw=TRUE;
}
if(redraw){
REDRAW_BUFFER(wnew)=TRUE;
}
return redraw;
}
#undef NE
#undef NB
static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *proposed,
XtWidgetGeometry *answer) {
Dimension ret_width,pref_width;
answer->request_mode = (CWWidth | CWHeight);
ret_width=WIDTH(w);
pref_width=preferredWidth(w);
if(SIZE_POLICY(w) == XmRESIZE_IF_POSSIBLE ||
(SIZE_POLICY(w) == XmVARIABLE && pref_width>ret_width)){
ret_width=pref_width;
}
answer->height=preferredHeight(w);
answer->width=ret_width;
if(((proposed->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
&& proposed->width==answer->width && proposed->height==answer->height)
return XtGeometryYes;
else if(answer->width == WIDTH(w) &&
answer->height == HEIGHT(w))
return XtGeometryNo;
else
return XtGeometryAlmost;
}
static int figureColToResize(Widget w,Position x,Position y){
Dimension label_height;
int i,col_x;
label_height=SHOW_LABELS(w)?LABEL_HEIGHT(w):RESIZE_STRIP_WITH_HIDDEN_LABELS;
if(y<SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w)) return -1;
if(y>SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w)+label_height) return -1;
if(x<SHADOW_THICKNESS(w)+MARGIN_WIDTH(w)) return -1;
if(x>WIDTH(w)-MARGIN_WIDTH(w)-SHADOW_THICKNESS(w)) return -1;
for(i=0;i<COLUMN_COUNT(w);i++){
col_x=COLUMN_OFFSET(w,i+1)-HOR_SHIFT(w);
if(Abs(x-col_x)<=RESIZE_MARGIN) return i;
}
return -1;
}
static int XYToRow(Widget w,int x,int y){
int row;
if(y<(int)ROW_OFFSET(w,0)-(int)EHT(w) ||
y>=(int)HEIGHT(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_HEIGHT(w))return -1;
if(x<(int)SHADOW_THICKNESS(w)+(int)MARGIN_WIDTH(w) ||
x>(int)WIDTH(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_WIDTH(w) ||
x>(int)COLUMN_OFFSET(w,COLUMN_COUNT(w))-(int)HOR_SHIFT(w)) return -1;
y-=(ROW_OFFSET(w,-1)+ROW_HEIGHT(w)+EHT(w));
y+=VERT_SHIFT(w);
row=y/(ROW_HEIGHT(w)+ROW_SPACING(w)+EHT(w));
if(row<0) row=0;
if(row>=ROW_COUNT(w)) return -1;
return row;
}
static int XYToCol(Widget w,int x,int y){
int col;
if(y<(int)ROW_OFFSET(w,0)-(int)EHT(w) ||
y>=(int)HEIGHT(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_HEIGHT(w))return -1;
if(x<(int)SHADOW_THICKNESS(w)+(int)MARGIN_WIDTH(w) ||
x>(int)WIDTH(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_WIDTH(w) ||
x>(int)COLUMN_OFFSET(w,COLUMN_COUNT(w))-(int)HOR_SHIFT(w)) return -1;
x+=HOR_SHIFT(w);
for(col=0;col<COLUMN_COUNT(w);col++){
if(x<COLUMN_OFFSET(w,col+1)) return col;
}
return -1;
}
static void _XmAxyListBeginSelect(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
XButtonEvent *be=(XButtonEvent*)event;
int row;
if((SHOW_LABELS(w) && COLUMN_COUNT(w)>0) ||
(ROW_COUNT(w)>0 && COLUMN_COUNT(w)>0)){
XmProcessTraversal(w,XmTRAVERSE_CURRENT);
}
if(ROW_COUNT(w)==0 || COLUMN_COUNT(w)==0) return;
row=XYToRow(w,be->x,be->y);
if(row<0) return;
switch(SELECTION_POLICY(w)){
case XmEXTENDED_SELECT:
deselect_all(w);
select_row(w,row);
ANCHOR(w)=row;
break;
default:
return;
}
/*printf("Anchor=%d Last=%d\n",ANCHOR(w),LAST_SELECTED_ROW(w));*/
Redisplay(w,NULL,NULL);
return;
}
static void _XmAxyListEndSelect(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
XButtonEvent *be=(XButtonEvent*)event;
int row,col;
SELECTION_DRAG(w)=FALSE;
if(SCROLL_TIMER_SET(w)){
XtRemoveTimeOut(SCROLL_TIMER_ID(w));
SCROLL_TIMER_SET(w)=FALSE;
}
if((row=XYToRow(w,be->x,be->y))<0) return;
if((col=XYToCol(w,be->x,be->y))<0) return;
if(CLICK_COUNT(w)>0 && be->time<CLICK_TIME(w)+CLICK_INTERVAL(w)){
XmAxyListDefaultActionCallbackStruct cbs;
cbs.reason=XmAxyListDefaultActionReason;
cbs.event=event;
cbs.row=row;
cbs.column=col;
XtCallCallbackList(w,DEFAULT_CB_LIST(w),&cbs);
CLICK_COUNT(w)=0;
} else {
CLICK_TIME(w)=be->time;
CLICK_COUNT(w)=1;
}
}
static void _XmAxyListBeginToggle(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
XButtonEvent *be=(XButtonEvent*)event;
int row;
if((SHOW_LABELS(w) && COLUMN_COUNT(w)>0) ||
(ROW_COUNT(w)>0 && COLUMN_COUNT(w)>0)){
XmProcessTraversal(w,XmTRAVERSE_CURRENT);
}
if(ROW_COUNT(w)==0 || COLUMN_COUNT(w)==0) return;
if(SELECTION_POLICY(w)==XmEXTENDED_SELECT){
row=XYToRow(w,be->x,be->y);
if(row<0) return;
if(ROW_IS_SELECTED(w,row)){
deselect_row(w,row);
} else {
select_row(w,row);
}
ANCHOR(w)=row;
/*printf("Anchor=%d Last=%d\n",ANCHOR(w),LAST_SELECTED_ROW(w));*/
Redisplay(w,NULL,NULL);
}
return;
}
static void _XmAxyListEndToggle(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
SELECTION_DRAG(w)=FALSE;
}
static void _XmAxyListBeginExtend(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
XButtonEvent *be=(XButtonEvent*)event;
int row;
if((SHOW_LABELS(w) && COLUMN_COUNT(w)>0) ||
(ROW_COUNT(w)>0 && COLUMN_COUNT(w)>0)){
XmProcessTraversal(w,XmTRAVERSE_CURRENT);
}
if(ROW_COUNT(w)==0 || COLUMN_COUNT(w)==0) return;
if(SELECTION_POLICY(w)==XmEXTENDED_SELECT){
row=XYToRow(w,be->x,be->y);
if(row<0) return;
if(ANCHOR(w)>=0) {
change_select_range(w,row);
/*printf("Anchor=%d Last=%d\n",ANCHOR(w),LAST_SELECTED_ROW(w));*/
Redisplay(w,NULL,NULL);
}
}
return;
}
static void _XmAxyListEndExtend(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
SELECTION_DRAG(w)=FALSE;
}
#define SCROLL_DELAY 100
static void _XmAxyListButtonMotion(Widget w,XEvent *event,
String *parmas, Cardinal *num_params){
XButtonEvent *be=(XButtonEvent*)event;
int row;
if((SHOW_LABELS(w) && COLUMN_COUNT(w)>0) ||
(ROW_COUNT(w)>0 && COLUMN_COUNT(w)>0)){
XmProcessTraversal(w,XmTRAVERSE_CURRENT);
}
if(ROW_COUNT(w)==0 || COLUMN_COUNT(w)==0) return;
if(SELECTION_POLICY(w)==XmEXTENDED_SELECT){
if(be->y>=(int)HEIGHT(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_HEIGHT(w)){
if(SELECTION_DRAG(w) && !SCROLL_TIMER_SET(w)){
SCROLL_DIRECTION(w)=1;
SCROLL_TIMER_SET(w)=TRUE;
SCROLL_TIMER_ID(w)=XtAppAddTimeOut(XtWidgetToApplicationContext(w),
SCROLL_DELAY,scrollTimer,(XtPointer)w);
}
} else if(be->y<(int)ROW_OFFSET(w,0)-(int)EHT(w)){
if(SELECTION_DRAG(w) && !SCROLL_TIMER_SET(w)){
SCROLL_DIRECTION(w)=-1;
SCROLL_TIMER_SET(w)=TRUE;
SCROLL_TIMER_ID(w)=XtAppAddTimeOut(XtWidgetToApplicationContext(w),
SCROLL_DELAY,scrollTimer,(XtPointer)w);
}
} else {
if(SCROLL_TIMER_SET(w)){
XtRemoveTimeOut(SCROLL_TIMER_ID(w));
SCROLL_TIMER_SET(w)=FALSE;
}
row=XYToRow(w,be->x,be->y);
if(row<0) return;
SELECTION_DRAG(w)=TRUE;
if(LAST_SELECTED_ROW(w)!=row){
change_select_range(w,row);
Redisplay(w,NULL,NULL);
}
}
}
return;
}
static void scrollTimer(XtPointer w,XtIntervalId* id){
int shift;
XmScrollBarCallbackStruct cbs;
if((SCROLL_DIRECTION(w)==1 && VERT_SHIFT(w)==VERT_MAX(w)-VERT_SLIDER(w)) ||
(SCROLL_DIRECTION(w)==-1 && VERT_SHIFT(w)==0)){
SCROLL_TIMER_SET(w)=FALSE;
return;
}
if(SCROLL_DIRECTION(w)==1){
shift=VERT_SHIFT(w)+(ROW_HEIGHT(w)+EHT(w)+ROW_SPACING(w));
if(shift>VERT_MAX(w)-VERT_SLIDER(w)){
shift=VERT_MAX(w)-VERT_SLIDER(w);
}
change_select_range((Widget)w,LAST_SELECTED_ROW(w)+1);
} else {
shift=VERT_SHIFT(w)-(ROW_HEIGHT(w)+EHT(w)+ROW_SPACING(w));
if(shift<0){
shift=0;
}
change_select_range((Widget)w,LAST_SELECTED_ROW(w)-1);
}
XtVaSetValues((Widget)VERT_SB(w),XmNvalue,shift,NULL);
cbs.value=shift;
vert_sb_cb(NULL,(XtPointer)w,(XtPointer)&cbs);
SCROLL_TIMER_ID(w)=XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w),
SCROLL_DELAY,scrollTimer,(XtPointer)w);
return;
}
static void deselect_current_range(Widget w){
int i,last=LAST_SELECTED_ROW(w);
if(LAST_SELECTED_ROW(w)<0 || ANCHOR(w)<0) return;
if(LAST_SELECTED_ROW(w)>ANCHOR(w)){
for(i=ANCHOR(w)+1;i<=last && i<ROW_COUNT(w);i++){
deselect_row(w,i);
}
} else {
for(i=ANCHOR(w)-1;i>=last && i>=0;i--){
deselect_row(w,i);
}
}
}
static void change_select_range(Widget w,int row){
int i;
deselect_current_range(w);
if(row>ANCHOR(w)){
for(i=ANCHOR(w)+1;i<=row && i<ROW_COUNT(w);i++){
if(ROW_IS_SELECTED(w,ANCHOR(w))) select_row(w,i);
else deselect_row(w,i);
}
} else {
for(i=ANCHOR(w)-1;i>=row && i>=0;i--){
if(ROW_IS_SELECTED(w,ANCHOR(w))) select_row(w,i);
else deselect_row(w,i);
}
}
}
static void select_row(Widget w,int row){
int i;
if(row<0 || row>=ROW_COUNT(w)) return;
LAST_SELECTED_ROW(w)=row;
if(ROW_IS_SELECTED(w,row)) return;
ROW_IS_SELECTED(w,row)=TRUE;
if(SELECTION_POLICY(w)==XmSINGLE_SELECT ||
SELECTION_POLICY(w)==XmBROWSE_SELECT){
if(SELECTED_ROW_COUNT(w)>0){
ROW_IS_SELECTED(w,SELECTED_ROW(w,0))=FALSE;
}
SELECTED_ROW(w,0)=row;
SELECTED_ROW_COUNT(w)=1;
} else {
if(SELECTED_ROW_COUNT(w)==ROW_COUNT(w)) return;
for(i=0;i<SELECTED_ROW_COUNT(w);i++){
if(SELECTED_ROW(w,i)==row) return;
}
SELECTED_ROW(w,SELECTED_ROW_COUNT(w))=row;
SELECTED_ROW_COUNT(w)++;
}
REDRAW_BUFFER(w)=TRUE;
}
static void deselect_all(Widget w){
int i;
for(i=0;i<ROW_COUNT(w);i++){
ROW_IS_SELECTED(w,i)=FALSE;
SELECTED_ROW(w,i)=-1;
}
SELECTED_ROW_COUNT(w)=0;
LAST_SELECTED_ROW(w)=-1;
REDRAW_BUFFER(w)=TRUE;
}
static void deselect_row(Widget w,int row){
int i;
if(row<0 || row>=ROW_COUNT(w)) return;
if(!ROW_IS_SELECTED(w,row)) return;
ROW_IS_SELECTED(w,row)=FALSE;
if(SELECTION_POLICY(w)==XmSINGLE_SELECT ||
SELECTION_POLICY(w)==XmBROWSE_SELECT){
SELECTED_ROW(w,0)=-1;
SELECTED_ROW_COUNT(w)=0;
LAST_SELECTED_ROW(w)=-1;
} else {
for(i=0;i<SELECTED_ROW_COUNT(w);i++){
if(SELECTED_ROW(w,i)==row){
for(i++;i<SELECTED_ROW_COUNT(w);i++){
SELECTED_ROW(w,i-1)=SELECTED_ROW(w,i);
}
SELECTED_ROW_COUNT(w)--;
if(LAST_SELECTED_ROW(w)==row) LAST_SELECTED_ROW(w)=-1;
break;
}
}
}
REDRAW_BUFFER(w)=TRUE;
}
static void PointerMotion(Widget w, XEvent *event,
String *params, Cardinal *num_params) {
int col;
XMotionEvent *me;
if (event->type != MotionNotify) return;
me = (XMotionEvent *)event;
if(COL_RESIZE_UNDERWAY(w)) return;
/* just changing cursor ... */
col=figureColToResize(w,me->x,me->y);
if(col<0){
if(COL_RESIZE_AREA(w)){
COL_RESIZE_AREA(w)=FALSE;
XUndefineCursor(XtDisplay(w),XtWindow(w));
}
} else {
COL_RESIZE_NUM(w)=col;
if(!COL_RESIZE_AREA(w)){
COL_RESIZE_AREA(w)=TRUE;
XDefineCursor(XtDisplay(w),XtWindow(w),RESIZE_CURSOR(w));
}
}
return;
}
static void ButtonMotion(Widget w, XEvent *event,
String *params, Cardinal *num_params) {
XMotionEvent *me;
if (event->type != MotionNotify) return;
me = (XMotionEvent *)event;
if(!COL_RESIZE_UNDERWAY(w)) return;
drawResizeLine(w,me->x);
return;
}
static void ButtonUp(Widget w, XEvent *event,
String *params, Cardinal *num_params) {
XButtonEvent *be;
if (event->type != ButtonRelease) return;
be = (XButtonEvent *)event;
if(!COL_RESIZE_UNDERWAY(w)) return;
COL_RESIZE_UNDERWAY(w)=FALSE;
COL_RESIZE_AREA(w)=FALSE;
XUndefineCursor(XtDisplay(w),XtWindow(w));
/* do real resize stuff */
doColResize(w);
drawResizeLine(w,-1);
return;
}
static void ButtonDown(Widget w, XEvent *event,
String *params, Cardinal *num_params) {
XButtonEvent *be;
if (event->type != ButtonPress) return;
be = (XButtonEvent *)event;
if(!COL_RESIZE_AREA(w)) return;
COL_RESIZE_UNDERWAY(w)=TRUE;
COL_RESIZE_X(w)=-1;
drawResizeLine(w,be->x);
return;
}
static void doColResize(Widget w){
int col,i,delta;
col=COL_RESIZE_NUM(w);
delta=COL_RESIZE_X(w)-COLUMN_OFFSET(w,col+1)+HOR_SHIFT(w);
if(delta<0){
int max_offset=COL_RESIZE_X(w)+HOR_SHIFT(w)-COL_MIN_SIZE;
for(i=col;i>0;i--){
if(COLUMN_OFFSET(w,i)>max_offset){
COLUMN_OFFSET(w,i)=max_offset;
max_offset-=COL_MIN_SIZE;
if(max_offset<COLUMN_OFFSET(w,0)){
for(i=0;i<col;i++){
COLUMN_OFFSET(w,i+1)=COLUMN_OFFSET(w,i)+COL_MIN_SIZE;
}
delta=COLUMN_OFFSET(w,col)+COL_MIN_SIZE-COLUMN_OFFSET(w,col+1);
break;
}
} else {
break;
}
}
}
for(i=col;i<COLUMN_COUNT(w);i++){
COLUMN_OFFSET(w,i+1)+=delta;
}
REDRAW_BUFFER(w)=TRUE;
Resize(w);
Redisplay(w,NULL,NULL);
}
static void drawResizeLine(Widget w,Position x){
XRectangle r;
Region region;
if(COL_RESIZE_X(w)>=0 && COL_RESIZE_X(w)<WIDTH(w)){
/* erasing previous thing */
r.x=COL_RESIZE_X(w);
r.y=0;
r.width=1;
r.height=HEIGHT(w);
region=XCreateRegion();
XUnionRectWithRegion(&r,region,region);
Redisplay(w,NULL,region);
XDestroyRegion(region);
}
COL_RESIZE_X(w)=x;
if(COL_RESIZE_X(w)>=0 && COL_RESIZE_X(w)<WIDTH(w)){
XDrawLine(XtDisplay(w),XtWindow(w),HIGHLIGHT_GC(w),x,0,x,HEIGHT(w));
}
}
static void destroy_parent_cb(Widget w, XtPointer app,XtPointer call){
XtDestroyWidget(XtParent(w));
}
Widget XmAxyCreateList(Widget parent, char *name,
Arg *arglist, Cardinal argCount) {
return XtCreateWidget(name,xmAxyListWidgetClass,parent,arglist,argCount);
}
Widget XmAxyCreateScrolledList(Widget parent, char *name,
Arg *arglist, Cardinal argCount) {
Widget sw, list;
char *sn;
int n;
Arg *args;
sn = XtMalloc(strlen(name) + 3);
strcpy(sn, name);
strcat(sn, "SW");
args = (Arg *)XtCalloc(argCount + 4, sizeof(Arg));
for(n = 0;n<argCount;n++){
args[n].name=arglist[n].name;
args[n].value=arglist[n].value;
}
XtSetArg(args[n],XmNscrollingPolicy,XmAPPLICATION_DEFINED);n++;
XtSetArg(args[n],XmNvisualPolicy,XmVARIABLE);n++;
XtSetArg(args[n],XmNscrollBarDisplayPolicy,XmSTATIC);n++;
XtSetArg(args[n],XmNshadowThickness,0);n++;
sw=XtCreateManagedWidget(sn,xmScrolledWindowWidgetClass,parent,args,n);
XtFree((XtPointer)args);
XtFree((XtPointer)sn);
list=XtCreateWidget(name,xmAxyListWidgetClass,sw,arglist,argCount);
XtAddCallback(list,XmNdestroyCallback,destroy_parent_cb,(XtPointer)list);
if(XtIsRealized(parent)){
XtRealizeWidget(sw);
}
return list;
}
void XmAxyListRefresh(Widget w){
REDRAW_BUFFER(w)=TRUE;
Redisplay(w,NULL,NULL);
}
void XmAxyListDeselectAllRows(Widget w){
deselect_all(w);
Redisplay(w,NULL,NULL);
}
void XmAxyListDeselectRow(Widget w,int row){
deselect_row(w,row);
Redisplay(w,NULL,NULL);
}
void XmAxyListSelectRow(Widget w,int row){
select_row(w,row);
Redisplay(w,NULL,NULL);
}
Boolean XmAxyListRowSelected(Widget w,int row){
if(row<0 || row>ROW_COUNT(w)) return FALSE;
return ROW_IS_SELECTED(w,row);
}
Boolean XmAxyListGetSelectedRows(Widget w,int **selection,int* num){
int i;
*num=SELECTED_ROW_COUNT(w);
if(*num==0) return FALSE;
*selection=(int*)XtMalloc(sizeof(int)*SELECTED_ROW_COUNT(w));
for(i=0;i<*num;i++){
(*selection)[i]=SELECTED_ROW(w,i);
}
return TRUE;
}
static Dimension preferredWidth(Widget w){
return (Dimension)(COLUMN_OFFSET(w,COLUMN_COUNT(w))+
SHADOW_THICKNESS(w)+MARGIN_WIDTH(w));
}
static Dimension preferredHeight(Widget w){
Dimension height=0;
height=SHADOW_THICKNESS(w)*2+MARGIN_HEIGHT(w)*2;
if(COLUMN_LABELS(w)!=NULL && SHOW_LABELS(w)){
height+=LABEL_HEIGHT(w);
}
if(ROW_COUNT(w)>0){
height+=(EHT(w)+(ROW_HEIGHT(w)+EHT(w))*ROW_COUNT(w));
if(ROW_COUNT(w)>1){
height+=(ROW_SPACING(w)*(ROW_COUNT(w)-1));
}
}
return height;
}
static void copyWidths(Widget w){
short *copy=(short*)XtMalloc(sizeof(short)*COLUMN_COUNT(w));
int i;
for(i=0;i<COLUMN_COUNT(w);i++){
copy[i]=COLUMN_WIDTHS(w)[i];
}
COLUMN_WIDTHS(w)=copy;
}
static void copyColumnAlignments(Widget w){
unsigned char *copy=
(unsigned char*)XtMalloc(sizeof(unsigned char)*COLUMN_COUNT(w));
int i;
for(i=0;i<COLUMN_COUNT(w);i++){
copy[i]=COLUMN_ALIGNMENT(w,i);
}
COLUMN_ALIGNMENTS(w)=copy;
}
static void copyColumnLabelAlignments(Widget w){
unsigned char *copy=
(unsigned char*)XtMalloc(sizeof(unsigned char)*COLUMN_COUNT(w));
int i;
for(i=0;i<COLUMN_COUNT(w);i++){
copy[i]=COLUMN_LABEL_ALIGNMENT(w,i);
}
COLUMN_LABEL_ALIGNMENTS(w)=copy;
}
static void copyColumnLabels(Widget w){
String *copy=(String*)XtMalloc(sizeof(String)*COLUMN_COUNT(w));
int i;
for(i=0;i<COLUMN_COUNT(w);i++){
copy[i]=XtNewString(COLUMN_LABELS(w)[i]);
}
COLUMN_LABELS(w)=copy;
}
static void createBackgroundGC(Widget w){
XGCValues values;
values.foreground=BACKGROUND(w);
BACKGROUND_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground, &values);
}
static void createLabelBackgroundGC(Widget w){
XGCValues values;
values.foreground=LABEL_BACKGROUND(w);
LABEL_BACKGROUND_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground, &values);
}
static void createLabelTopShadowGC(Widget w){
XGCValues values;
values.foreground=LABEL_TOP_SHADOW_COLOR(w);
values.background=LABEL_BACKGROUND(w);
values.line_width=1;
values.line_style=LineSolid;
values.join_style=JoinMiter;
values.cap_style=CapButt;
if(LABEL_TOP_SHADOW_PIXMAP(w)!=None &&
LABEL_TOP_SHADOW_PIXMAP(w)!=XmUNSPECIFIED_PIXMAP){
values.tile=LABEL_TOP_SHADOW_PIXMAP(w);
values.fill_style=FillTiled;
LABEL_TOP_SHADOW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
GCJoinStyle | GCTile | GCFillStyle, &values);
} else {
LABEL_TOP_SHADOW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
GCJoinStyle, &values);
}
}
static void createLabelBottomShadowGC(Widget w){
XGCValues values;
values.foreground=LABEL_BOTTOM_SHADOW_COLOR(w);
values.background=LABEL_BACKGROUND(w);
values.line_width=1;
values.line_style=LineSolid;
values.join_style=JoinMiter;
values.cap_style=CapButt;
if(LABEL_BOTTOM_SHADOW_PIXMAP(w)!=None &&
LABEL_BOTTOM_SHADOW_PIXMAP(w)!=XmUNSPECIFIED_PIXMAP){
values.tile=LABEL_BOTTOM_SHADOW_PIXMAP(w);
values.fill_style=FillTiled;
LABEL_BOTTOM_SHADOW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
GCJoinStyle | GCTile | GCFillStyle, &values);
} else {
LABEL_BOTTOM_SHADOW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
GCJoinStyle, &values);
}
}
static void createLabelDrawGC(Widget w){
XGCValues values;
values.foreground=LABEL_FOREGROUND(w);
values.background=LABEL_BACKGROUND(w);
values.font=LABEL_FONT_FID(w);
LABEL_DRAW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCFont, &values);
}
static void createCellBackgroundGC(Widget w){
XGCValues values;
values.foreground=CELL_BACKGROUND(w);
CELL_BACKGROUND_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground, &values);
}
static void createDrawGC(Widget w){
XGCValues values;
values.foreground=CELL_FOREGROUND(w);
values.background=CELL_BACKGROUND(w);
values.font=FONT_FID(w);
DRAW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCFont, &values);
}
static void createSelectedBackgroundGC(Widget w){
XGCValues values;
values.foreground=SELECTED_BACKGROUND(w);
SELECTED_BACKGROUND_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground, &values);
}
static void createSelectedDrawGC(Widget w){
XGCValues values;
values.foreground=SELECTED_FOREGROUND(w);
values.background=SELECTED_BACKGROUND(w);
values.font=FONT_FID(w);
SELECTED_DRAW_GC(w)=XCreateGC(XtDisplay(w),
RootWindowOfScreen(XtScreen(w)),
GCForeground | GCBackground | GCFont, &values);
}
static void createGCs(Widget w){
createBackgroundGC(w);
createLabelBackgroundGC(w);
createLabelTopShadowGC(w);
createLabelBottomShadowGC(w);
createLabelDrawGC(w);
createCellBackgroundGC(w);
createDrawGC(w);
createSelectedBackgroundGC(w);
createSelectedDrawGC(w);
}
static void hor_sb_cb(Widget w,XtPointer app,XtPointer call){
Widget list=(Widget)app;
XmScrollBarCallbackStruct *cbs=(XmScrollBarCallbackStruct*)call;
int delta=cbs->value-HOR_SHIFT(list),x;
XRectangle cr,r;
if(delta==0) {
return;
}
if(!XtIsRealized(list) || !BUFFER(list) || REDRAW_BUFFER(list)){
HOR_SHIFT(list)=cbs->value;
Redisplay(list,NULL,NULL);
return;
}
cr.x=SHADOW_THICKNESS(list)+MARGIN_WIDTH(list)+EHT(list);
cr.y=SHADOW_THICKNESS(list)+MARGIN_HEIGHT(list);
cr.width=x=WIDTH(list)-SHADOW_THICKNESS(list)*2-
MARGIN_WIDTH(list)*2-EHT(list)*2;
if(x<0)cr.width=0;
cr.height=x=HEIGHT(list)-SHADOW_THICKNESS(list)*2-MARGIN_HEIGHT(list)*2;
if(x<0)cr.height=0;
if(delta>0){
if(delta<cr.width){
XCopyArea(XtDisplay(list),BUFFER(list),BUFFER(list),BACKGROUND_GC(list),
cr.x+delta,cr.y,cr.width-delta,cr.height,cr.x,cr.y);
r.x=cr.x+cr.width-delta;
r.y=cr.y;
r.width=delta;
r.height=cr.height;
} else {
r.x=cr.x;r.y=cr.y;r.width=cr.width;r.height=cr.height;
}
} else {
if(-delta<cr.width){
XCopyArea(XtDisplay(list),BUFFER(list),BUFFER(list),BACKGROUND_GC(list),
cr.x,cr.y,cr.width+delta,cr.height,cr.x-delta,cr.y);
r.x=cr.x;
r.y=cr.y;
r.width=-delta;
r.height=cr.height;
} else {
r.x=cr.x;r.y=cr.y;r.width=cr.width;r.height=cr.height;
}
}
HOR_SHIFT(list)=cbs->value;
redrawList(list,BUFFER(list),&r);
XCopyArea(XtDisplay(list),BUFFER(list),XtWindow(list),BACKGROUND_GC(list),
cr.x,cr.y,cr.width,cr.height,cr.x,cr.y);
return;
}
static void vert_sb_cb(Widget w,XtPointer app,XtPointer call){
Widget list=(Widget)app;
XmScrollBarCallbackStruct *cbs=(XmScrollBarCallbackStruct*)call;
int x,delta=cbs->value-VERT_SHIFT(list);
XRectangle cr,r;
if(delta==0) {
return;
}
if(!XtIsRealized(list) || !BUFFER(list) || REDRAW_BUFFER(list)){
VERT_SHIFT(list)=cbs->value;
Redisplay(list,NULL,NULL);
return;
}
cr.x=SHADOW_THICKNESS(list)+MARGIN_WIDTH(list);
cr.y=SHADOW_THICKNESS(list)+MARGIN_HEIGHT(list)+
(SHOW_LABELS(list)?LABEL_HEIGHT(list):(Dimension)0);
cr.width=x=WIDTH(list)-SHADOW_THICKNESS(list)*2-MARGIN_WIDTH(list)*2;
if(x<0)cr.width=0;
cr.height=x=HEIGHT(list)-SHADOW_THICKNESS(list)-cr.y-MARGIN_WIDTH(list)*2;
if(x<0)cr.height=0;
if(delta>0){
if(delta<cr.height){
XCopyArea(XtDisplay(list),BUFFER(list),BUFFER(list),BACKGROUND_GC(list),
cr.x,cr.y+delta,cr.width,cr.height-delta,cr.x,cr.y);
r.x=cr.x;
r.y=cr.y+cr.height-delta;
r.width=cr.width;
r.height=delta;
} else {
r.x=cr.x;r.y=cr.y;r.width=cr.width;r.height=cr.height;
}
} else {
if(-delta<cr.height){
XCopyArea(XtDisplay(list),BUFFER(list),BUFFER(list),BACKGROUND_GC(list),
cr.x,cr.y,cr.width,cr.height+delta,cr.x,cr.y-delta);
r.x=cr.x;
r.y=cr.y;
r.width=cr.width;
r.height=-delta;
} else {
r.x=cr.x;r.y=cr.y;r.width=cr.width;r.height=cr.height;
}
}
VERT_SHIFT(list)=cbs->value;
redrawList(list,BUFFER(list),&r);
XCopyArea(XtDisplay(list),BUFFER(list),XtWindow(list),BACKGROUND_GC(list),
cr.x,cr.y,cr.width,cr.height,cr.x,cr.y);
return;
}
static void redrawList(Widget w,Drawable d,XRectangle *cr){
XRectangle bcr,margin;
int x;
if(cr==NULL){
cr=&bcr;cr->x=0;cr->y=0;cr->width=WIDTH(w);cr->height=HEIGHT(w);
}
XFillRectangle(XtDisplay(w),d,BACKGROUND_GC(w),
cr->x,cr->y,cr->width,cr->height);
margin.x=SHADOW_THICKNESS(w)+MARGIN_WIDTH(w);
margin.y=SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w);
margin.width=x=WIDTH(w)-SHADOW_THICKNESS(w)*2-MARGIN_WIDTH(w)*2;
if(x<0)margin.width=0;
margin.height=x=HEIGHT(w)-SHADOW_THICKNESS(w)*2-MARGIN_HEIGHT(w)*2;
if(x<0)margin.height=0;
axyRectanglesIntersection(cr,&margin,&margin);
drawLabels(w,d,&margin);
drawCells(w,d,&margin);
if(cr->x>SHADOW_THICKNESS(w) &&
cr->x+cr->width<WIDTH(w)-SHADOW_THICKNESS(w) &&
cr->y>SHADOW_THICKNESS(w) &&
cr->y+cr->height<HEIGHT(w)-SHADOW_THICKNESS(w)) return;
else
_XmDrawShadows(XtDisplay(w),d,
TOP_SHADOW_GC(w),BOTTOM_SHADOW_GC(w),
0,0,WIDTH(w),HEIGHT(w),
SHADOW_THICKNESS(w),XmSHADOW_IN);
}
static void installFont(Widget new_w){
XmFontContext context;
XFontStruct *font;
XmFontListEntry font_list_entry;
XmFontType type;
XFontSetExtents *extents;
XFontStruct **fonts;
char **font_names;
XmFontListInitFontContext(&context, LABEL_FONT(new_w));
font_list_entry = XmFontListNextEntry(context);
font = (XFontStruct*)XmFontListEntryGetFont(font_list_entry, &type);
if(type == XmFONT_IS_FONTSET){
extents = XExtentsOfFontSet((XFontSet)font);
FONT_WIDTH(new_w) = extents->max_logical_extent.width;
FONT_HEIGHT(new_w) = extents->max_logical_extent.height;
FONT_Y(new_w) = -extents->max_logical_extent.y;
XFontsOfFontSet((XFontSet)font, &fonts, &font_names);
FONT_FID(new_w) = fonts[0]->fid;
FONT_STRUCT(new_w) = fonts[0];
FONT_SET(new_w) = (XFontSet)font;
} else {
FONT_WIDTH(new_w) =
(font->max_bounds.width + font->min_bounds.width) /2;
FONT_HEIGHT(new_w) =
(font->max_bounds.descent + font->max_bounds.ascent);
FONT_Y(new_w) = font->max_bounds.ascent;
FONT_FID(new_w) = font->fid;
FONT_STRUCT(new_w) = font;
FONT_SET(new_w) = (XFontSet)NULL;
}
XmFontListFreeFontContext(context);
}
static void installLabelFont(Widget new_w){
XmFontContext context;
XFontStruct *font;
XmFontListEntry font_list_entry;
XmFontType type;
XFontSetExtents *extents;
XFontStruct **fonts;
char **font_names;
XmFontListInitFontContext(&context, LABEL_FONT(new_w));
font_list_entry = XmFontListNextEntry(context);
font = (XFontStruct*)XmFontListEntryGetFont(font_list_entry, &type);
if (type == XmFONT_IS_FONTSET){
extents = XExtentsOfFontSet((XFontSet)font);
LABEL_FONT_WIDTH(new_w) = extents->max_logical_extent.width;
LABEL_FONT_HEIGHT(new_w) = extents->max_logical_extent.height;
LABEL_FONT_Y(new_w) = -extents->max_logical_extent.y;
XFontsOfFontSet((XFontSet)font, &fonts, &font_names);
LABEL_FONT_FID(new_w) = fonts[0]->fid;
LABEL_FONT_STRUCT(new_w) = fonts[0];
LABEL_FONT_SET(new_w) = (XFontSet)font;
} else {
LABEL_FONT_WIDTH(new_w) =
(font->max_bounds.width + font->min_bounds.width) /2;
LABEL_FONT_HEIGHT(new_w) =
(font->max_bounds.descent + font->max_bounds.ascent);
LABEL_FONT_Y(new_w) = font->max_bounds.ascent;
LABEL_FONT_FID(new_w) = font->fid;
LABEL_FONT_STRUCT(new_w) = font;
LABEL_FONT_SET(new_w) = (XFontSet)NULL;
}
XmFontListFreeFontContext(context);
}
static void drawLabels(Widget w,Drawable d,XRectangle *cr){
int i,i0,i1,x;
XRectangle r,bcr;
if(!SHOW_LABELS(w)) return;
if(cr==NULL){
cr=&bcr; cr->x=0; cr->y=0; cr->width=WIDTH(w); cr->height=HEIGHT(w);
}
r.x=SHADOW_THICKNESS(w)+MARGIN_WIDTH(w)-HOR_SHIFT(w);
r.y=SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w);
r.width=x=
COLUMN_OFFSET(w,COLUMN_COUNT(w))-SHADOW_THICKNESS(w)-MARGIN_WIDTH(w);
if(x<0)r.width=0;
r.height=x=LABEL_HEIGHT(w);
if(x<0)r.height=0;
axyRectanglesIntersection(cr,&r,&r);
if(axyRectangleIsEmpty(&r)) return;
for(i=0;i<COLUMN_COUNT(w);i++){
if((int)COLUMN_OFFSET(w,i+1)-(int)HOR_SHIFT(w)>(int)r.x){
break;
}
}
i0=i;
for(i=i0;i<COLUMN_COUNT(w);i++){
if((int)COLUMN_OFFSET(w,i)-(int)HOR_SHIFT(w)>=(int)r.x+(int)r.width){
break;
}
}
i1=i;
XFillRectangle(XtDisplay(w),d,LABEL_BACKGROUND_GC(w),
r.x,r.y,r.width,r.height);
for(i=i0;i<i1;i++){
drawLabel(w,d,&r,i);
}
}
static void drawLabel(Widget w,Drawable d,XRectangle *cr,int i){
XRectangle r,clip;
int width,x;
r.x=COLUMN_OFFSET(w,i)+LABEL_SHADOW_THICKNESS(w)+EHT(w)+
LABEL_MARGIN_WIDTH(w)-HOR_SHIFT(w);
r.y=SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w)+LABEL_SHADOW_THICKNESS(w)+EHT(w)+
LABEL_MARGIN_HEIGHT(w);
r.width=x=COLUMN_OFFSET(w,i+1)-COLUMN_OFFSET(w,i)-
LABEL_SHADOW_THICKNESS(w)*2-EHT(w)*2-LABEL_MARGIN_WIDTH(w)*2;
if(x<0)r.width=0;
r.height=x=LABEL_HEIGHT(w)-LABEL_SHADOW_THICKNESS(w)*2-EHT(w)*2-
LABEL_MARGIN_HEIGHT(w)*2;
if(x<0)r.height=0;
axyRectanglesIntersection(cr,&r,&clip);
if(!axyRectangleIsEmpty(&clip)){
width=XTextWidth(LABEL_FONT_STRUCT(w),
COLUMN_LABEL(w,i),strlen(COLUMN_LABEL(w,i)));
if(COLUMN_LABEL_ALIGNMENT(w,i)==XmALIGNMENT_END){
x=(int)r.x+(int)r.width-width;
} else if(COLUMN_LABEL_ALIGNMENT(w,i)==XmALIGNMENT_CENTER){
x=(int)r.x+(int)r.width/2-width/2;
} else {
x=(int)r.x;
}
XSetClipRectangles(XtDisplay(w),LABEL_DRAW_GC(w),0,0,&clip,1,Unsorted);
XDrawString(XtDisplay(w),d,LABEL_DRAW_GC(w),
x,r.y+LABEL_FONT_Y(w),
COLUMN_LABELS(w)[i],strlen(COLUMN_LABELS(w)[i]));
XSetClipMask(XtDisplay(w),LABEL_DRAW_GC(w),None);
}
XSetClipRectangles(XtDisplay(w),LABEL_TOP_SHADOW_GC(w),
0,0,cr,1,Unsorted);
XSetClipRectangles(XtDisplay(w),LABEL_BOTTOM_SHADOW_GC(w),
0,0,cr,1,Unsorted);
_XmDrawShadows(XtDisplay(w),d,
LABEL_TOP_SHADOW_GC(w),LABEL_BOTTOM_SHADOW_GC(w),
COLUMN_OFFSET(w,i)-HOR_SHIFT(w),
SHADOW_THICKNESS(w)+MARGIN_HEIGHT(w),
COLUMN_OFFSET(w,i+1)-COLUMN_OFFSET(w,i),
LABEL_HEIGHT(w),
LABEL_SHADOW_THICKNESS(w),XmSHADOW_OUT);
XSetClipMask(XtDisplay(w),LABEL_TOP_SHADOW_GC(w),None);
XSetClipMask(XtDisplay(w),LABEL_BOTTOM_SHADOW_GC(w),None);
}
static void drawCells(Widget w,Drawable d,XRectangle *cr){
int i0,i1,j0,j1,i,j,x,y;
XRectangle r,bcr;
if(ROW_COUNT(w)<=0 || COLUMN_COUNT(w)<=0) return;
if(cr==NULL){
cr=&bcr; cr->x=0; cr->y=0; cr->width=WIDTH(w); cr->height=HEIGHT(w);
}
/*printf("ClipBox=%dx%d+%d+%d\n",cr->width,cr->height,cr->x,cr->y);*/
r.x=SHADOW_THICKNESS(w)+MARGIN_WIDTH(w);
r.y=ROW_OFFSET(w,0)-EHT(w);
x=COLUMN_OFFSET(w,COLUMN_COUNT(w))-HOR_SHIFT(w);
y=ROW_OFFSET(w,ROW_COUNT(w))-ROW_SPACING(w)-VERT_SHIFT(w);
x=Min(x,cr->x+cr->width);
y=Min(y,cr->y+cr->height);
r.width=x-r.x;
r.height=y-r.y;
axyRectanglesIntersection(cr,&r,&r);
if(axyRectangleIsEmpty(&r)) return;
/*printf("CellClip=%dx%d+%d+%d\n",rect.width,rect.height,rect.x,rect.y);*/
for(i=0;i<COLUMN_COUNT(w);i++){
if((int)COLUMN_OFFSET(w,i+1)-(int)HOR_SHIFT(w)>(int)r.x){
break;
}
}
i0=i;
for(i=i0;i<COLUMN_COUNT(w);i++){
if((int)COLUMN_OFFSET(w,i)-(int)HOR_SHIFT(w)>=(int)r.x+(int)r.width){
break;
}
}
i1=i;
for(j=0;j<ROW_COUNT(w);j++){
if((int)ROW_OFFSET(w,j+1)-(int)VERT_SHIFT(w)>(int)r.y){
break;
}
}
j0=j;
for(j=j0;j<ROW_COUNT(w);j++){
if((int)ROW_OFFSET(w,j)-(int)VERT_SHIFT(w)>=(int)r.y+(int)r.height){
break;
}
}
j1=j;
/*printf("COL: %d - %d ROW: %d - %d \n",i0,i1,j0,j1);*/
XFillRectangle(XtDisplay(w),d,CELL_BACKGROUND_GC(w),
r.x,r.y,r.width,r.height);
drawSelection(w,d,&r,j0,j1);
for(i=i0;i<i1;i++){
for(j=j0;j<j1;j++){
drawCell(w,d,&r,i,j);
}
}
}
static void drawSelection(Widget w,Drawable d,XRectangle *cr,int j0,int j1){
int j,tmp;
XRectangle r;
for(j=j0;j<j1;j++){
if(!ROW_IS_SELECTED(w,j)) continue;
r.y=ROW_OFFSET(w,j)-VERT_SHIFT(w);
r.height=ROW_HEIGHT(w);
tmp=ROW_OFFSET(w,0)-EHT(w);
if(r.y<tmp) {
tmp-=r.y;
r.y+=tmp;
if(tmp<r.height) r.height-=tmp;
else r.height=0;
}
tmp=(int)HEIGHT(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_HEIGHT(w);
if((int)r.y+(int)r.height>=tmp){
tmp-=((int)r.y+(int)r.height);
if(tmp<r.height) r.height-=tmp;
else r.height=0;
}
r.x=SHADOW_THICKNESS(w)+MARGIN_WIDTH(w)+EHT(w);
tmp=Min(COLUMN_OFFSET(w,COLUMN_COUNT(w))-HOR_SHIFT(w),
(int)WIDTH(w)-(int)SHADOW_THICKNESS(w)-(int)MARGIN_WIDTH(w))-
(int)EHT(w);
tmp-=(int)r.x;
if(tmp<0)tmp=0;
r.width=tmp;
axyRectanglesIntersection(cr,&r,&r);
if(axyRectangleIsEmpty(&r)) continue;
XFillRectangle(XtDisplay(w),d,SELECTED_BACKGROUND_GC(w),
r.x,r.y,r.width,r.height);
}
}
static void drawCell(Widget w,Drawable d,XRectangle *cr,int i,int j){
XmAxyListDrawCellCallbackStruct cbs;
Window root;
int x,y,width;
unsigned int border;
XRectangle r,clip,pixr,pixr_trans,helper;
helper.y=0;
helper.height=HEIGHT(w);
helper.x=SHADOW_THICKNESS(w)+MARGIN_WIDTH(w)+EHT(w);
width=WIDTH(w)-SHADOW_THICKNESS(w)*2-MARGIN_WIDTH(w)*2-EHT(w)*2;
if(width>0) helper.width=width;
else helper.width=0;
axyRectanglesIntersection(cr,&helper,&helper);
cr=&helper;
r.x=COLUMN_OFFSET(w,i)+EHT(w)-HOR_SHIFT(w);
r.y=ROW_OFFSET(w,j)-VERT_SHIFT(w);
r.width=x=COLUMN_OFFSET(w,i+1)-COLUMN_OFFSET(w,i)-EHT(w)*2;
if(x<0)r.width=0;
r.height=ROW_HEIGHT(w);
if(!axyRectanglesIntersect(cr,&r)) return;
cbs.reason=XmAxyListDrawCellReason;
cbs.event=NULL;
cbs.column=i;
cbs.row=j;
cbs.is_xm_string=FALSE;
cbs.width=r.width;
cbs.height=r.height;
cbs.type=0;
cbs.string=NULL;
cbs.pixmap=(Pixmap)0;
cbs.pixmask=(Pixmap)0;
cbs.pixwidth=0;
cbs.pixheight=0;
cbs.pixdepth=0;
if(ROW_IS_SELECTED(w,j)){
cbs.foreground=SELECTED_FOREGROUND(w);
cbs.background=SELECTED_BACKGROUND(w);
} else {
cbs.foreground=CELL_FOREGROUND(w);
cbs.background=CELL_BACKGROUND(w);
}
XtCallCallbackList(w,DRAW_CB_LIST(w),(XtPointer)&cbs);
switch(cbs.type){
case XmSTRING:
r.x+=CELL_MARGIN_WIDTH(w);
r.y+=CELL_MARGIN_HEIGHT(w);
if(r.width<CELL_MARGIN_WIDTH(w)*2) r.width=0;
else r.width-=CELL_MARGIN_WIDTH(w)*2;
if(r.height<CELL_MARGIN_HEIGHT(w)*2) r.height=0;
else r.height-=CELL_MARGIN_HEIGHT(w)*2;
axyRectanglesIntersection(cr,&r,&clip);
if(axyRectangleIsEmpty(&clip)) break;
if(!cbs.is_xm_string){
width=XTextWidth(FONT_STRUCT(w),cbs.string,strlen(cbs.string));
if(COLUMN_ALIGNMENT(w,i)==XmALIGNMENT_END){
x=(int)r.width-width;
} else if(COLUMN_ALIGNMENT(w,i)==XmALIGNMENT_CENTER){
x=(int)r.width/2-width/2;
} else {
x=0;
}
XSetClipRectangles(XtDisplay(w),
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),
0,0,&clip,1,Unsorted);
XDrawString(XtDisplay(w),d,
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),
r.x+x,r.y+FONT_Y(w),
cbs.string,strlen(cbs.string));
XSetClipMask(XtDisplay(w),
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),None);
} else {
XSetClipRectangles(XtDisplay(w),
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),
0,0,&clip,1,Unsorted);
XmStringDraw(XtDisplay(w),d,FONT(w),(XmString)cbs.string,
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),
r.x,r.y,r.width,
COLUMN_ALIGNMENT(w,i),STRING_DIR(w),&clip);
XSetFont(XtDisplay(w),DRAW_GC(w),FONT_FID(w));
XSetClipMask(XtDisplay(w),
ROW_IS_SELECTED(w,j)?SELECTED_DRAW_GC(w):DRAW_GC(w),None);
}
break;
case XmPIXMAP:
axyRectanglesIntersection(cr,&r,&clip);
if(axyRectangleIsEmpty(&clip)) break;
if(cbs.pixwidth<=0 || cbs.pixdepth<=0 || cbs.pixheight<=0){
XGetGeometry(XtDisplay(w),cbs.pixmap,&root,&x,&y,
&cbs.pixwidth,&cbs.pixheight,&border,&cbs.pixdepth);
}
/* x,y are coords of the pixmap relative to the upper left corner
* of the cell */
if(COLUMN_ALIGNMENT(w,i)==XmALIGNMENT_END){
x=(int)r.width-(int)cbs.pixwidth;
} else if(COLUMN_ALIGNMENT(w,i)==XmALIGNMENT_CENTER){
x=(int)r.width/2-(int)cbs.pixwidth/2;
} else {
x=0;
}
y=(int)r.height/2-(int)cbs.pixheight/2;
/* pixr rectangle of the pixmap to copy after clipping on the cell */
pixr.x=(x<0)?(-x):0;
pixr.y=(y<0)?(-y):0;
pixr.width=Min(r.width,cbs.pixwidth);
pixr.height=Min(r.height,cbs.pixheight);
/* pixr_trans are the same rectangle, only in the "absolute" coords */
pixr_trans.x=pixr.x+r.x+x;
pixr_trans.y=pixr.y+r.y+y;
pixr_trans.width=pixr.width;
pixr_trans.height=pixr.height;
/* Now clip() it */
axyRectanglesIntersection(&pixr_trans,&clip,&clip);
/* so clip is the rect we want to put _part_ of the pixmap */
/* Now modify the rectangle in pixmap coords */
pixr.x+=(clip.x-pixr_trans.x);
pixr.y+=(clip.y-pixr_trans.y);
pixr.width=clip.width;
pixr.height=clip.height;
if(cbs.pixdepth>1){
if(cbs.pixmask){
XSetClipMask(XtDisplay(w),DRAW_GC(w),cbs.pixmask);
XSetClipOrigin(XtDisplay(w),DRAW_GC(w),r.x+x,r.y+y);
}
XCopyArea(XtDisplay(w),cbs.pixmap,d,DRAW_GC(w),
pixr.x,pixr.y,
pixr.width,pixr.height,
clip.x,clip.y);
} else {
XCopyPlane(XtDisplay(w),cbs.pixmap,d,DRAW_GC(w),
pixr.x,pixr.y,
pixr.width,pixr.height,
clip.x,clip.y,1L);
}
XSetClipMask(XtDisplay(w),DRAW_GC(w),None);
break;
default:
break;
}
}
static void handleVertSB(Widget w,Boolean* mc){
int ph;
/*if(RESIZING_VSB(w)) return;*/
RESIZING_VSB(w)=TRUE;
ph=(int)preferredHeight(w);
if(ph>HEIGHT(w)){
if(!XtIsManaged((Widget)VERT_SB(w))){
XtManageChild((Widget)VERT_SB(w));
*mc=TRUE;
}
VISIBLE_ROW_COUNT(w)=(HEIGHT(w)-(SHOW_LABELS(w)?LABEL_HEIGHT(w):0)-
SHADOW_THICKNESS(w)*2)/(ROW_HEIGHT(w)+ROW_SPACING(w)+EHT(w));
if(VISIBLE_ROW_COUNT(w)<0) VISIBLE_ROW_COUNT(w)=0;
VERT_MAX(w)=ph-HEIGHT(w);
VERT_SLIDER(w)=HEIGHT(w);
if(VERT_SLIDER(w)<6)VERT_SLIDER(w)=6;
VERT_MAX(w)=VERT_MAX(w)+VERT_SLIDER(w);
if(VISIBLE_ROW_COUNT(w)>1){
VERT_PAGE(w)=
(VISIBLE_ROW_COUNT(w)-1)*(ROW_HEIGHT(w)+ROW_SPACING(w)+EHT(w));
} else {
VERT_PAGE(w)=ROW_HEIGHT(w)+ROW_SPACING(w)+EHT(w);
}
if(VERT_PAGE(w)<1)VERT_PAGE(w)=1;
if(VERT_SHIFT(w)>VERT_MAX(w)-VERT_SLIDER(w))
VERT_SHIFT(w)=VERT_MAX(w)-VERT_SLIDER(w);
XtVaSetValues((Widget)VERT_SB(w),
XmNminimum,0,
XmNmaximum,VERT_MAX(w),
XmNsliderSize,VERT_SLIDER(w),
XmNpageIncrement,VERT_PAGE(w),
XmNvalue,VERT_SHIFT(w),
NULL);
} else {
VERT_SHIFT(w)=0;
VERT_SLIDER(w)=6;
VERT_MAX(w)=VERT_SLIDER(w);
VISIBLE_ROW_COUNT(w)=ROW_COUNT(w);
if(XtIsManaged((Widget)VERT_SB(w))){
XtUnmanageChild((Widget)VERT_SB(w));
*mc=TRUE;
}
}
/*
xmScrolledWindowWidgetClass->core_class.resize(
(Widget)SCROLLED_WINDOW(w));
*/
RESIZING_VSB(w)=FALSE;
}
static void handleHorSB(Widget w,Boolean* mc){
int pw;
/*if(RESIZING_HSB(w)) return;*/
RESIZING_HSB(w)=TRUE;
pw=(int)preferredWidth(w);
if(pw>WIDTH(w)){
if(!XtIsManaged((Widget)HOR_SB(w))){
XtManageChild((Widget)HOR_SB(w));
*mc=TRUE;
}
HOR_MAX(w)=pw-WIDTH(w);
HOR_SLIDER(w)=WIDTH(w);
if(HOR_SLIDER(w)<6)HOR_SLIDER(w)=6;
HOR_MAX(w)+=HOR_SLIDER(w);
HOR_PAGE(w)=WIDTH(w)-32;
if(HOR_PAGE(w)<1)HOR_PAGE(w)=1;
if(HOR_SHIFT(w)>HOR_MAX(w)-HOR_SLIDER(w))
HOR_SHIFT(w)=HOR_MAX(w)-HOR_SLIDER(w);
/*printf("Setting HOR_MAX=%d HOR_SLIDER=%d\n",HOR_MAX(w),HOR_SLIDER(w));*/
XtVaSetValues((Widget)HOR_SB(w),XmNmaximum,HOR_MAX(w),
XmNminimum,0,
XmNmaximum,HOR_MAX(w),
XmNsliderSize,HOR_SLIDER(w),
XmNpageIncrement,HOR_PAGE(w),
XmNvalue,HOR_SHIFT(w),
NULL);
} else {
HOR_SHIFT(w)=0;
HOR_SLIDER(w)=6;
HOR_MAX(w)=HOR_SLIDER(w);
if(XtIsManaged((Widget)HOR_SB(w))){
XtUnmanageChild((Widget)HOR_SB(w));
*mc=TRUE;
}
}
/*
xmScrolledWindowWidgetClass->core_class.resize(
(Widget)SCROLLED_WINDOW(w));
*/
RESIZING_HSB(w)=FALSE;
}
static void resizeLater(XtPointer w,XtIntervalId* id){
RESIZE_TIMER_STARTED(w)=TRUE;
RESIZING(w)++;
SCROLLED_WINDOW(w)->core.widget_class->core_class.resize(
(Widget)SCROLLED_WINDOW(w));
RESIZE_TIMER_SET(w)=FALSE;
RESIZING(w)--;
RESIZE_TIMER_STARTED(w)=FALSE;
}
syntax highlighted by Code2HTML, v. 0.9.1