📄 walkmenu_render.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)walkmenu_render.c 1.1 92/07/30 Copyright 1985 Sun Micro";#endif#endif/* * Copyright (c) 1985 by Sun Microsystems, Inc. *//*- WALKING MENU PACKAGE walkmenu_render.c, Sun Jun 30 15:38:39 1985 Craig Taylor, Sun Microsystems *//* ------------------------------------------------------------------------- */#include <sys/types.h>#include <sys/time.h>#include <stdio.h>#include <fcntl.h>#include <varargs.h>#include <pixrect/pixrect.h>#include <pixrect/pr_util.h>#include <pixrect/memvar.h>#include <sunwindow/rect.h>#include <sunwindow/rectlist.h>#include <sunwindow/cms.h>#include <sunwindow/pixwin.h>#include <sunwindow/win_screen.h>#include <sunwindow/win_input.h>#include <sunwindow/win_cursor.h>#include <sunwindow/win_struct.h>#include <sunwindow/win_ioctl.h>#include <suntool/fullscreen.h>#include <suntool/window.h>#include <suntool/walkmenu_impl.h>#define PIXRECT_NULL ((struct pixrect *)0)#define SCREEN_MARGIN 10 /* Minimum number of pixels away * from the edge of the screen a menu's * left and top sides should be. * (to enable backing out of * pullright menus *//* ------------------------------------------------------------------------- *//* * Public */ /* None *//* * Package private */Pkg_extern struct pixrect menu_arrow_pr; /* in walkmenu_create.c */Pkg_extern struct fullscreen *menu_fs; /* in walkmenu_public.c */Pkg_extern int menu_curitem();Pkg_private int menu_render();/* * Private */Private int compute_item_size();Private int compute_dimensions();Private void compute_rects();Private void render_items();Private int render_pullright();Private void paint_shadow();Private void paint_menu();Private void feedback();Private void constrainrect();Private void destroy_gen_items();/* * Private defs */#define MENU_SHADOW 6 /* Width of menu shadow */#define MENU_BORDER 1 /* Width of menu border */#define STANDOFF 3 /* 1/2 the number of active pixels left of the menu */extern int sv_journal;extern void win_sync();static int old_mousex, old_mousey;int menu_count;/* ------------------------------------------------------------------------- *//* * Menu_render modifies the inputevent parameter iep. * It should contain the last active inputevent read for the fd. */Pkg_private intmenu_render(menu, dynamic, parent, subrect, reenter, fd) struct menu *menu; struct menu_info *dynamic; struct menu_item *parent; struct rectnode *subrect; int fd;{ register struct menu *m; register struct menu_item *mi; register curitem, item_width, item_height; register struct inputevent *iep; register short menu_button, locx; struct image *std_image; struct menu *(*gen_proc)(); struct rect menurect, activerect, saverect, itemrect; struct pixrect *menu_image, *items_image; Pw_pixel_cache *pixel_cache; int stand_off, status, gen_items; int margin, right_margin, ncols, nrows; /* * Initial setup: Pull out dynamic information. */ menu->dynamic_info = dynamic, menu->parent = parent; dynamic->depth++; iep = dynamic->last_iep; menu_button = iep->ie_code; stand_off = reenter == FALSE && menu->stand_off; pixel_cache = PW_PIXEL_CACHE_NULL, gen_items = FALSE, gen_proc = NULL; /* * Dynamically create the menu if requested. */ if (gen_proc = menu->gen_proc) { m = (gen_proc)(menu, MENU_DISPLAY); if (m == NULL) { (void) fprintf(stderr, "menu_show: menu's gen_proc failed to generate a menu.\n"); goto error_exit; } m->dynamic_info = dynamic, m->parent = parent; } else { m = menu; } /* * No items, return to parent menu */ if (m->nitems == 0) { status = 1; goto exit; } /* * Find the current menu item */ if (reenter) { /* Based on default selection */ curitem = menu_curitem(m, m->default_selection, 1); } else { /* Based on initial selection */ curitem = menu_curitem(m, m->initial_selection, 1); if (!curitem) { status = 1; goto exit; } } /* * Compute the size of an item. */ std_image = &m->default_image; gen_items = compute_item_size(m, std_image); item_width = std_image->width; item_height = std_image->height; margin = std_image->margin; right_margin = std_image->right_margin; /* * Automatically compute the elided dimension. */ if (!compute_dimensions(m, item_width, item_height, &menurect, &ncols, &nrows)) goto error_exit; /* * Compute the rects: * menurect - represents the area of the menu including its borders. * activerect - extends the left edge of the menurect. Cursor motion * is mapped to its associated menu with this rect. * saverect - extended menurect with includes the menu shadow. */ compute_rects(m, iep, stand_off, curitem, item_width, item_height, ncols, nrows, &menurect, &activerect, &saverect); /* * Save the mouse position so that after selecting, it will return * to the same place */ if (menu_count++ == 0){ old_mousex = win_get_vuid_value(fd, LOC_X_ABSOLUTE); old_mousey = win_get_vuid_value(fd, LOC_Y_ABSOLUTE); } /* * Save image under menu, generate menu and display it. */ if (((pixel_cache = pw_save_pixels(menu_fs->fs_pixwin, &saverect)) == PW_PIXEL_CACHE_NULL) || (pw_primary_cached_mpr(menu_fs->fs_pixwin, pixel_cache) == (struct pixrect *)0)) goto error_exit; /* * Create pixrect w/menu image. * For now assume that the menu is monochrome. */ menu_image = mem_create(saverect.r_width, saverect.r_height, 1); items_image = pr_region(menu_image, MENU_BORDER, MENU_BORDER, item_width * ncols, item_height * nrows); paint_shadow(menu_image, m->shadow_pr, pw_primary_cached_mpr(menu_fs->fs_pixwin, pixel_cache)); render_items(m, std_image, items_image, ncols, nrows); /* * Display the menu and provide item highlighting. */ (void) pw_lock(menu_fs->fs_pixwin, &saverect); paint_menu(menu_image, &saverect, (m->shadow_pr)? 1: 0); if (!stand_off) feedback(m, &menurect, curitem, ncols, nrows, MENU_PROVIDE_FEEDBACK); (void) pw_unlock(menu_fs->fs_pixwin); mem_destroy(items_image); mem_destroy(menu_image); if (sv_journal) { win_sync(WIN_SYNC_MENU, fd); } /* From here on any returns from this procedure should go thru exit: */ /* * Handle initial selection expansion */ if (!reenter && !m->display_one_level) { mi = m->item_list[curitem - 1]; if (mi->pullright && !mi->inactive && !mi->selected && (mi->value || mi->gen_pullright)) { if (!mi->gen_pullright) { /* FIXME: Should handle gen pullright */ struct menu *mn = (struct menu *)LINT_CAST(mi->value); if (!menu_curitem(mn, mn->initial_selection, 0)) goto enter_input_loop; } if (stand_off) { feedback(m, &menurect, curitem, ncols, nrows, MENU_PROVIDE_FEEDBACK); } locx = menurect.r_left; if (m->column_major) locx += ((curitem - 1) / nrows + 1) * item_width + MENU_BORDER; else locx += ((curitem - 1) % ncols + 1) * item_width + MENU_BORDER; itemrect.r_width = locx; locx -= margin + right_margin + mi->image->right_pr->pr_width; locx -= stand_off ? STANDOFF : -STANDOFF; iep->ie_locx = locx; iep->ie_locy = menurect.r_top + MENU_BORDER; if (m->column_major) iep->ie_locy += (curitem - 1) % nrows * item_height + item_height / 2; else iep->ie_locy += (curitem - 1) / ncols * item_height + item_height / 2; itemrect.r_left = locx; itemrect.r_width -= locx; itemrect.r_top = iep->ie_locy - item_height / 2; itemrect.r_height = item_height; (void) win_setmouseposition(menu_fs->fs_windowfd, iep->ie_locx, iep->ie_locy); event_set_id(iep, menu_button); status = render_pullright(mi, subrect, &menurect, &itemrect, FALSE,fd); if (status == 0 || --status != 0) goto exit; stand_off = FALSE; } }enter_input_loop: if (stand_off) curitem = 0; locx = iep->ie_locx; /* * Track the mouse. */ for (;;) { register int itemx, itemy, newitem; int arrow_bdry; if (rect_includespoint(&activerect, iep->ie_locx, iep->ie_locy)) { /* * Check if cursor is in the current menu */ itemx = iep->ie_locx - menurect.r_left - MENU_BORDER; if (itemx < 0) itemx = m->nitems; /* Outside menu proper */ else { itemx = itemx / item_width; if (itemx >= ncols) itemx = ncols - 1; } itemy = (iep->ie_locy - menurect.r_top - MENU_BORDER) / item_height; if (itemy < 0) itemy = 0; else if (itemy >= nrows) itemy = nrows - 1; newitem = m->column_major ? itemx * nrows + itemy + 1 : itemy * ncols + itemx + 1; if (newitem > m->nitems) newitem = 0; } else { register struct rectnode *rp; if (subrect && !rect_includespoint(&subrect->rn_rect, iep->ie_locx, iep->ie_locy)) { if ((rect_includesrect(&menurect,&subrect->rn_next->rn_rect)) && iep->ie_locx < menurect.r_left) { /* * cursor is to the left of pullright, and * parent is obscured by the child menu, so we * pop back to the parent menu. */ status = 1; goto exit; } /* * Check if cursor is in a parent menu */ status = 1; for (rp = subrect->rn_next; rp; rp = rp->rn_next ? rp->rn_next->rn_next : NULL, status++) { if (rect_includespoint(&rp->rn_rect, iep->ie_locx, iep->ie_locy)) goto exit; } } newitem = 0; } /* * Provide feedback for new item. */ if (newitem != curitem) { /* revert item to normal state */ if (curitem) feedback(m, &menurect, curitem, ncols, nrows, MENU_REMOVE_FEEDBACK); curitem = newitem; /* invert new item */ if (curitem) { feedback(m, &menurect, curitem, ncols, nrows, MENU_PROVIDE_FEEDBACK); locx = iep->ie_locx; } } if (locx >= iep->ie_locx) locx = iep->ie_locx; if (newitem) { /* * If item is a menu, recurse. */ mi = m->item_list[newitem - 1]; if (mi->pullright) arrow_bdry = menurect.r_left + MENU_BORDER + STANDOFF + (itemx * item_width) + item_width - (margin + (mi->image->string?right_margin:0) + mi->image->right_pr->pr_width); if (mi->pullright && !mi->inactive && (iep->ie_locx > arrow_bdry || iep->ie_locx >= locx + m->pullright_delta) && (mi->value || mi->gen_pullright)) { if (iep->ie_locx > arrow_bdry) iep->ie_locx = arrow_bdry; iep->ie_locy = (menurect.r_top + MENU_BORDER + itemy * item_height + (item_height / 2)); event_set_id(iep, menu_button); /* Recurse */ itemrect.r_left = iep->ie_locx; itemrect.r_width = menurect.r_left + MENU_BORDER + STANDOFF + itemx * item_width + item_width - iep->ie_locx;; itemrect.r_top = iep->ie_locy - item_height / 2; itemrect.r_height = item_height; status = render_pullright(mi, subrect, &menurect, &itemrect, TRUE,fd); if (status == 0 || --status != 0) goto exit; locx = iep->ie_locx; } } /* * Get next input event. */ do { if (input_readevent(menu_fs->fs_windowfd, iep) == -1) { (void) fprintf(stderr, "menu_show: failed to track cursor.\n"); perror("menu_show"); status = -1; goto exit; } /* * If button up is the menu button then * an item has been selected, return it. */ if (menu_button == iep->ie_code && win_inputnegevent(iep)) { if (curitem == 0 || m->item_list[curitem-1]->inactive) m->dynamic_info->depth = 0, curitem = NULL; status = 0; goto exit; } else if (event_action(iep) == ACTION_HELP && win_inputposevent(iep)) { if (curitem == 0 || !m->item_list[curitem-1]->help_data) m->dynamic_info->help = m->help_data; else m->dynamic_info->help = m->item_list[curitem-1]->help_data; m->dynamic_info->depth = 0, curitem = NULL; status = 0; goto exit; } } while (iep->ie_code != LOC_MOVEWHILEBUTDOWN && iep->ie_code != LOC_STILL && iep->ie_code != LOC_MOVE); } /* Entry states at the next higher level: * status<0 abort menu chain (error or null selection), * status=0 valid selection save selected item, * status>0 cursor has entered a parent menu. */exit: if (status == 0 && curitem) m->selected_position = curitem; if (status > 0) --m->dynamic_info->depth; /* * set the mouse back to the position where it was first clicked */ if(--menu_count == 0) win_setmouseposition(menu_fs->fs_windowfd, old_mousex, old_mousey); pw_restore_pixels(menu_fs->fs_pixwin, pixel_cache); /* Checks for null */ if (gen_items) destroy_gen_items(m); m->dynamic_info = NULL; if (gen_proc) { (gen_proc)(m, MENU_DISPLAY_DONE); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -