📄 walkmenu_render.c
字号:
return status;error_exit: status = -1; m->dynamic_info->depth = 0; goto exit;}/* * Compute max item size. Only zero sized items have to be recomputed */Private intcompute_item_size(menu, std_image) struct menu *menu; struct image *std_image;{ register int width, height, nitems, recompute; register struct menu_item *mi, **mip; int gen_items = FALSE; nitems = menu->nitems; width = height = 0; recompute = std_image->width == 0; /* * This causes the menu to shrink around the items. * When the std_image is available at the client interface zeroing the * size of std_image should be rethought. */ std_image->width = std_image->height = 0; /* Compute max size if any of the items have changed */ for (mip = menu->item_list;mi = *mip, nitems--; mip++) { mi->parent = menu; if (mi->gen_proc) { *mip = mi = (mi->gen_proc)(mi, MENU_DISPLAY); gen_items = TRUE; } /* This is an untested (unnecessary?) optimization */ if (recompute) mi->image->width = 0; /* This forces the size to be * recompute inside image_get() */ if (mi->image->width == 0) { width = imax(image_get(mi->image, std_image, IMAGE_WIDTH), width); height = imax((int)image_get(mi->image, std_image, IMAGE_HEIGHT), height); } else { width = imax(mi->image->width, width); height = imax(mi->image->height, height); } } std_image->width = width; std_image->height = height; return gen_items;}/* * Compute the dimensions of the menu. */Private intcompute_dimensions(menu, iwidth, iheight, rect, ncolp, nrowp) register struct menu *menu; int iwidth, iheight; register Rect *rect; int *ncolp, *nrowp;{ register int ncols, nrows; ncols = menu->ncols; nrows = menu->nrows; /* Fix 1015167: subtract SCREEN_MARGIN everywhere */ if (!(ncols && nrows)) { if (ncols) { /* case: ncols=n, nrows=to fit */ rect->r_width = (ncols * iwidth) + 2*MENU_BORDER + (menu->shadow_pr ? MENU_SHADOW : 0); if (rect->r_width > menu_fs->fs_screenrect.r_width -SCREEN_MARGIN) { ncols = (menu_fs->fs_screenrect.r_width - SCREEN_MARGIN - 2*MENU_BORDER + (menu->shadow_pr ? MENU_SHADOW : 0)) / iwidth; } nrows = (menu->nitems - 1) / ncols + 1; } else { /* case: nrows=n, ncols=to fit */ if (!nrows) nrows = menu->nitems; /* Both zero, fit cols */ rect->r_height = (nrows * iheight) + 2*MENU_BORDER + (menu->shadow_pr ? MENU_SHADOW : 0); if (rect->r_height > menu_fs->fs_screenrect.r_height - SCREEN_MARGIN) { nrows = (menu_fs->fs_screenrect.r_height - SCREEN_MARGIN - 2*MENU_BORDER - (menu->shadow_pr ? MENU_SHADOW : 0)) / iheight; ncols = (menu->nitems - 1) / nrows + 1; nrows = (menu->nitems - 1) / ncols + 1; } else { ncols = (menu->nitems - 1) / nrows + 1; } } } rect->r_width = (ncols * iwidth) + 2*MENU_BORDER + (menu->shadow_pr ? MENU_SHADOW : 0); rect->r_height = (nrows * iheight) + 2*MENU_BORDER + (menu->shadow_pr ? MENU_SHADOW : 0); if (rect->r_width > menu_fs->fs_screenrect.r_width - SCREEN_MARGIN || rect->r_height > menu_fs->fs_screenrect.r_height - SCREEN_MARGIN) { (void) fprintf(stderr, "menu_show: Menu too large for screen.\n"); return FALSE; } *ncolp = ncols; *nrowp = nrows; return TRUE; }/* * Compute 3 rects: * mrect = menu_image; * srect = mrect + shadow * irect = input region = menu_rect + stand_off region */Private voidcompute_rects(menu, iep, stand_off, curitem, item_width, item_height, ncols, nrows, mrect, irect, srect) struct menu *menu; struct inputevent *iep; int stand_off, curitem, item_width, item_height, ncols, nrows; Rect *mrect, *irect, *srect;{ int left, top; left = item_width * (menu->column_major ? (curitem - 1) / nrows : (curitem - 1) % ncols); top = item_height * (menu->column_major ? (curitem - 1) % nrows : (curitem - 1) / ncols); mrect->r_left = iep->ie_locx - left - MENU_BORDER; mrect->r_top = iep->ie_locy - top - MENU_BORDER - item_height / 2; if (left != 0) stand_off = FALSE; /* Not on the edge */ /* Move the menu under the cursor so that it is outside/inside the item */ mrect->r_left += stand_off ? STANDOFF : -STANDOFF; left = mrect->r_left, top = mrect->r_top; constrainrect(mrect, &menu_fs->fs_screenrect); if (left != mrect->r_left || top != mrect->r_top) { iep->ie_locx -= left - mrect->r_left; iep->ie_locy -= top - mrect->r_top; (void) win_setmouseposition(menu_fs->fs_windowfd, iep->ie_locx, iep->ie_locy); } *srect = *mrect; /* Remember total size of affected area */ if (menu->shadow_pr) { mrect->r_width -= MENU_SHADOW; mrect->r_height -= MENU_SHADOW; } *irect = *mrect; if (stand_off) { irect->r_left -= STANDOFF; irect->r_width += STANDOFF; }}/* * Rop items into supplied pixrect */Private voidrender_items(menu, std_image, pr, ncols, nrows) struct menu *menu; struct image *std_image; struct pixrect *pr;{ register int top, left, n, i, j; register struct menu_item **mip; int item_width, item_height; register total_height, total_width; item_width = std_image->width; item_height = std_image->height; mip = menu->item_list; n = 0; total_height = item_height * nrows; total_width = item_width * ncols; if (menu->column_major) { for (j = left = 0; j < ncols; j++) { for (i = top = 0; i < nrows; i++) { if (++n > menu->nitems) break; if ((*mip)->inactive) { image_render((*mip)->image, std_image, LINT_CAST(IMAGE_REGION), pr, left, top, IMAGE_INACTIVE, 0); } else { image_render((*mip)->image, std_image, LINT_CAST(IMAGE_REGION), pr, left, top, 0); } if (menu->h_line || (*mip)->h_line) { image_vector(0,top+item_height,total_width-1,top+item_height); } if (menu->v_line || (*mip)->v_line) { image_vector(left+item_width,0,left+item_width,total_height-1); } top += item_height; mip++; } left += item_width; } } else { for (i = top = n = 0; i < nrows; i++) { for (j = left = 0; j < ncols; j++) { if (++n > menu->nitems) break; if ((*mip)->inactive) image_render((*mip)->image, std_image, LINT_CAST(IMAGE_REGION), pr, left, top, IMAGE_INACTIVE, 0); else { image_render((*mip)->image, std_image, LINT_CAST(IMAGE_REGION), pr, left, top, 0); } if (menu->h_line || (*mip)->h_line) { image_vector(0,top+item_height,total_width-1,top+item_height); } if (menu->v_line || (*mip)->v_line) { image_vector(left+item_width,0,left+item_width,total_height-1); } left += item_width; mip++; } top += item_height; } }}/* * Handle recursive calls for pullright items */Private intrender_pullright(mi, subrect, menurect, itemrect, reenter, fd) register struct menu_item *mi; Rectnode *subrect; Rect *menurect, *itemrect; int fd;{ register struct menu *m, *(*gen_proc)(); struct rectnode menu_node, active_node; int status; if (gen_proc = mi->gen_pullright) { m = (gen_proc)(mi, MENU_DISPLAY); if (!m) { (void) fprintf(stderr, "menu_show: gen_proc failed to generate a pullright menu.\n"); return -1; } mi->value = (caddr_t)m; } else { m = (struct menu *)LINT_CAST(mi->value); } menu_node.rn_next = subrect, menu_node.rn_rect = *menurect; active_node.rn_next = &menu_node, active_node.rn_rect = *itemrect; status = menu_render(m, mi->parent->dynamic_info, mi, &active_node, reenter, fd); if (gen_proc) mi->value = (caddr_t)(gen_proc)(mi, MENU_DISPLAY_DONE); return status;}Private voidpaint_shadow(pr, shadow_pr, save_pr) register struct pixrect *pr, *shadow_pr, *save_pr;{ if (shadow_pr) { /* Draw borders with shadows */ (void) pr_rop(pr, 0, 0, pr->pr_width - MENU_SHADOW, MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, 0, MENU_BORDER, MENU_BORDER, pr->pr_height - MENU_SHADOW - 2*MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, pr->pr_width - MENU_SHADOW - MENU_BORDER, MENU_BORDER, MENU_BORDER, pr->pr_height - MENU_SHADOW - 2*MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, 0, pr->pr_height - MENU_SHADOW - MENU_BORDER, pr->pr_width - MENU_SHADOW, MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); /* Fill in with background */ (void) pr_rop(pr, pr->pr_width - MENU_SHADOW, 0, MENU_SHADOW, pr->pr_height, PIX_SRC, save_pr, pr->pr_width - MENU_SHADOW, 0); (void) pr_rop(pr, 0, pr->pr_height - MENU_SHADOW, pr->pr_width - MENU_SHADOW, MENU_SHADOW, PIX_SRC, save_pr, 0, pr->pr_height - MENU_SHADOW); /* Rop shadow over background */ (void) pr_replrop(pr, pr->pr_width - MENU_SHADOW, MENU_SHADOW, MENU_SHADOW, pr->pr_height - MENU_SHADOW, PIX_SRC /* |PIX_DST opaque shadow */, shadow_pr, pr->pr_width - MENU_SHADOW, MENU_SHADOW); (void) pr_replrop(pr, MENU_SHADOW, pr->pr_height - MENU_SHADOW, pr->pr_width - 2 * MENU_SHADOW, MENU_SHADOW, PIX_SRC /* |PIX_DST */, shadow_pr, MENU_SHADOW, pr->pr_height - MENU_SHADOW); } else { /* Draw borders without shadows */ (void) pr_rop(pr, 0, 0, pr->pr_width, MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, 0, MENU_BORDER - 1, MENU_BORDER, pr->pr_height - 2*MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, pr->pr_width - MENU_BORDER - 1, MENU_BORDER - 1, MENU_BORDER, pr->pr_height - 2*MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); (void) pr_rop(pr, 0, pr->pr_height - MENU_BORDER - 1, pr->pr_width, MENU_BORDER, PIX_SET, PIXRECT_NULL, 0, 0); }}Private voidpaint_menu(image, rect, shadow) register struct pixrect *image; register Rect *rect; register int shadow;{ if (menu_fs->fs_pixwin->pw_pixrect->pr_depth > 1 && shadow) { rect->r_width -= MENU_SHADOW; rect->r_height -= MENU_SHADOW; } (void) pw_preparesurface_full(menu_fs->fs_pixwin, rect, 1); (void) pw_write(menu_fs->fs_pixwin, rect->r_left, rect->r_top, rect->r_width, rect->r_height, PIX_SRC, image, 0, 0); if (menu_fs->fs_pixwin->pw_pixrect->pr_depth > 1 && shadow) { Rect shadow_rect; shadow_rect.r_left = rect->r_left + rect->r_width; shadow_rect.r_top = rect->r_top + MENU_SHADOW; shadow_rect.r_width = MENU_SHADOW; shadow_rect.r_height = rect->r_height; (void) pw_preparesurface_full(menu_fs->fs_pixwin, &shadow_rect, 1); (void) pw_write(menu_fs->fs_pixwin, shadow_rect.r_left, shadow_rect.r_top, MENU_SHADOW, rect->r_height, PIX_SRC /* | PIX_DST opaque shadow */, image, image->pr_width - MENU_SHADOW, MENU_SHADOW); shadow_rect.r_left = rect->r_left + MENU_SHADOW; shadow_rect.r_top = rect->r_top + rect->r_height; shadow_rect.r_width = rect->r_width - MENU_SHADOW; shadow_rect.r_height = MENU_SHADOW; (void)pw_preparesurface_full(menu_fs->fs_pixwin, &shadow_rect, 1); (void) pw_write(menu_fs->fs_pixwin, shadow_rect.r_left, shadow_rect.r_top, shadow_rect.r_width, MENU_SHADOW, PIX_SRC /* | PIX_DST opaque shadow */, image, MENU_SHADOW, image->pr_height - MENU_SHADOW); rect->r_width += MENU_SHADOW; rect->r_height += MENU_SHADOW; }}/* * Provide feedback directly to the pixwin. * Someday this should be a client settable option. */Private voidfeedback(m, r, n, ncols, nrows, state) register struct menu *m; struct rect *r; int n, ncols, nrows; Menu_feedback state;{ struct menu_item *mi = m->item_list[n - 1]; int max_width = m->default_image.width; int max_height = m->default_image.height; if (!mi->no_feedback && !m->feedback_proc && !mi->inactive) { int left, top; register int margin = m->default_image.margin; n--; /* Convert to zero origin */ left = (r->r_left + MENU_BORDER + margin + (m->column_major ? n / nrows : n % ncols) * max_width); top = (r->r_top + MENU_BORDER + margin + (m->column_major ? n % nrows : n / ncols) * max_height); (void) pw_writebackground(menu_fs->fs_pixwin, left, top, max_width - 2 * margin, max_height - 2 * margin, PIX_NOT(PIX_DST)); } else if (m->feedback_proc) (m->feedback_proc)(mi, state); /* FIXME: Pass rect or region? */}/* * Menu must be completely on the screen. */Private voidconstrainrect(rconstrain, rbound) register struct rect *rconstrain, *rbound;{ /* * Bias algorithm to have too big rconstrain fall off right/bottom. */ if (rect_right(rconstrain) > rect_right(rbound)) { rconstrain->r_left = rbound->r_left + rbound->r_width - rconstrain->r_width; } if (rconstrain->r_left < rbound->r_left) { rconstrain->r_left = rbound->r_left + SCREEN_MARGIN; } if (rect_bottom(rconstrain) > rect_bottom(rbound)) { rconstrain->r_top = rbound->r_top + rbound->r_height - rconstrain->r_height; } if (rconstrain->r_top < rbound->r_top) { rconstrain->r_top = rbound->r_top + SCREEN_MARGIN; }}/* * Clean up any client generated items */Private voiddestroy_gen_items(menu) struct menu *menu;{ register int nitems; register struct menu_item *mi, **mip; nitems = menu->nitems; /* Give client a chance to clean up any generated items */ for (mip = menu->item_list;mi = *mip, nitems--; mip++) if (mi->gen_proc) *mip = (mi->gen_proc)(mi, MENU_DISPLAY_DONE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -