home *** CD-ROM | disk | FTP | other *** search
- /* X11dialogs - Low level dialog objects for X11 */
- /* 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 <stdio.h>
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
- #include <X11/cursorfont.h>
-
- #include "dialogs.h"
-
- extern Display *StX11Display();
-
- typedef struct {
- unsigned long fore, back;
- } ColorPair;
-
- /***********************************************************************/
- /** **/
- /** Global Variables **/
- /** **/
- /***********************************************************************/
-
- /* configuration parameters - should be set using the defaults database */
- static char *DialogFontName = "9x15";
- XFontStruct *DialogFont;
- unsigned long DialogBorderColor, ButtonBorderColor;
- ColorPair DialogC, ButtonC;
- unsigned int dialog_border_width, button_border_width, text_border_width,
- list_border_width;
- int min_button_height, min_button_width, min_toggle_height, min_choice_height,
- dialog_item_gap;
-
- GC DialogGC, DialogRGC;
-
- extern XContext EventContext, ObjectContext;
-
- #define TOGGLE_MARK_HEIGHT 16
- #define CHOICE_MARK_HEIGHT 16
-
- /* gray stipple pattern bitmap data for scroll bar thumb items */
- #define gray_width 16
- #define gray_height 16
- static char gray_bits[] = {
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa,
- 0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
- Pixmap ScrollThumbPM;
-
- /* toggle item bitmaps */
- #define toggle_off_width TOGGLE_MARK_HEIGHT
- #define toggle_off_height TOGGLE_MARK_HEIGHT
- static char toggle_off_bits[] = {
- 0xff, 0xff, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
- 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
- 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0xff, 0xff};
- Pixmap ToggleOffPM;
- #define toggle_on_width CHOICE_MARK_HEIGHT
- #define toggle_on_height CHOICE_MARK_HEIGHT
- static char toggle_on_bits[] = {
- 0xff, 0xff, 0x03, 0xc0, 0x05, 0xa0, 0x09, 0x90, 0x11, 0x88, 0x21, 0x84,
- 0x41, 0x82, 0x81, 0x81, 0x81, 0x81, 0x41, 0x82, 0x21, 0x84, 0x11, 0x88,
- 0x09, 0x90, 0x05, 0xa0, 0x03, 0xc0, 0xff, 0xff};
- Pixmap ToggleOnPM;
-
- /* choice item bitmaps */
- #define choice_off_width 16
- #define choice_off_height 16
- static char choice_off_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x08, 0x10,
- 0xe4, 0x27, 0x14, 0x28, 0x14, 0x28, 0x14, 0x28, 0x14, 0x28, 0x14, 0x28,
- 0x14, 0x28, 0xe4, 0x27, 0x08, 0x10, 0xf0, 0x0f};
- Pixmap ChoiceOffPM;
- #define choice_on_width 16
- #define choice_on_height 16
- static char choice_on_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x08, 0x10,
- 0xe4, 0x27, 0xf4, 0x2f, 0xf4, 0x2f, 0xf4, 0x2f, 0xf4, 0x2f, 0xf4, 0x2f,
- 0xf4, 0x2f, 0xe4, 0x27, 0x08, 0x10, 0xf0, 0x0f};
- Pixmap ChoiceOnPM;
-
- /* slider button pixmap */
- #define left_slider_width 16
- #define left_slider_height 16
- static char left_slider_bits[] = {
- 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0xfc, 0xff,
- 0xfe, 0xff, 0x01, 0x00, 0xfe, 0xff, 0xfc, 0xff, 0x08, 0x00, 0x10, 0x00,
- 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00};
- Pixmap LeftSliderPM;
- #define right_slider_width 16
- #define right_slider_height 16
- static char right_slider_bits[] = {
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0xff, 0x3f,
- 0xff, 0x7f, 0x00, 0x80, 0xff, 0x7f, 0xff, 0x3f, 0x00, 0x10, 0x00, 0x08,
- 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
- Pixmap RightSliderPM;
-
- extern Cursor ArrowCursor;
- Cursor DoubleArrowCursor, RightArrowCursor, LeftArrowCursor;
- Cursor UpDownArrowCursor, UpArrowCursor, DownArrowCursor;
-
- /***********************************************************************/
- /** **/
- /** Utility Functions **/
- /** **/
- /***********************************************************************/
-
- Point DialogStringSize(s)
- char *s;
- {
- Point pt;
-
- pt.v = DialogFont->max_bounds.ascent + DialogFont->max_bounds.descent;
- pt.h = XTextWidth(DialogFont,s, strlen(s));
-
- return(pt);
- }
-
- char *checkstring(s)
- LVAL s;
- {
- if (! stringp(s)) xlerror("not a string", s);
- return((char *) getstring(s));
- }
-
- LVAL StX11ItemObject(dpy, win)
- Display *dpy;
- Window win;
- {
- LVAL item, win_id;
- LVAL s_window_id = xlenter("WINDOW-ID");
-
- item = NIL;
- win_id = NIL;
- if (XFindContext(dpy, win, ObjectContext, &item) == 0 && objectp(item)) {
- win_id = slot_value(item, s_window_id);
- if (! fixp(win_id)) item = NIL;
- }
- return(item);
- }
-
- static FindItemType(item)
- LVAL item;
- {
- if (consp(item)) return(ITEM_LIST);
- else if (button_item_p(item)) return(BUTTON_ITEM);
- else if (toggle_item_p(item)) return(TOGGLE_ITEM);
- else if (text_item_p(item)) return(TEXT_ITEM);
- else if (choice_item_p(item)) return(CHOICE_ITEM);
- else if (scroll_item_p(item)) return(SCROLL_ITEM);
- else if (list_item_p(item)) return(LIST_ITEM);
- else xlfail("item of unknown type");
- }
-
- /***********************************************************************/
- /** **/
- /** Dialog System Initialization and Cleanup **/
- /** **/
- /***********************************************************************/
-
- StX11InitDialogs()
- {
- Display *dpy = StX11Display();
- int screen = StX11Screen();
- unsigned long valuemask;
- XGCValues values;
- int font_height, margin;
- char *font;
-
- dialog_border_width = 1;
- button_border_width = 1;
- list_border_width = 1;
- text_border_width = 1;
- min_button_height = 20;
- min_button_width = 100;
- dialog_item_gap = 5;
-
- DialogC.fore = BlackPixel(dpy, screen);
- DialogC.back = WhitePixel(dpy, screen);
- ButtonC.fore = BlackPixel(dpy, screen);
- ButtonC.back = WhitePixel(dpy, screen);
- DialogBorderColor = BlackPixel(dpy, screen);
- ButtonBorderColor = BlackPixel(dpy, screen);
-
- font = (char *) XGetDefault(dpy, "xlisp", "dialog.font");
- if (font == NULL) font = DialogFontName;
- if ((DialogFont = XLoadQueryFont(dpy, font)) == NULL) {
- fprintf(stderr, "xlisp: Can't open %s font\n", font);
- if ((DialogFont = XLoadQueryFont(dpy, DialogFontName)) == NULL) {
- fprintf(stderr, "xlisp: Can't open %s font\n", DialogFontName);
- exit(-1);
- }
- }
-
- min_toggle_height = TOGGLE_MARK_HEIGHT + DialogFont->max_bounds.descent;
- min_choice_height = CHOICE_MARK_HEIGHT + DialogFont->max_bounds.descent;
-
- ScrollThumbPM = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, screen),
- gray_bits,
- gray_width, gray_height,
- BlackPixel(dpy, screen),
- WhitePixel(dpy, screen),
- DefaultDepth(dpy, screen));
- ToggleOffPM = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
- toggle_off_bits,
- toggle_off_width, toggle_off_height);
- ToggleOnPM = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
- toggle_on_bits,
- toggle_on_width, toggle_on_height);
-
- ChoiceOffPM = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
- choice_off_bits,
- choice_off_width, choice_off_height);
- ChoiceOnPM = XCreateBitmapFromData(dpy, RootWindow(dpy, screen),
- choice_on_bits,
- choice_on_width, choice_on_height);
-
- LeftSliderPM = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, screen),
- left_slider_bits,
- left_slider_width,
- left_slider_height,
- BlackPixel(dpy, screen),
- WhitePixel(dpy, screen),
- DefaultDepth(dpy, screen));
- RightSliderPM = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, screen),
- right_slider_bits,
- right_slider_width,
- right_slider_height,
- BlackPixel(dpy, screen),
- WhitePixel(dpy, screen),
- DefaultDepth(dpy, screen));
-
- valuemask = 0; /* ignore XGCValues and use defaults */
- DialogGC = XCreateGC(dpy, RootWindow(dpy, screen), valuemask, &values);
- XSetFont(dpy, DialogGC, DialogFont->fid);
- XSetForeground(dpy, DialogGC, DialogC.fore);
- XSetBackground(dpy, DialogGC, DialogC.back);
-
- valuemask = 0; /* ignore XGCValues and use defaults */
- DialogRGC = XCreateGC(dpy, RootWindow(dpy, screen), valuemask, &values);
- XSetFont(dpy, DialogRGC, DialogFont->fid);
- XSetForeground(dpy, DialogRGC, DialogC.back);
- XSetBackground(dpy, DialogRGC, DialogC.fore);
-
- font_height = DialogFont->max_bounds.ascent
- + DialogFont->max_bounds.descent;
- margin = DialogFont->max_bounds.descent / 2;
- if (min_button_height < font_height + 2 * margin)
- min_button_height = font_height + 2 * margin;
-
- DoubleArrowCursor = XCreateFontCursor(dpy, XC_sb_h_double_arrow);
- RightArrowCursor = XCreateFontCursor(dpy, XC_sb_right_arrow);
- LeftArrowCursor = XCreateFontCursor(dpy, XC_sb_left_arrow);
- UpDownArrowCursor = XCreateFontCursor(dpy, XC_sb_v_double_arrow);
- UpArrowCursor = XCreateFontCursor(dpy, XC_sb_up_arrow);
- DownArrowCursor = XCreateFontCursor(dpy, XC_sb_down_arrow);
- }
-
- StX11FinishDialogs()
- {
- Display *dpy = StX11Display();
-
- XUnloadFont(dpy, DialogFont->fid);
- XFreeGC(dpy, DialogGC);
- XFreePixmap(dpy, ScrollThumbPM);
- XFreePixmap(dpy, ToggleOffPM);
- XFreePixmap(dpy, ToggleOnPM);
- XFreePixmap(dpy, ChoiceOffPM);
- XFreePixmap(dpy, ChoiceOnPM);
- XFreePixmap(dpy, LeftSliderPM);
- XFreePixmap(dpy, RightSliderPM);
- XFreeCursor(dpy, DoubleArrowCursor);
- XFreeCursor(dpy, RightArrowCursor);
- XFreeCursor(dpy, LeftArrowCursor);
- XFreeCursor(dpy, UpDownArrowCursor);
- XFreeCursor(dpy, UpArrowCursor);
- XFreeCursor(dpy, DownArrowCursor);
- }
-
- StX11DialogReset()
- {
- Display *dpy = StX11Display();
-
- XUngrabPointer(dpy, CurrentTime);
- }
-
- /***********************************************************************/
- /** **/
- /** Constructing and Removing Dialogs **/
- /** **/
- /***********************************************************************/
-
- static LVAL frame_handler(report, modal)
- XEvent report;
- int modal;
- {
- if (modal) return(NIL);
-
- switch(report.type) {
- case ClientMessage:
- StX11HandleClientMessage(report);
- break;
- default:
- break;
- }
- return(NIL);
- }
-
- DialogAllocate(dialog)
- LVAL dialog;
- {
- char *title;
- Point loc, size;
- int go_away, modeless;
- Window win, panel;
- unsigned int width, height, wheight;
- int left, top;
- XSetWindowAttributes setwinattr;
- unsigned long valuemask;
- Display *dpy = StX11Display();
- int screen = StX11Screen();
-
- if (check_dialog_address(dialog)) DialogRemove(dialog);
-
- if (! stringp(slot_value(dialog, s_title)))
- xlerror("not a string", slot_value(dialog, s_title));
- title = (char *) getstring(slot_value(dialog, s_title));
-
- loc = ListToPoint(slot_value(dialog, s_location));
- size = ListToPoint(slot_value(dialog, s_size));
- go_away = (slot_value(dialog, s_go_away) != NIL) ? TRUE : FALSE;
-
- modeless = (slot_value(dialog, s_type) == s_modeless) ? TRUE : FALSE;
-
- /* create opaque dialog window */
- left = loc.h; top = loc.v;
- width = size.h; height = size.v;
- wheight = (modeless && go_away) ? height + ClosePanelHeight() : height;
- win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen),
- left, top, width, wheight, dialog_border_width,
- DialogBorderColor, DialogC.back);
- if (modeless) StX11SetWindowClass(dpy, win);
- StX11SetNormalHints(dpy, win, left, top, width, wheight);
-
- if (XSaveContext(dpy, win, EventContext, (XContext) frame_handler) != 0)
- xlfail("could not install event handler");
- if (XSaveContext(dpy, win, ObjectContext, (XContext) dialog) != 0)
- xlfail("could not install object in window");
-
- if (! modeless) {
- if (StX11UseICCCM()) StX11SetTransientHint(dpy, win);
- else {
- /* set override_redirect and save_under attributes for a modal dialog */
- valuemask = CWOverrideRedirect | CWSaveUnder;
- setwinattr.override_redirect = TRUE;
- setwinattr.save_under = TRUE;
- XChangeWindowAttributes(dpy, win, valuemask, &setwinattr);
- }
- }
- XStoreName(dpy, win, title);
- set_dialog_address(win, dialog);
- XDefineCursor(dpy, win, ArrowCursor);
- StX11SetStandardHints(dpy, win);
-
- left = 0;
- top = (modeless && go_away) ? ClosePanelHeight() : 0;
- panel = XCreateSimpleWindow(dpy, win,
- left, top, width, height, dialog_border_width,
- DialogBorderColor, DialogC.back);
-
- InstallDialogItems(panel, dialog);
- if (modeless && go_away) InstallCloseButton(win, dialog);
-
- /* Display (map) the windows */
- XMapSubwindows(dpy, panel);
- XMapSubwindows(dpy, win);
- XMapWindow(dpy, win);
- }
-
- DialogRemove(dialog)
- LVAL dialog;
- {
- Window win;
- Display *dpy = StX11Display();
-
- if (check_dialog_address(dialog)
- && (win = (Window) GETDIALOGADDRESS(dialog)) != nil) {
- if (XDeleteContext(dpy, win, EventContext) != 0)
- xlfail("cound not delete event context");
- if (XDeleteContext(dpy, win, ObjectContext) != 0)
- xlfail("cound not delete object context");
- DeleteDialogItems(dialog);
- DeleteCloseButton(win);
- XDestroyWindow(dpy, win);
- XFlush(dpy);
- }
- if (objectp(dialog)) standard_hardware_clobber(dialog);
- }
-
- DialogSetDefaultButton(dialog, item)
- LVAL dialog, item;
- {
- if (item == NIL || button_item_p(item))
- set_slot_value(dialog, s_default_button, item);
- }
-
- static InstallDialogItems(win, dialog)
- Window win;
- LVAL dialog;
- {
- LVAL items;
-
- items = slot_value(dialog, s_items);
- InstallItemList(win, items);
- }
-
- static InstallItemList(win, items)
- Window win;
- LVAL items;
- {
- for (; consp(items); items = cdr(items))
- if (consp(car(items))) InstallItemList(win, car(items));
- else InstallItem(win, car(items));
- }
-
- static InstallItem(win, item)
- Window win;
- LVAL item;
- {
- int type;
-
- if (! dialog_item_p(item)) xlerror("not a dialog item", item);
-
- type = FindItemType(item);
-
- switch (type) {
- case BUTTON_ITEM: InstallButtonItem(win, item); break;
- case TOGGLE_ITEM: InstallToggleItem(win, item); break;
- case CHOICE_ITEM: InstallChoiceItem(win, item); break;
- case TEXT_ITEM: InstallTextItem(win, item); break;
- case SCROLL_ITEM: InstallScrollItem(win, item); break;
- case LIST_ITEM: InstallListItem(win, item); break;
- default: xlfail("unkown item type");
- }
- }
-
- static DeleteDialogItems(dialog)
- LVAL dialog;
- {
- Window win;
- LVAL items;
-
- win = (Window) GETDIALOGADDRESS(dialog);
- if (win != nil) {
- items = slot_value(dialog, s_items);
- DeleteItemList(win, items);
- }
- }
-
- static DeleteItemList(win, items)
- Window win;
- LVAL items;
- {
- for (; consp(items); items = cdr(items))
- if (consp(car(items))) DeleteItemList(win, car(items));
- else DeleteItem(win, car(items));
- }
-
- static DeleteItem(win, item)
- Window win;
- LVAL item;
- {
- int type;
-
- if (! dialog_item_p(item)) xlerror("not a dialog item", item);
-
- type = FindItemType(item);
-
- switch (type) {
- case BUTTON_ITEM: DeleteButtonItem(win, item); break;
- case TOGGLE_ITEM: DeleteToggleItem(win, item); break;
- case CHOICE_ITEM: DeleteChoiceItem(win, item); break;
- case TEXT_ITEM: DeleteTextItem(win, item); break;
- case SCROLL_ITEM: DeleteScrollItem(win, item); break;
- case LIST_ITEM: DeleteListItem(win, item); break;
- default: xlfail("unkown item type");
- }
- }
-
- /***********************************************************************/
- /** **/
- /** Modal Dialog Loop **/
- /** **/
- /***********************************************************************/
-
- LVAL DialogGetModalItem(dialog)
- LVAL dialog;
- {
- Window win, event_win, old_focus_win;
- Display *dpy = StX11Display();
- XEvent report;
- LVAL result = NIL;
- LVAL (*callback)();
- int old_revert_to, use_icccm;
- LVAL sk_show_window = xlenter(":SHOW-WINDOW");
-
- send_message(dialog, sk_show_window);
- win = GETDIALOGADDRESS(dialog);
- if (win != nil) {
-
- StX11ReleaseButton();
- use_icccm = StX11UseICCCM();
- if (! use_icccm) {
- /* set the input focus and grap the pointer */
- XGetInputFocus(dpy, &old_focus_win, &old_revert_to);
- XSetInputFocus(dpy, win, RevertToPointerRoot, CurrentTime);
- XGrabPointer(dpy, win, TRUE, ButtonReleaseMask,
- GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
- }
-
- /* Loop until button is released, examining each event */
- while (result == NIL) {
- XNextEvent(dpy, &report);
- event_win = report.xany.window;
- if (is_item_window(dpy, event_win, dialog)
- && XFindContext(dpy, event_win, EventContext, &callback) == 0
- && callback != nil)
- result = (*callback)(report, TRUE);
- else if (report.type == Expose)
- StProcessEvent(dpy, report);
- else if (report.type == MappingNotify)
- XRefreshKeyboardMapping(&report);
- }
- if (! use_icccm) {
- XUngrabPointer(dpy, CurrentTime);
- XSetInputFocus(dpy, old_focus_win, old_revert_to, CurrentTime);
- }
- else StX11FlushStdin();
- }
- return(result);
- }
-
- static is_item_window(dpy, event_win, dialog)
- Display *dpy;
- Window event_win;
- LVAL dialog;
- {
- LVAL item;
-
- if (XFindContext(dpy, event_win, ObjectContext, &item) != 0) return(FALSE);
- else if (! objectp(item) || ! dialog_item_p(item)) return(FALSE);
- else if (slot_value(item, s_dialog) != dialog) return(FALSE);
- else return(TRUE);
- }
-
- install_dialog_item_handler(dpy, win, handler, item)
- Display *dpy;
- Window win;
- LVAL (*handler)(), item;
- {
- if (XSaveContext(dpy, win, EventContext, (XContext) handler) != 0)
- xlfail("could not install event handler");
- }
-
- delete_dialog_item_handler(dpy, win)
- Display *dpy;
- Window win;
- {
- if (XDeleteContext(dpy, win, EventContext) != 0)
- xlfail("cound not delete event context");
- }
-
- #ifdef TODO
- register dialog with all subwindows; use in modal loop
- make hitting return envoke default button for all dialogs
- #endif TODO
-