/* X11text - text 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 #include #include #include #include "dialogs.h" extern Display *StX11Display(); extern Point DialogStringSize(); extern LVAL StX11ItemObject(); extern char *checkstring(); typedef struct { unsigned long fore, back; } ColorPair; # define STATIC_TEXT_LEAD 5 # define STATIC_TEXT_PAD 10 # define EDIT_TEXT_LEAD 10 # define EDIT_TEXT_PAD 20 /***********************************************************************/ /** **/ /** Global Variables **/ /** **/ /***********************************************************************/ /* configuration parameters - should be set using the defaults database */ extern XFontStruct *DialogFont; extern unsigned long DialogBorderColor; extern ColorPair DialogC; extern unsigned int text_border_width; extern GC DialogGC, DialogRGC; extern XContext ObjectContext, TextCursorContext; extern Cursor IBeamCursor; /***********************************************************************/ /** **/ /** Text Items **/ /** **/ /***********************************************************************/ static max_line_size(s) char *s; { char *bp; int w; Point sz; for (w = 0; *s != '\0'; s++) { for (bp = buf; *s != '\0' && *s != '\r' && *s != '\n'; s++, bp++) *bp = *s; *bp = '\0'; sz = DialogStringSize(buf); w = max(w, sz.h); if (*s == '\0') break; } return(w); } static draw_text(dpy, win, item, erase, move_cursor) Display *dpy; Window win; LVAL item; int erase, move_cursor; { char *text, *bp; int x, y, len, ascent, font_height, editable, cx, cy; Window cursor; ascent = DialogFont->max_bounds.ascent; font_height = ascent + DialogFont->max_bounds.descent; if (erase) XClearWindow(dpy, win); text = checkstring(slot_value(item, s_text)); editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE; x = (editable) ? EDIT_TEXT_LEAD : 0; y = (editable) ? EDIT_TEXT_LEAD + ascent : STATIC_TEXT_LEAD + ascent; if (editable) { len = strlen(text); if (move_cursor) { cy = EDIT_TEXT_LEAD; cx = EDIT_TEXT_LEAD + XTextWidth(DialogFont, text, len); if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0) xlfail("can't find text cursor context"); XMoveWindow(dpy, cursor, cx, cy); } XDrawString(dpy, win, DialogGC, x, y, text, len); } else { for(; *text != '\0'; text++, y += font_height + STATIC_TEXT_LEAD) { for (bp = buf; *text != '\0' && *text != '\r' && *text != '\n'; text++, bp++) *bp = *text; *bp = '\0'; len = strlen(buf); XDrawString(dpy, win, DialogGC, x, y, buf, len); } } } #define bufsize 20 static do_key(report, dpy, win, item) XEvent report; Display *dpy; Window win; LVAL item; { char buffer[bufsize], *text; int count, len, erase = FALSE, result = FALSE; KeySym keysym; /*XComposeStatus compose;*/ text = checkstring(slot_value(item, s_text)); strcpy(buf, text); count = XLookupString(&report, buffer, bufsize, &keysym, nil /*&compose*/); if (keysym == XK_Return || keysym == XK_KP_Enter || keysym == XK_Linefeed) { result = TRUE; /* XBell(dpy, 100);*/ } else if ((keysym >= XK_KP_Space && keysym <= XK_KP_9) || (keysym >= XK_space && keysym <= XK_asciitilde)) { if (strlen(buf) + count >= STRMAX) XBell(dpy, 100); else strncat(buf, buffer, count); } else if (keysym >= XK_Shift_L && keysym <= XK_Hyper_R) ; /* do nothing because it is a modifier key */ else if (keysym >= XK_F1 && keysym <= XK_F35) { if (count == 0) XBell(dpy, 100); else if (strlen(buf) + count >= STRMAX) XBell(dpy, 100); else strncat(buf, buffer, count); } else if (keysym == XK_BackSpace || keysym == XK_Delete) { if ((len = strlen(buf)) > 0) { buf[len - 1] = '\0'; erase = TRUE; } else XBell(dpy, 100); } else XBell(dpy, 100); set_slot_value(item, s_text, make_string(buf)); draw_text(dpy, win, item, erase, TRUE); return(result); } static LVAL text_handler(report, modal) XEvent report; int modal; { Display *dpy = StX11Display(); Window win, cursor; LVAL item, result = NIL; int editable; win = report.xany.window; item = StX11ItemObject(dpy, win); editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE; if (item != NIL) { switch (report.type) { case Expose: draw_text(dpy, win, item, FALSE, TRUE); break; case KeyPress: if (editable && do_key(report, dpy, win, item) && modal) result = slot_value(slot_value(item, s_dialog), s_default_button); break; case ButtonPress: break; case ButtonRelease: break; case EnterNotify: if (editable && report.xcrossing.subwindow == None && report.xcrossing.focus) { if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0) xlfail("can't find text cursor context"); XSetWindowBackground(dpy, cursor, DialogC.fore); XClearWindow(dpy, cursor); XSetWindowBorderWidth(dpy, win, text_border_width + 1); } break; case LeaveNotify: if (editable && report.xcrossing.subwindow == None && report.xcrossing.focus) { if (XFindContext(dpy, win, TextCursorContext, &cursor) != 0) xlfail("can't find text cursor context"); XSetWindowBackground(dpy, cursor, DialogC.back); XClearWindow(dpy, cursor); XSetWindowBorderWidth(dpy, win, text_border_width); } break; default: break; } } return(result); } InstallTextItem(win, item) Window win; LVAL item; { Display *dpy = StX11Display(); Point loc, size; Window field, cursor; int editable, ascent; LVAL s_window_id = xlenter("WINDOW-ID"); loc = ListToPoint(slot_value(item, s_location)); size = ListToPoint(slot_value(item, s_size)); editable = (slot_value(item, s_editable) != NIL) ? TRUE : FALSE; field = XCreateSimpleWindow(dpy, win, loc.h, loc.v, size.h, size.v, (editable) ? text_border_width : 0, DialogBorderColor, DialogC.back); if (editable) XSelectInput(dpy, field, ExposureMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask); else XSelectInput(dpy, field, ExposureMask); if (editable) { XDefineCursor(dpy, field, IBeamCursor); ascent = DialogFont->max_bounds.ascent; cursor = XCreateSimpleWindow(dpy, field, EDIT_TEXT_LEAD, EDIT_TEXT_LEAD, ascent / 2, ascent, text_border_width, DialogBorderColor, DialogC.back); if (XSaveContext(dpy, field, TextCursorContext, (XContext) cursor) != 0) xlfail("can't install cursor for text field"); XMapWindow(dpy, cursor); } set_slot_value(item, s_window_id, cvfixnum((FIXTYPE) field)); install_dialog_item_handler(dpy, field, text_handler, item); if (XSaveContext(dpy, field, ObjectContext, (XContext) item) != 0) xlfail("could not install object in window"); } DeleteTextItem(win, item) Window win; LVAL item; { Display *dpy = StX11Display(); Window field; LVAL s_window_id = xlenter("WINDOW-ID"); field = (Window) getfixnum(slot_value(item, s_window_id)); delete_dialog_item_handler(dpy, field); if (XDeleteContext(dpy, field, ObjectContext) != 0) xlfail("cound not delete object context"); if (slot_value(item, s_editable) != nil && XDeleteContext(dpy, field, TextCursorContext) != 0) xlfail("cound not delete cursor context"); set_slot_value(item, s_window_id, NIL); } DialogTextGetDefaultSize(item, width, height) LVAL item; int *width, *height; { Point sz, em_sz; LVAL text = slot_value(item, s_text); LVAL text_length = slot_value(item, xlenter("TEXT-LENGTH")); int w = 0; char *s; em_sz = DialogStringSize("M"); sz.v = em_sz.v + 2 * STATIC_TEXT_LEAD; if (stringp(text)) { w = max_line_size(getstring(text)); s = (char *) getstring(text); for (sz.v = em_sz.v + 2 * STATIC_TEXT_LEAD; *s != '\0'; s++) if (*s == '\n' || *s == '\r') sz.v += em_sz.v + STATIC_TEXT_LEAD; } if (fixp(text_length)) { w = max((int) (getfixnum(text_length) * em_sz.h), w); } if (slot_value(item, s_editable) != NIL) { if (width != nil) *width = w + EDIT_TEXT_PAD; if (height != nil) *height = em_sz.v + 2 * EDIT_TEXT_LEAD; } else { if (width != nil) *width = w + STATIC_TEXT_PAD; if (height != nil) *height = sz.v; } } LVAL DialogTextItemText(item, set, text) LVAL item; int set; char *text; { Display *dpy = StX11Display(); LVAL win_id; LVAL s_window_id = xlenter("WINDOW-ID"); if (set) { set_slot_value(item, s_text, make_string(text)); win_id = slot_value(item, s_window_id); if (fixp(win_id)) draw_text(dpy, (Window) getfixnum(win_id), item, TRUE, TRUE); } return(slot_value(item, s_text)); } #ifdef TODO mouse editing support #endif TODO