home *** CD-ROM | disk | FTP | other *** search
- /* X11listitem - list items for X11 dialogs */
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- /***********************************************************************/
- /** **/
- /** General Includes and Definitions **/
- /** **/
- /***********************************************************************/
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
-
- #include "dialogs.h"
-
- extern Display *StX11Display();
- extern Point DialogStringSize();
- extern LVAL StX11ItemObject();
- extern char *checkstring();
-
- typedef struct {
- unsigned long fore, back;
- } ColorPair;
-
- extern LVAL s_internals;
-
- extern LVAL coerce_to_vector();
-
- /***********************************************************************/
- /** **/
- /** Global Variables **/
- /** **/
- /***********************************************************************/
-
- /* configuration parameters - should be set using the defaults database */
- extern XFontStruct *DialogFont;
- extern unsigned long DialogBorderColor;
- extern ColorPair DialogC;
- extern unsigned int list_border_width;
- extern int min_button_width;
-
- extern GC DialogGC, DialogRGC;
-
- extern XContext ObjectContext, ListFieldContext;
-
- /***********************************************************************/
- /** **/
- /** List Items **/
- /** **/
- /***********************************************************************/
-
- # define LIST_TEXT_PATTERN "MMMMMMMMMMMMMMM"
- # define LIST_LEAD 5
- # define LIST_PAD 15
- # define MAX_LIST_ROWS 12
- # define SCROLL_WIDTH 20
- # define DOUBLE_CLICK_TIME 1000
- # define DOUBLE_CLICK_MOVE 10
-
- /***********************************************************************/
- /** **/
- /** Double Click Detection **/
- /** **/
- /***********************************************************************/
-
- static int click_x, click_y, click_inited = FALSE;
- static Time click_time;
- Window click_win;
-
- static is_double_click(report)
- XEvent *report;
- {
- int result, x, y, del_x, del_y, del_time;
- Time time;
- Window win;
-
- x = report->xbutton.x;
- y = report->xbutton.y;
- time = report->xbutton.time;
- win = report->xbutton.window;
- if (click_inited) {
- del_x = (click_x < x) ? x - click_x : click_x - x;
- del_y = (click_y < y) ? y - click_y : click_y - y;
- del_time = (click_time < time) ? time - click_time : click_time - time;
- result = (click_win == win
- && del_x < DOUBLE_CLICK_MOVE
- && del_y < DOUBLE_CLICK_MOVE
- && del_time < DOUBLE_CLICK_TIME) ? TRUE : FALSE;
- }
- else result = FALSE;
-
- click_inited = ! result;
- click_x = x;
- click_y = y;
- click_time = time;
- click_win = win;
-
- return(result);
- }
-
- /***********************************************************************/
- /** **/
- /** Basic Size Calculations **/
- /** **/
- /***********************************************************************/
-
- static Point data_size(data)
- LVAL data;
- {
- Point sz;
- if (listp(data)) {
- sz.v = llength(data);
- sz.h = 1;
- }
- else if (simplevectorp(data)) {
- sz.v = getsize(data);
- sz.h = 1;
- }
- else if (matrixp(data)) {
- sz.v = getfixnum(getelement(displacedarraydim(data), 0));
- sz.h = getfixnum(getelement(displacedarraydim(data), 1));
- }
- else xlerror("bad list item data", data);
- return(sz);
- }
-
- static Point cell_size()
- {
- Point cellsz;
-
- cellsz = DialogStringSize(LIST_TEXT_PATTERN);
- cellsz.v += LIST_LEAD;
- cellsz.h += LIST_PAD;
- return(cellsz);
- }
-
- static max_cols(item)
- LVAL item;
- {
- LVAL columns = slot_value(item, s_columns);
-
- return((fixp(columns)) ? getfixnum(columns) : 1);
- }
-
- /***********************************************************************/
- /** **/
- /** Index Conversion **/
- /** **/
- /***********************************************************************/
-
- static field_index(dpy, win, vdims, ddims, offset)
- Display *dpy;
- Window win;
- Point vdims, ddims, offset;
- {
- int vis_index, index;
- Point vpoint, dpoint;
-
- if (XFindContext(dpy, win, ListFieldContext, &vis_index) != 0)
- xlfail("could not find field index");
- vis_index--; /* needed to avoid storing a zero - confuses som X's */
-
- vpoint.v = vis_index / vdims.h;
- vpoint.h = vis_index % vdims.h;
- dpoint.v = offset.v + vpoint.v;
- dpoint.h = offset.h + vpoint.h;
- index = dpoint.v * ddims.h + dpoint.h;
-
- return(index);
- }
-
- /***********************************************************************/
- /** **/
- /** Internal Data Represenation **/
- /** **/
- /***********************************************************************/
-
- make_internals(item)
- LVAL item;
- {
- LVAL internals, data;
- int cols, num_fields;
- Point dsize, vsize;
-
- data = slot_value(item, s_list_data);
- cols = max_cols(item);
- dsize = data_size(data);
- vsize.h = (dsize.h > cols) ? cols : dsize.h;
- vsize.v = (dsize.v > MAX_LIST_ROWS) ? MAX_LIST_ROWS : dsize.v;
- num_fields = vsize.h * vsize.v;
-
- internals = newvector(8);
- set_slot_value(item, s_internals, internals);
- setelement(internals, 0, PointToList(vsize));
- setelement(internals, 1, PointToList(dsize));
- setelement(internals, 2, (listp(data)) ? coerce_to_vector(data) : data);
- setelement(internals, 3, newvector(num_fields));
- setelement(internals, 4, integer_list_2(0, 0));
- setelement(internals, 5, NIL);
- setelement(internals, 6, NIL);
- setelement(internals, 7, NIL);
- }
-
- static Point visible_dims(internals)
- LVAL internals;
- {
- return(ListToPoint(getelement(internals, 0)));
- }
-
- static Point data_dims(internals)
- LVAL internals;
- {
- return(ListToPoint(getelement(internals, 1)));
- }
-
- static LVAL get_data(internals)
- LVAL internals;
- {
- return(getelement(internals, 2));
- }
-
- static LVAL get_fields(internals)
- LVAL internals;
- {
- return(getelement(internals, 3));
- }
-
- static Point get_offset(internals)
- LVAL internals;
- {
- return(ListToPoint(getelement(internals, 4)));
- }
-
- set_offset(internals, offset)
- LVAL internals;
- Point offset;
- {
- setelement(internals, 4, PointToList(offset));
- }
-
- static LVAL get_selection(internals)
- LVAL internals;
- {
- return(getelement(internals, 5));
- }
-
- static selection_index(internals)
- LVAL internals;
- {
- LVAL sel = get_selection(internals);
- Point ddims, psel;
-
- if (sel == NIL) return(-1);
- else if (fixp(sel)) return(getfixnum(sel));
- else {
- ddims = data_dims(internals);
- psel = ListToPoint(sel);
- return(ddims.h * psel.h + psel.v);
- }
- }
-
- static set_selection(item, val, index, use_val)
- LVAL item, val;
- int index, use_val;
- {
- Point ddims, p;
- LVAL internals;
-
- internals = slot_value(item, s_internals);
- if (use_val) setelement(internals, 5, val);
- else if (vectorp(get_data(internals)))
- setelement(internals, 5, cvfixnum((FIXTYPE) index));
- else {
- ddims = data_dims(internals);
- p.h = index / ddims.h;
- p.v = index % ddims.h;
- setelement(internals, 5, PointToList(p));
- }
- draw_fields(item);
- }
-
- static set_vscroll(internals, w, has)
- LVAL internals;
- Window w;
- int has;
- {
- setelement(internals, 6, (has) ? cvfixnum((FIXTYPE) w) : NIL);
- }
-
- static set_hscroll(internals, w, has)
- LVAL internals;
- Window w;
- int has;
- {
- setelement(internals, 7, (has) ? cvfixnum((FIXTYPE) w) : NIL);
- }
-
- static has_vscroll(internals)
- LVAL internals;
- {
- return(getelement(internals, 6) != NIL);
- }
-
- static has_hscroll(internals)
- LVAL internals;
- {
- return(getelement(internals, 7) != NIL);
- }
-
- static Window get_vscroll(internals)
- LVAL internals;
- {
- LVAL val = getelement(internals, 6);
- return(fixp(val) ? (Window) getfixnum(val) : None);
- }
-
- static Window get_hscroll(internals)
- LVAL internals;
- {
- LVAL val = getelement(internals, 7);
- return(fixp(val) ? (Window) getfixnum(val) : None);
- }
-
- /***********************************************************************/
- /** **/
- /** Drawing Routines **/
- /** **/
- /***********************************************************************/
-
- static draw_field_content(dpy, win, text, reversed)
- Display *dpy;
- Window win;
- char *text;
- int reversed;
- {
- Point ssz;
- int x, y, len;
- GC gc;
- unsigned long color;
-
- gc = (reversed) ? DialogRGC : DialogGC;
- color = (reversed) ? DialogC.fore : DialogC.back;
-
- XSetWindowBackground(dpy, win, color);
- XClearWindow(dpy, win);
- ssz = DialogStringSize(text);
- x = LIST_PAD / 2;
- y = LIST_LEAD / 2 + DialogFont->max_bounds.ascent;
- len = strlen(text);
- XDrawString(dpy, win, gc, x, y, text, len);
- XSetWindowBackground(dpy, win, DialogC.back);
- }
-
- static draw_fields(item)
- LVAL item;
- {
- Display *dpy = StX11Display();
- Window win;
- LVAL fields, internals, data;
- Point vdims, ddims, offset;
- char *text;
- int sel, i, j, k, index, num_fields;
-
- internals = slot_value(item, s_internals);
- data = arraydata(get_data(internals));
- fields = get_fields(internals);
- vdims = visible_dims(internals);
- ddims = data_dims(internals);
- offset = get_offset(internals);
- sel = selection_index(internals);
- num_fields = getsize(fields);
-
- for (i = 0, k = 0; i < vdims.v; i++) {
- for (j = 0; j < vdims.h && k < num_fields; j++, k++) {
- win = getfixnum(getelement(fields, k));
- index = (i + offset.v) * ddims.h + j + offset.h;
- text = checkstring(getelement(data, index));
- draw_field_content(dpy, win, text, sel == index);
- }
- }
- }
-
- /***********************************************************************/
- /** **/
- /** Event Handlers **/
- /** **/
- /***********************************************************************/
-
- static LVAL field_handler(report, modal)
- XEvent report;
- int modal;
- {
- Display *dpy = StX11Display();
- Window win;
- LVAL item, internals, data;
- LVAL result = NIL;
- Point vdims, ddims, offset;
- char *text;
- int sel, index;
-
- win = report.xany.window;
- item = StX11ItemObject(dpy, win);
- internals = slot_value(item, s_internals);
- data = arraydata(get_data(internals));
- vdims = visible_dims(internals);
- ddims = data_dims(internals);
- offset = get_offset(internals);
- sel = selection_index(internals);
-
- if (item != NIL) {
- switch (report.type) {
- case Expose:
- index = field_index(dpy, win, vdims, ddims, offset);
- text = checkstring(getelement(data, index));
- draw_field_content(dpy, win, text, sel == index);
- break;
- case ButtonPress:
- index = field_index(dpy, win, vdims, ddims, offset);
- set_selection(item, NIL, index, FALSE);
- if (is_double_click(&report))
- send_message_1L(item, sk_do_action, s_true);
- else
- send_message(item, sk_do_action);
- break;
- default:
- break;
- }
- }
- return(result);
- }
-
- static scroll_action(item, s, which, x, y)
- LVAL item;
- Window s;
- int which, x, y;
- {
- int is_h_scroll, val, max, page, pos, inc;
- Point size, offset, ddims, vdims, cellsz;
- LVAL internals;
- Window hscroll, vscroll;
- double side;
-
- internals = slot_value(item, s_internals);
- offset = get_offset(internals);
- ddims = data_dims(internals);
- vdims = visible_dims(internals);
- cellsz = cell_size();
- size.v = vdims.v * cellsz.v;
- size.h = vdims.h * cellsz.h;
- hscroll = get_hscroll(internals);
- vscroll = get_vscroll(internals);
-
- is_h_scroll = (s == hscroll) ? TRUE : FALSE;
- val = (is_h_scroll) ? offset.h : offset.v;
- max = (is_h_scroll) ? ddims.h : ddims.v;
- page = (is_h_scroll) ? vdims.h : vdims.v;
- side = (is_h_scroll) ? size.h : size.v;
- pos = (is_h_scroll) ? x * (max / side) : y * (max / side);
- inc = 1;
-
- switch (which) {
- case 'M': val = pos; break;
- case 'L': val += inc; break;
- case 'R': val -= inc; break;
- }
- if (val + page > max) val = max - page;
- if (val < 0) val = 0;
-
- if (is_h_scroll) offset.h = val;
- else offset.v = val;
- set_offset(internals, offset);
- draw_fields(item);
- if (hscroll != None) AdjustScrollBar(hscroll, offset.h, vdims.h, ddims.h);
- if (vscroll != None) AdjustScrollBar(vscroll, offset.v, vdims.v, ddims.v);
- }
-
- /***********************************************************************/
- /** **/
- /** Public Routines **/
- /** **/
- /***********************************************************************/
-
- DialogListGetDefaultSize(item, width, height)
- LVAL item;
- int *width, *height;
- {
- LVAL data = slot_value(item, s_list_data);
- Point sz, cellsz;
- int cols, m, n;
-
- cellsz = cell_size();
-
- cols = max_cols(item);
- sz = data_size(data);
- m = sz.v;
- n = sz.h;
-
- *height = (m <= MAX_LIST_ROWS) ? m * cellsz.v : MAX_LIST_ROWS * cellsz.v;
- *width = (n <= cols) ? n * cellsz.h : cols * cellsz.h;
- if (m > MAX_LIST_ROWS) *width += SCROLL_WIDTH;
- if (n > cols) *height += SCROLL_WIDTH;
- }
-
- InstallListItem(win, item)
- Window win;
- LVAL item;
- {
- Display *dpy = StX11Display();
- Point loc, vsize, size, cellsz, dsize;
- Window panel, newfield, scroll;
- LVAL s_window_id = xlenter("WINDOW-ID"), internals, fields;
- int num_fields, i, j, k;
-
- make_internals(item);
-
- internals = slot_value(item, s_internals);
- cellsz = cell_size();
- loc = ListToPoint(slot_value(item, s_location));
- vsize = visible_dims(internals);
- dsize = data_dims(internals);
- size.v = vsize.v * cellsz.v;
- size.h = vsize.h * cellsz.h;
- fields = get_fields(internals);
- num_fields = getsize(fields);
-
- panel = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v,
- list_border_width,
- DialogBorderColor, DialogC.back);
-
- set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) panel));
-
- if (XSaveContext(dpy, panel, ObjectContext, (XContext) item) != 0)
- xlfail("could not install object in window");
-
- if (dsize.h > vsize.h) {
- InstallScrollBar(win, item, loc.h, loc.v + size.v, size.h, SCROLL_WIDTH,
- &scroll, scroll_action);
- set_hscroll(internals, scroll, TRUE);
- AdjustScrollBar(scroll, 0, vsize.h, dsize.h);
- }
- if (dsize.v > vsize.v) {
- InstallScrollBar(win, item, loc.h + size.h, loc.v, SCROLL_WIDTH, size.v,
- &scroll, scroll_action);
- set_vscroll(internals, scroll, TRUE);
- AdjustScrollBar(scroll, 0, vsize.v, dsize.v);
- }
-
- for (i = 0, k = 0; i < vsize.v; i++) {
- for (j = 0; j < vsize.h && k < num_fields; j++, k++) {
- newfield = XCreateSimpleWindow(dpy, panel, cellsz.h * j, cellsz.v * i,
- cellsz.h, cellsz.v, 0,
- DialogBorderColor, DialogC.back);
-
- XSelectInput(dpy, newfield, ExposureMask | ButtonPressMask);
- install_dialog_item_handler(dpy, newfield, field_handler, item);
- if (XSaveContext(dpy, newfield, ObjectContext, (XContext) item) != 0)
- xlfail("could not install object in window");
-
- /* add 1 to index to avoid confusing context manager with zeros */
- if (XSaveContext(dpy, newfield, ListFieldContext, (k + 1)) != 0)
- xlfail("could not install field index in window");
- setelement(fields, k, cvfixnum((FIXTYPE) newfield));
- }
- }
- XMapSubwindows(dpy, panel);
- }
-
- DeleteListItem(win, item)
- Window win;
- LVAL item;
- {
- Display *dpy = StX11Display();
- Window panel, thefield;
- LVAL s_window_id = xlenter("WINDOW-ID"), internals, fields;
- int k, num_fields;
-
- panel = (Window) getfixnum(slot_value(item, s_window_id));
- internals = slot_value(item, s_internals);
- fields = get_fields(internals);
-
- num_fields = getsize(fields);
- for (k = 0; k < num_fields; k++) {
- thefield = getfixnum(getelement(fields, k));
- delete_dialog_item_handler(dpy, thefield);
- if (XDeleteContext(dpy, thefield, ObjectContext) != 0)
- xlfail("cound not delete object context");
- if (XDeleteContext(dpy, thefield, ListFieldContext) != 0)
- xlfail("cound not delete list field context");
- setelement(fields, k, NIL);
- }
-
- if (has_hscroll(internals)) DeleteScrollBar(get_hscroll(internals));
- if (has_vscroll(internals)) DeleteScrollBar(get_vscroll(internals));
-
- if (XDeleteContext(dpy, panel, ObjectContext) != 0)
- xlfail("cound not delete object context");
- set_slot_value(item, s_window_id, NIL);
- }
-
- DialogListItemSetText(item, index, text)
- LVAL item, index;
- char *text;
- {
- LVAL internals, data;
- Point p, ddims;
- int i;
-
- internals = slot_value(item, s_internals);
- data = arraydata(get_data(internals));
- if (fixp(index)) i = getfixnum(index);
- else {
- p = ListToPoint(index);
- ddims = data_dims(internals);
- i = p.v * ddims.h + p.h;
- }
- if (0 <= i && i < getsize(data))
- setelement(data, i, cvstring(text));
- else xlerror("index out of range", index);
- draw_fields(item);
- }
-
- LVAL DialogListItemSelection(item, set, index)
- LVAL item, index;
- int set;
- {
- if (set) set_selection(item, index, 0, TRUE);
- return(get_selection(slot_value(item, s_internals)));
- }
-