/* * gl.c - Simple graphics library, based on X11. * * Author: John Sullivan, Amdahl Corporation (jjs40@cd.amdahl.com) * */ /*****************************************************************************/ #include "gl.h" #include #include #include #include #include /*****************************************************************************/ Display *gl_display; int gl_screen; Window gl_window; GC gl_gc; GL_REDRAW_FUNC gl_redraw_fn; GL_EVENT_FUNC gl_event_fn; int gl_main; int gl_screen_width; int gl_screen_height; int gl_fg; int gl_bg; /*****************************************************************************/ void gl_bomb(s) char *s; { printf("gl_bomb(): %s\n"); exit(1); }; /*****************************************************************************/ GL_PIXEL gl_alloc_color(name) char *name; { XColor c1, c2; int res; res = XAllocNamedColor(gl_display, DefaultColormap(gl_display, gl_screen), name, &c1, &c2); if (!res) { gl_bomb("Unable to allocate color."); }; return (c1.pixel); }; /*****************************************************************************/ void gl_redraw_func(func) GL_REDRAW_FUNC func; { gl_redraw_fn = func; }; /*****************************************************************************/ void gl_event_func(func) GL_EVENT_FUNC func; { gl_event_fn = func; }; /*****************************************************************************/ char gl_event_str_buf[GL_BUFSIZE]; char * gl_event_str(gl_ev) GL_EVENT *gl_ev; { switch (gl_ev->type) { case GL_EVENT_KEY: sprintf(gl_event_str_buf, "gl_event: key '%c' at (%d,%d)", gl_ev->key, gl_ev->x, gl_ev->y); break; case GL_EVENT_BUTTON: sprintf(gl_event_str_buf, "gl_event: button %d at (%d,%d)", gl_ev->button, gl_ev->x, gl_ev->y); }; return (gl_event_str_buf); }; /*****************************************************************************/ void gl_main_loop() { XEvent xev; XButtonEvent *xbev; XKeyEvent *xkev; GL_EVENT gl_ev; char buf[GL_BUFSIZE]; gl_main = 1; while (gl_main) { XNextEvent(gl_display, &xev); switch (xev.type) { case Expose: if (gl_redraw_fn != NULL) { (*gl_redraw_fn) (); }; break; case KeyPress: gl_ev.type = GL_EVENT_KEY; xkev = (XKeyEvent *) & xev; XLookupString(xkev, buf, GL_BUFSIZE, NULL, NULL); gl_ev.key = buf[0]; gl_ev.x = xkev->x; gl_ev.y = xkev->y; if (gl_event_fn != NULL) { (*gl_event_fn) (&gl_ev); }; break; case ButtonPress: gl_ev.type = GL_EVENT_BUTTON; xbev = (XButtonEvent *) & xev; gl_ev.button = xbev->button; gl_ev.x = xbev->x; gl_ev.y = xbev->y; if (gl_event_fn != NULL) { (*gl_event_fn) (&gl_ev); }; break; }; }; }; /*****************************************************************************/ void gl_exit_main() { gl_main = 0; }; /*****************************************************************************/ void gl_set_fg(c) GL_PIXEL c; { XGCValues gcv; gl_fg = c; gcv.foreground = gl_fg; XChangeGC(gl_display, gl_gc, GCForeground, &gcv); }; /*****************************************************************************/ void gl_set_bg(c) GL_PIXEL c; { XGCValues gcv; gl_bg = c; gcv.background = gl_bg; XChangeGC(gl_display, gl_gc, GCBackground, &gcv); }; /*****************************************************************************/ void gl_set_fg_bg(c1, c2) GL_PIXEL c1, c2; { gl_set_fg(c1); gl_set_bg(c2); }; /*****************************************************************************/ void gl_draw_point(x, y) int x, y; { XDrawPoint(gl_display, gl_window, gl_gc, x, y); }; /*****************************************************************************/ void gl_draw_line(x1, y1, x2, y2) int x1, y1; int x2, y2; { XDrawLine(gl_display, gl_window, gl_gc, x1, y1, x2, y2); }; /*****************************************************************************/ void gl_draw_rect(x1, y1, w, h) int x1, y1; int w, h; { XDrawRectangle(gl_display, gl_window, gl_gc, x1, y1, w - 1, h - 1); }; /*****************************************************************************/ void gl_fill_rect(x1, y1, w, h) int x1, y1; int w, h; { XFillRectangle(gl_display, gl_window, gl_gc, x1, y1, w, h); }; /*****************************************************************************/ void gl_draw_text(x, y, s) int x, y; char *s; { int len; len = strlen(s); y = y + GL_FONT_DESCENT; XDrawImageString(gl_display, gl_window, gl_gc, x, y, s, len); }; /*****************************************************************************/ void gl_ring_bell() { XBell(gl_display, 75); }; /*****************************************************************************/ GL_BITMAP gl_load_bitmap(data, w, h) char *data; int w, h; { return (XCreateBitmapFromData(gl_display, gl_window, data, w, h)); }; /*****************************************************************************/ void gl_draw_bitmap(bitmap, x, y, w, h) GL_BITMAP bitmap; int x, y; int w, h; { XCopyPlane(gl_display, bitmap, gl_window, gl_gc, 0, 0, w, h, x, y, 1); }; /*****************************************************************************/ void gl_init(argc, argv, w, h) int argc; char **argv; int w, h; { XSizeHints hints; XGCValues gcv; unsigned long gcvm; gl_display = XOpenDisplay(NULL); if (!gl_display) { gl_bomb("Unable to connect to display."); }; gl_redraw_fn = NULL; gl_event_fn = NULL; gl_screen_width = w; gl_screen_height = h; hints.width = gl_screen_width; hints.height = gl_screen_height; hints.flags = PSize; gl_fg = gl_alloc_color(GL_FOREGROUND); gl_bg = gl_alloc_color(GL_BACKGROUND); gcv.foreground = gl_fg; gcv.background = gl_bg; gcv.font = XLoadFont(gl_display, GL_FONT); gcvm = GCForeground | GCBackground | GCFont; gl_screen = DefaultScreen(gl_display); gl_window = XCreateSimpleWindow(gl_display, RootWindow(gl_display, gl_screen), 0, 0, hints.width, hints.height, 2, gcv.foreground, gcv.background); XSetStandardProperties(gl_display, gl_window, "GL", "GL", None, argv, argc, &hints); XSelectInput(gl_display, gl_window, ExposureMask | KeyPressMask | ButtonPressMask); gl_gc = XCreateGC(gl_display, gl_window, gcvm, &gcv); }; /*****************************************************************************/ void gl_start() { XMapWindow(gl_display, gl_window); XSync(gl_display, 1); }; /*****************************************************************************/ void gl_exit() { XCloseDisplay(gl_display); exit(0); }; /*****************************************************************************/ void gu_draw_border(x, y, w, h, z) int x, y; int w, h; int z; { int i; for (i = 1; i <= z; i++) { gl_draw_rect(x - i, y - i, w + i * 2, h + i * 2); }; }; /*****************************************************************************/ void gu_draw_centered_text(x, y, s) int x, y; char *s; { int sx, sy; sx = x - (strlen(s) * GL_FONT_WIDTH) / 2; sy = y - GL_FONT_HEIGHT / 2; gl_draw_text(sx, sy, s); }; /*****************************************************************************/ GL_BOOL gu_event_in_rect(event, x, y, w, h) GL_EVENT *event; int x, y; int w, h; { x = event->x - x; y = event->y - y; return ((x >= 0) && (x < w) && (y >= 0) && (y < h)); }; /*****************************************************************************/ void gb_draw_button(btn) GB_BUTTON *btn; { gl_set_fg(btn->border); gu_draw_border(btn->x, btn->y, btn->w, btn->h, 2); gl_set_fg(btn->background); gl_fill_rect(btn->x, btn->y, btn->w, btn->h); gl_set_fg_bg(btn->text, btn->background); gu_draw_centered_text(btn->x + btn->w / 2, btn->y + btn->h / 2, btn->label); }; /*****************************************************************************/ void gb_draw_buttons(n, btn) int n; GB_BUTTON *btn; { int i; for (i = 0; i < n; i++) { gb_draw_button(&(btn[i])); }; }; /*****************************************************************************/ GL_BOOL gb_event_in_button(event, btn) GL_EVENT *event; GB_BUTTON *btn; { return (gu_event_in_rect(event, btn->x, btn->y, btn->w, btn->h)); }; /*****************************************************************************/ void gb_button_press(event, btn) GL_EVENT *event; GB_BUTTON *btn; { if (btn->event_fn != NULL) { (*(btn->event_fn)) (event); }; }; /*****************************************************************************/ GL_BOOL gb_button_event(event, n, btn) GL_EVENT *event; int n; GB_BUTTON *btn; { int i; for (i = 0; i < n; i++) { if (gb_event_in_button(event, &(btn[i]))) { gb_button_press(event, &(btn[i])); return (GL_TRUE); }; }; return (GL_FALSE); }; /*****************************************************************************/