/* @(#)xview.c 1.15 90/08/14 * * These are the XView dependent graphics routines used by calctool. * * Copyright (c) Rich Burridge. * Sun Microsystems, Australia - All rights reserved. * * Permission is given to distribute these sources, as long as the * copyright messages are not removed, and no monies are exchanged. * * No responsibility is taken for any errors or inaccuracies inherent * either to the comments or the code of this program, but if * reported to me then an attempt will be made to fix them. */ #include #include "calctool.h" #include "color.h" #include "extern.h" #include #include #include #include #include #include #include #include #define MENU_SET (void) menu_set #define NOTIFY_DO_DISPATCH (void) notify_do_dispatch #define NOTIFY_INTERPOSE_DESTROY_FUNC (void) notify_interpose_destroy_func #define SELN_QUERY (void) seln_query #define XV_SET (void) xv_set #define WINDOW_DONE (void) window_done #define BIGFONT "lucidasanstypewriter-18" #define DEFFONT "fixed" #define NORMALFONT "lucidasanstypewriter-12" #define SMALLFONT "lucidasanstypewriter-10" void func_key_proc() ; int menu_proc() ; Canvas kcanvas, rcanvas ; Canvas_paint_window cpw, rcpw ; Event *cur_event ; Frame frame, rframe ; Icon calctool_icon ; Menu menus[MAXMENUS] ; Notify_value destroy_proc() ; Seln_client sel_client ; Seln_holder holder ; Seln_rank rank = SELN_PRIMARY ; Seln_result get_proc(), reply_proc() ; Xv_Cursor help_cursor, main_cursor ; Display *dpy ; Drawable xid_cpw, xid_rcpw ; GC gc ; Window root ; XColor current_col ; XFontStruct *bfont, *font, *nfont, *sfont ; XGCValues gc_val ; unsigned long gc_mask ; int screen ; unsigned long backgnd, foregnd ; unsigned long palette[CALC_COLORSIZE] ; enum menu_type curmenu ; /* Current menu (if any) being processed. */ int started ; /* Set just before window is displayed. */ short help_cursor_array[16] = { #include "help.cursor" } ; unsigned short icon_image[] = { #include "calctool.icon" } ; short cicon_image[] = { #include "calctool.color.icon" } ; mpr_static(cicon_pr, 64, 64, 8, cicon_image) ; /*ARGSUSED*/ void canvas_event_proc(canvas, event, arg) Canvas canvas ; Event *event ; caddr_t arg ; { if (!started) return ; cur_event = event ; process_event(get_next_event(event)) ; } clear_canvas(ctype, color) enum can_type ctype ; int color ; { int x, y ; unsigned int width, height, bwidth, depth ; Window root, window ; if (ctype == KEYCANVAS) window = xid_cpw ; else if (ctype == REGCANVAS) window = xid_rcpw ; XGetGeometry(dpy, window, &root, &x, &y, &width, &height, &bwidth, &depth) ; if (iscolor) gc_val.foreground = palette[color] ; else { if (color == WHITE) gc_val.foreground = backgnd ; else gc_val.foreground = foregnd ; } gc_val.function = GXcopy ; XChangeGC(dpy, gc, GCForeground | GCFunction, &gc_val) ; XFillRectangle(dpy, window, gc, x, y, width, height) ; } close_frame() { if ((int) xv_get(rframe, XV_SHOW) == TRUE) XV_SET(rframe, XV_SHOW, FALSE, 0) ; XV_SET(frame, FRAME_CLOSED, TRUE, 0) ; rstate = 0 ; } color_area(x, y, width, height, color) int x, y, width, height, color ; { if (iscolor) gc_val.foreground = palette[color] ; else { if (color == WHITE) gc_val.foreground = backgnd ; else gc_val.foreground = foregnd ; } gc_val.function = GXcopy ; XChangeGC(dpy, gc, GCForeground | GCFunction, &gc_val) ; XFillRectangle(dpy, xid_cpw, gc, x, y, (unsigned int) width, (unsigned int) height) ; } create_menu(mtype) /* Create popup menu for right button press. */ enum menu_type mtype ; { int i ; menus[(int) mtype] = xv_create(XV_NULL, MENU_COMMAND_MENU, MENU_NOTIFY_PROC, menu_proc, 0) ; for (i = 0; i < MAXREGS; i++) { switch (mtype) { case M_ACC : /* Accuracies. */ case M_EXCH : /* Register exchange. */ case M_LSHIFT : /* Left shift. */ case M_RCL : /* Register recall. */ case M_RSHIFT : /* Right shift. */ case M_STO : MENU_SET(menus[(int) mtype], /* Register store. */ MENU_STRING_ITEM, num_names[i], i+1, 0) ; break ; case M_CON : if (strlen(con_names[i])) /* Constants. */ MENU_SET(menus[(int) mtype], MENU_STRING_ITEM, con_names[i], i+1, 0) ; break ; case M_FUN : if (strlen(fun_names[i])) /* Functions. */ MENU_SET(menus[(int) mtype], MENU_STRING_ITEM, fun_names[i], i+1, 0) ; } } } destroy_frame() { WINDOW_DONE(frame) ; exit(0) ; } destroy_rframe(frame) Frame frame ; { rstate = 0 ; XV_SET(frame, XV_SHOW, FALSE, 0) ; } /*ARGSUSED*/ Notify_value destroy_proc(client, status) Notify_client client ; Destroy_status status ; { exit(0) ; } /* This routine works rather strangely. Because menu_show does not block * under XView, do_menu cannot return a valid selection. So the menu * selection handling has been moved to the notification procedure, and * the appropriate code in graphics.c has been isolated into a separate * routine. All in all, a bit of a kludge. */ do_menu(mtype) /* Popup appropriate menu. */ enum menu_type mtype ; { curmenu = mtype ; menu_show(menus[(int) mtype], kcanvas, cur_event, 0) ; return(0) ; } drawline(x1, y1, x2, y2) int x1, y1, x2, y2 ; { if (iscolor) gc_val.foreground = palette[BLACK] ; else gc_val.foreground = foregnd ; gc_val.function = GXcopy ; XChangeGC(dpy, gc, GCForeground | GCFunction, &gc_val) ; XDrawLine(dpy, xid_cpw, gc, x1, y1, x2, y2) ; } draw_regs() { Rect frect, rrect ; make_registers() ; /* Force the register popup to appear to the right of the main calctool * frame if it's not already being displayed. */ if (xv_get(rframe, XV_SHOW)) return ; frame_get_rect(frame, &frect) ; frame_get_rect(rframe, &rrect) ; rrect.r_left = frect.r_left + frect.r_width + 5 ; rrect.r_top = frect.r_top + 21 ; frame_set_rect(rframe, &rrect) ; XV_SET(rframe, XV_SHOW, TRUE, 0) ; } drawtext(x, y, ctype, fontno, color, str) enum font_type fontno ; enum can_type ctype ; int x, y, color ; char *str ; { Drawable window ; if (fontno == SFONT) font = sfont ; else if (fontno == NFONT) font = nfont ; else if (fontno == BFONT) font = bfont ; if (ctype == KEYCANVAS) window = xid_cpw ; else if (ctype == REGCANVAS) window = xid_rcpw ; if (ctype == KEYCANVAS && y == items[(int) DISPLAYITEM].y) x += 70 ; if (iscolor) gc_val.foreground = palette[color] ; else { if (color == WHITE) gc_val.foreground = backgnd ; else gc_val.foreground = foregnd ; } gc_val.font = font->fid ; gc_val.function = GXcopy ; XChangeGC(dpy, gc, GCFont | GCForeground | GCFunction, &gc_val) ; XDrawString(dpy, window, gc, x, y, str, strlen(str)) ; } /*ARGSUSED*/ void func_key_proc(client_data, args) char *client_data ; Seln_function_buffer *args ; { get_display() ; } get_display() /* The GET function key has been pressed. */ { if (seln_acquire(sel_client, SELN_SHELF) == SELN_SHELF) { if (shelf != NULL) free(shelf) ; shelf = malloc((unsigned) strlen(display)) ; STRCPY(shelf, display) ; /* Safely keep copy of display. */ } } XFontStruct * get_font(name) char *name ; { XFontStruct *font ; if (!(font = XLoadQueryFont(dpy, name))) if (!(font = XLoadQueryFont(dpy, DEFFONT))) { perror("couldn't get the default font.") ; exit(1) ; } return(font) ; } get_next_event(event) Event *event ; { static char eb[4] ; /* Event buffer. */ int i ; #ifdef SUN4_KEYBOARD char *rpad = "\000\000\000=/*789456123" ; #else char *rpad = "\000\000\00078945612301=" ; #endif /*SUN4_KEYBOARD*/ nextc = event_id(event) ; curx = event_x(event) ; cury = event_y(event) ; if (event_is_button(event)) if (event_is_down(event) && nextc == MS_LEFT) return(LEFT_DOWN) ; else if (event_is_down(event) && nextc == MS_MIDDLE) return(MIDDLE_DOWN) ; else if (event_is_down(event) && nextc == MS_RIGHT) return(RIGHT_DOWN) ; else if (event_is_up(event) && nextc == MS_LEFT) return(LEFT_UP) ; else if (event_is_up(event) && nextc == MS_MIDDLE) return(MIDDLE_UP) ; else if (event_is_up(event) && nextc == MS_RIGHT) return(RIGHT_UP) ; if (event_is_ascii(event) && event_is_down(event)) { /* With the Sun4 keyboard, the right function keypad generates key_right * events except for the function keys which are not in the range R1-R15. * These return ASCII values which are: * INS (0) = 0, DEL (.) = 127, Enter = 13, - = 45, + = 43. * * These are correct except for INS and DEL. INS can be remapped to ASCII * 48 (the digit zero), but there is no easy way to handle DEL remapping, * If you remap DEL to ASCII 46 (decimal point), this also remaps the * Delete key value. For now, this value is left alone. */ #ifdef SUN4_KEYBOARD if (nextc == 0) nextc = 48 ; /* Remap INS (0) key. */ #endif /*SUN4_KEYBOARD*/ /* All the rest of the ASCII characters. */ cur_ch = nextc ; return(KEYBOARD) ; } if (event_is_key_right(event) && event_is_up(event)) { for (i = 1; i < 16; i++) if (nextc == KEY_RIGHT(i)) { cur_ch = rpad[i-1] ; return(KEYBOARD) ; } } if (nextc == KBD_DONE && down) return(EXIT_WINDOW) ; if (nextc == LOC_WINEXIT) return(EXIT_WINDOW) ; if (nextc == LOC_WINENTER) return(ENTER_WINDOW) ; if (nextc == WIN_RESIZE) return(CFRAME_REPAINT) ; if (nextc == WIN_REPAINT) return(CFRAME_REPAINT) ; if ((nextc == KEY_LEFT(6)) & event_is_up(event)) return(PUT_ON_SHELF) ; if ((nextc == KEY_LEFT(8)) && event_is_up(event)) return(TAKE_FROM_SHELF) ; return(LASTEVENTPLUSONE) ; } Seln_result get_proc(buffer) Seln_request *buffer ; { issel = 0 ; if (*buffer->requester.context == 0) { if (buffer == (Seln_request *) NULL || *((Seln_attribute *) buffer->data) != SELN_REQ_CONTENTS_ASCII) return ; selection = buffer->data + sizeof(Seln_attribute) ; *buffer->requester.context = 1 ; } else selection = buffer->data ; issel = 1 ; } handle_selection() /* Handle the GET function key being pressed. */ { char context = 0 ; holder = seln_inquire(rank) ; if (holder.state == SELN_NONE) return ; SELN_QUERY(&holder, get_proc, &context, SELN_REQ_CONTENTS_ASCII, 0, 0) ; } init_fonts() /* Null routine; fonts loaded in make_subframes. */ { } init_ws_type() { gtype = XVIEW ; started = 0 ; /* Kludge to correctly handle repaints. */ return 0 ; } load_colors() /* Create and load calctool color map. */ { u_char red[CALC_COLORSIZE], green[CALC_COLORSIZE], blue[CALC_COLORSIZE] ; int i, numcolors ; iscolor = 0 ; if (DisplayCells(dpy, screen) > 2) { calc_colorsetup(red, green, blue) ; iscolor = 1 ; numcolors = 0 ; for (i = 0; i < CALC_COLORSIZE; i++) { current_col.flags = DoRed | DoGreen | DoBlue ; current_col.red = (unsigned short) (red[i] << 8) ; current_col.green = (unsigned short) (green[i] << 8) ; current_col.blue = (unsigned short) (blue[i] << 8) ; if (XAllocColor(dpy, DefaultColormap(dpy, screen), ¤t_col) == True) palette[numcolors++] = current_col.pixel ; } if (numcolors < 2) { FPRINTF(stderr, "%s: cannot allocate colors.\n", progname) ; exit(1) ; } } } make_frames(argc, argv) int argc ; char *argv[] ; { xv_init(XV_INIT_ARGS, argc, argv, 0) ; frame = xv_create(0, FRAME, FRAME_ICON, calctool_icon, FRAME_SHOW_LABEL, FALSE, FRAME_NO_CONFIRM, TRUE, XV_WIDTH, TWIDTH, XV_HEIGHT, THEIGHT + DISPLAY, 0) ; iscolor = ((int) xv_get(frame, WIN_DEPTH) > 1) ? 1 : 0 ; sel_client = seln_create(func_key_proc, reply_proc, (char *) 0) ; NOTIFY_INTERPOSE_DESTROY_FUNC(frame, destroy_proc) ; rframe = xv_create(frame, FRAME, FRAME_SHOW_LABEL, FALSE, FRAME_NO_CONFIRM, TRUE, FRAME_DONE_PROC, destroy_rframe, XV_X, TWIDTH + 15, XV_Y, 0, XV_SHOW, FALSE, XV_WIDTH, TWIDTH, XV_HEIGHT, 200, XV_FONT, nfont, 0) ; } make_icon() { Server_image sv_image ; sv_image = xv_create(XV_NULL, SERVER_IMAGE, SERVER_IMAGE_BITS, icon_image, SERVER_IMAGE_DEPTH, 1, XV_WIDTH, 64, XV_HEIGHT, 64, 0) ; calctool_icon = xv_create(XV_NULL, ICON, XV_WIDTH, ICONWIDTH, ICON_IMAGE, sv_image, 0) ; } make_items() { Server_image help_pr ; main_cursor = xv_get(kcanvas, WIN_CURSOR) ; if (iscolor) { calctool_icon = (Icon) xv_get(frame, FRAME_ICON) ; XV_SET(calctool_icon, ICON_IMAGE, &cicon_pr, 0) ; XV_SET(frame, FRAME_ICON, calctool_icon, 0) ; } help_pr = xv_create(XV_NULL, SERVER_IMAGE, XV_WIDTH, 16, XV_HEIGHT, 16, SERVER_IMAGE_BITS, help_cursor_array, 0) ; help_cursor = xv_create(0, CURSOR, CURSOR_XHOT, 0, CURSOR_YHOT, 0, CURSOR_OP, PIX_SRC | PIX_DST, CURSOR_IMAGE, help_pr, 0) ; } make_subframes() { rcanvas = xv_create(rframe, CANVAS, 0) ; kcanvas = xv_create(frame, CANVAS, CANVAS_RETAINED, FALSE, OPENWIN_AUTO_CLEAR, FALSE, XV_WIDTH, TWIDTH, XV_HEIGHT, THEIGHT + DISPLAY, XV_FONT, nfont, CANVAS_PAINTWINDOW_ATTRS, WIN_CONSUME_EVENTS, MS_LEFT, MS_MIDDLE, MS_RIGHT, WIN_ASCII_EVENTS, KBD_USE, KBD_DONE, LOC_WINENTER, LOC_WINEXIT, WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS, 0, WIN_IGNORE_EVENTS, LOC_MOVE, LOC_DRAG, 0, WIN_EVENT_PROC, canvas_event_proc, 0, 0) ; rcpw = canvas_paint_window(rcanvas) ; cpw = canvas_paint_window(kcanvas) ; dpy = (Display *) xv_get(frame, XV_DISPLAY) ; xid_cpw = (Drawable) xv_get(cpw, XV_XID) ; xid_rcpw = (Drawable) xv_get(rcpw, XV_XID) ; screen = DefaultScreen(dpy) ; root = RootWindow(dpy, screen) ; foregnd = BlackPixel(dpy, screen) ; backgnd = WhitePixel(dpy, screen) ; gc_mask = GCForeground | GCBackground | GCGraphicsExposures ; gc_val.foreground = foregnd ; gc_val.background = backgnd ; gc_val.graphics_exposures = False ; gc = XCreateGC(dpy, root, gc_mask, &gc_val) ; load_colors() ; /* Load the calctool colormap. */ bfont = get_font(BIGFONT) ; nfont = get_font(NORMALFONT) ; nfont_width = nfont->max_bounds.rbearing - nfont->min_bounds.lbearing ; sfont = get_font(SMALLFONT) ; } /*ARGSUSED*/ menu_proc(menu, menu_item) Menu menu ; Menu_item menu_item ; { int choice ; choice = (int) menu_get(menu_item, MENU_VALUE, 0) ; if (choice) handle_menu_selection(curmenu, choice) ; } /*ARGSUSED*/ Seln_result reply_proc(item, context, length) Seln_attribute item ; Seln_replier_data *context ; int length ; { int size ; char *destp ; switch (item) { case SELN_REQ_CONTENTS_ASCII : if (context->context == NULL) { if (shelf == NULL) return(SELN_DIDNT_HAVE) ; context->context = shelf ; } size = strlen(context->context) ; destp = (char *) context->response_pointer ; STRCPY(destp, context->context) ; destp += size ; while ((int) destp % 4 != 0) *destp++ = '\0' ; context->response_pointer = (char **) destp ; *context->response_pointer++ = 0 ; return(SELN_SUCCESS) ; case SELN_REQ_YIELD : *context->response_pointer++ = (char *) SELN_SUCCESS ; return(SELN_SUCCESS) ; case SELN_REQ_BYTESIZE : if (shelf == NULL) return(SELN_DIDNT_HAVE) ; *context->response_pointer++ = (char *) strlen(shelf) ; return(SELN_SUCCESS) ; case SELN_REQ_END_REQUEST : return(SELN_SUCCESS) ; default : return(SELN_UNRECOGNIZED) ; } } set_cursor(type) int type ; { switch (type) { case HELPCURSOR : XV_SET(cpw, WIN_CURSOR, help_cursor, 0) ; break ; case MAINCURSOR : XV_SET(cpw, WIN_CURSOR, main_cursor, 0) ; } } start_tool() { started = 1 ; xv_main_loop(frame) ; } toggle_reg_canvas() { rstate = !rstate ; if (rstate) draw_regs() ; else XV_SET(rframe, XV_SHOW, FALSE, 0) ; }