📄 panel_choice.c
字号:
#ifndef lint#ifdef sccsstatic char sccsid[] = "@(#)panel_choice.c 1.1 92/07/30 Copyr 1984 Sun Micro";#endif#endif/*****************************************************************************//* panel_choice.c *//* Copyright (c) 1985 by Sun Microsystems, Inc. *//*****************************************************************************/#include <suntool/panel_impl.h>#include <sundev/kbd.h>#include "sunwindow/sv_malloc.h"static short check_off_image[] = {#include <images/panel_check_off.pr>};static mpr_static(panel_check_off, 16, 16, 1, check_off_image);static short check_on_image[] = {#include <images/panel_check_on.pr>};static mpr_static(panel_check_on, 16, 16, 1, check_on_image);static short choice_off_image[] = {#include <images/panel_choice_off.pr>};static mpr_static(panel_choice_off, 16, 16, 1, choice_off_image);static short choice_on_image[] = {#include <images/panel_choice_on.pr>};static mpr_static(panel_choice_on, 16, 16, 1, choice_on_image);#define NULL_CHOICE -1#define MARK_XOFFSET 3 /* # of pixels to leave after a mark */#define CHOICE_X_GAP 10 /* # of x pixels between choices */#define CHOICE_Y_GAP 5 /* # of x pixels between choices *//* assume 8 bits per byte, so byte for nth * element is n/8, bit within that byte is * defined by the loworder three bits of n. */#define WORD(n) (n >> 5) /* word for element n */#define BIT(n) (n & 0x1F) /* bit in word for element n *//* Create a set with n elements. * Clear a set with n elements. * Copy n elements from one set to another */#define CREATE_SET(n) \ ((u_int *) LINT_CAST(calloc((u_int) (WORD(n) + 1), sizeof(u_int))))#define CLEAR_SET(set, n) \ (bzero((char *) (set), (int) (WORD(n) + 1) * sizeof(u_int)))#define COPY_SET(from_set, to_set, n) \ (bcopy((char *) (from_set), (char *) (to_set), (int) ((WORD(n) + 1) * sizeof(u_int))))/* Add a choice by or-ing in the correct bit. * Remove a choice by and-ing out the correct bit. */#define ADD_CHOICE(set, n) ((set)[WORD(n)] |= (1 << BIT(n)))#define REMOVE_CHOICE(set, n) ((set)[WORD(n)] &= ~(1 << BIT(n)))/* See if the nth bit is on */#define IN(set, n) (((set)[WORD(n)] >> BIT(n)) & 01)#define EACH_CHOICE(set, last_element, n) \ for ((n) = 0; (n) <= (last_element); (n)++) \ if (IN(set, n))#define choice_dp(ip) (choice_data *) LINT_CAST((ip)->data)static begin_preview(), update_preview(), cancel_preview(), accept_preview(), accept_menu(), paint(), destroy(), set_attr(), layout(), sync_menu(); static void update_item_rect();static caddr_t get_attr();static int choice_number();static u_int choice_value();static struct panel_ops ops = { panel_default_handle_event, /* handle_event() */ begin_preview, /* begin_preview() */ update_preview, /* update_preview() */ cancel_preview, /* cancel_preview() */ accept_preview, /* accept_preview() */ accept_menu, /* accept_menu() */ panel_nullproc, /* accept_key() */ paint, /* paint() */ destroy, /* destroy() */ get_attr, /* get_attr() */ set_attr, /* set_attr() */ (caddr_t (*)()) panel_nullproc, /* remove() */ (caddr_t (*)()) panel_nullproc, /* restore() */ layout /* layout() */};static struct pr_size image_size();typedef struct choice_data { /* data for a choice item */ struct { unsigned gap_set : 1; unsigned feedback_set : 1; unsigned choice_fixed : 1; unsigned menu_dirty : 1; } status; int current; /* current choice */ int actual; /* actual value of current */ u_int *value; /* bit field of choices */ int last; /* last possible choice */ Panel_setting display_level; /* NONE, CURRENT, ALL */ int choose_one; /* only one choice allowed */ Panel_setting feedback; /* MARKED, INVERTED, NONE */ struct panel_image *choices; /* each choice */ Rect *choice_rects; /* each choice rect */ Rect *mark_rects; /* each mark rect */ int choice_gap; /* gap between choices */ int choices_bold : 1; /* bold/not choices strings */ struct pixrect **mark_on; /* selection mark images */ struct pixrect **mark_off; /* un-selected mark images */} choice_data;/*****************************************************************************//* choice item create routine *//* Appends a new choice item to "panel". Returns a pointer to the new item. *//*****************************************************************************/Panel_itempanel_choice(ip, avlist)register panel_item_handle ip;Attr_avlist avlist;{ register choice_data *dp; /* choice data */ dp = (choice_data *) LINT_CAST(calloc(1, sizeof(choice_data))); if (!dp) return (NULL); ip->flags |= SHOW_MENU_MARK; /* default is menu on for choice items */ if (!show_menu_set(ip->panel)) ip->flags |= SHOW_MENU; ip->ops = &ops; ip->data = (caddr_t) dp; ip->item_type = PANEL_CHOICE_ITEM; /* initialize */ dp->value = CREATE_SET(1); /* set with one choice */ ADD_CHOICE(dp->value, 0); /* default is choice 0 selected */ dp->current = NULL_CHOICE; /* no current choice */ dp->actual = FALSE; /* current choice is off */ dp->last = 0; /* last slot is slot zero */ dp->display_level = PANEL_ALL; /* default is display all choices */ dp->choose_one = TRUE; /* check only one choice */ dp->feedback = PANEL_MARKED; /* marked feedback */ /* menu is dirty to start, * since it must be created to * match the default single choice * string. */ dp->status.menu_dirty = TRUE; /* initialize choices to a single * string choice of "". * Note that we do not call layout_choices() here. * The default layout is now to not have the label and * single mark baselines align. If we lower the label * at this point, and the client has fixed its position, * the baseline will not be realigned when choices are added. * So we settle for a bug in the initial state: label baseline does not * line up with single mark baseline. This restores release 3.0 * behavior. */ dp->choices = (panel_image_handle) LINT_CAST(sv_malloc(sizeof(struct panel_image))); panel_make_image(ip->panel->font, &dp->choices[0], IM_STRING, "", FALSE, FALSE); dp->choice_rects = (Rect *) LINT_CAST(sv_malloc(sizeof(Rect))); dp->choice_rects[0] = ip->value_rect; /* space between choices */ dp->choice_gap = (ip->layout == PANEL_HORIZONTAL) ? CHOICE_X_GAP : CHOICE_Y_GAP; /* set up the default choice marks */ dp->mark_on = (struct pixrect **) LINT_CAST(malloc(sizeof(struct pixrect *))); dp->mark_off = (struct pixrect **) LINT_CAST(sv_malloc(sizeof(struct pixrect *))); dp->mark_on[0] = &panel_choice_on;/* for PANEL_MARKED feedback */ dp->mark_off[0] = &panel_choice_off;/* for PANEL_MARKED feedback */ dp->mark_rects = (Rect *) LINT_CAST(sv_malloc(sizeof(Rect))); dp->mark_rects[0] = dp->choice_rects[0]; dp->mark_rects[0].r_width = dp->mark_on[0]->pr_width; dp->mark_rects[0].r_height = dp->mark_on[0]->pr_height; /* update the value and item rect */ update_item_rect(ip); if (!set_attr(ip, avlist)) return NULL; /* NOTE: append should be done in central create routine. */ return (Panel_item) panel_append(ip);} /* panel_choice */static intset_attr(ip, avlist)register panel_item_handle ip;register Attr_avlist avlist;{ register Panel_attribute attr; /* each attribute */ register choice_data *dp = choice_dp(ip); int choices_type = -1; /* IM_STRING or IM_PIXRECT */ caddr_t *choices; /* choices array */ struct pixfont **choices_fonts = NULL; /* choices fonts */ struct pixrect **mark_images, **nomark_images; short mark_images_set = FALSE; short nomark_images_set = FALSE; Attr_avlist orig_avlist = avlist; /* original avlist */ u_int value; /* initial value */ int which_choice, which_arg; short choices_changed = FALSE; short choices_moved = FALSE; while (attr = (Panel_attribute) *avlist++) { switch (attr) { case PANEL_CHOICE_STRINGS: case PANEL_CHOICE_IMAGES: choices_type = attr == PANEL_CHOICE_STRINGS ? IM_STRING : IM_PIXRECT; choices = avlist; /* base of the array */ while (*avlist++); /* skip past the list */ break; case PANEL_CHOICE_STRING: case PANEL_CHOICE_IMAGE: which_choice = (int) *avlist++; if (!modify_choice(ip, attr == PANEL_CHOICE_STRING ? IM_STRING : IM_PIXRECT, which_choice, *avlist++)) return 0; choices_changed = TRUE; break; case PANEL_CHOICE_FONTS: choices_fonts = (struct pixfont **) avlist; while (*avlist++); /* skip past the list */ break; case PANEL_CHOICES_BOLD: dp->choices_bold = (*avlist++ != 0); for (which_choice = 0; which_choice <= dp->last; which_choice++) if (is_string(&dp->choices[which_choice])) image_bold(&dp->choices[which_choice]) = dp->choices_bold; choices_changed = TRUE; break; case PANEL_CHOICE_OFFSET: dp->choice_gap = (int) *avlist++; dp->status.gap_set = TRUE; choices_changed = TRUE; break; case PANEL_CHOOSE_ONE: dp->choose_one = (int) *avlist++; CLEAR_SET(dp->value, dp->last); if (dp->choose_one) { ip->item_type = PANEL_CHOICE_ITEM; ADD_CHOICE(dp->value, 1); } else { ip->item_type = PANEL_TOGGLE_ITEM; /* Note that this depends on the fact that PANEL_CHOOSE_ONE can only be specified at creat time, as part of the PANEL_TOGGLE macro. So no choices have been set yet. */ dp->mark_on[0] = &panel_check_on; dp->mark_off[0] = &panel_check_off; /* force re-layout and resize of rect */ choices_changed = TRUE; } break; case PANEL_LAYOUT: avlist++; if (!dp->status.gap_set) dp->choice_gap = ip->layout == PANEL_HORIZONTAL ? CHOICE_X_GAP : CHOICE_Y_GAP; choices_changed = TRUE; break; case PANEL_FEEDBACK: dp->feedback = (Panel_setting) *avlist++; dp->status.feedback_set = TRUE; choices_changed = TRUE; break; case PANEL_MARK_IMAGES: mark_images = (struct pixrect **) avlist; mark_images_set = TRUE; while (*avlist++); break; case PANEL_NOMARK_IMAGES: nomark_images = (struct pixrect **) avlist; nomark_images_set = TRUE; while (*avlist++); break; case PANEL_MARK_IMAGE: case PANEL_NOMARK_IMAGE: avlist++; if (!*avlist) *avlist = (caddr_t) &panel_empty_pr; avlist++; break; case PANEL_SHOW_MENU: if ((int) *avlist++) ip->flags |= SHOW_MENU; else ip->flags &= ~SHOW_MENU; break; default: /* skip past what we don't care about */ avlist = attr_skip(attr, avlist); break; } } if (set(choices_type)) { if (!re_alloc_choices(ip, choices_type, choices)) return 0; choices_changed = TRUE; } if (choices_fonts) { for (which_choice = which_arg = 0; which_choice <= dp->last; which_choice++, which_arg += choices_fonts[which_arg + 1] ? 1 : 0) if (is_string(&dp->choices[which_choice])) image_font(&dp->choices[which_choice]) = choices_fonts[which_arg]; choices_changed = TRUE; } if (mark_images_set) { /* reset to empty pixrect if no list */ if (!mark_images[0]) for (which_choice = 0; which_choice <= dp->last; which_choice++) dp->mark_on[which_choice] = &panel_empty_pr; else for (which_choice = which_arg = 0; which_choice <= dp->last; which_choice++, which_arg += mark_images[which_arg + 1] ? 1 : 0) dp->mark_on[which_choice] = mark_images[which_arg]; choices_changed = TRUE; } if (nomark_images_set) { /* reset to empty pixrect if no list */ if (!nomark_images[0]) for (which_choice = 0; which_choice <= dp->last; which_choice++) dp->mark_off[which_choice] = &panel_empty_pr; else for (which_choice = which_arg = 0; which_choice <= dp->last; which_choice++, which_arg += nomark_images[which_arg + 1] ? 1 : 0) dp->mark_off[which_choice] = nomark_images[which_arg]; choices_changed = TRUE; } /* now set things that depend on the new list * of choices or the attributes that were set above. */ avlist = orig_avlist; while (attr = (Panel_attribute) *avlist++) { switch (attr) { case PANEL_MARK_IMAGE: case PANEL_NOMARK_IMAGE: which_choice = (int) LINT_CAST(*avlist++); if (which_choice < 0 || which_choice > dp->last) return 0; dp->mark_on[which_choice] = (struct pixrect *) LINT_CAST(*avlist++); /* may have to relayout the choices */ choices_changed = TRUE; break; case PANEL_CHOICE_FONT: which_choice = (int) *avlist++; if (which_choice < 0 || which_choice > dp->last) return 0; if (is_string(&dp->choices[which_choice])) image_font(&dp->choices[which_choice]) = (Pixfont *) *avlist++; choices_changed = TRUE; break; case PANEL_VALUE: value = (u_int) *avlist++; if (dp->choose_one) { if(value <= dp->last) { CLEAR_SET(dp->value, dp->last); ADD_CHOICE(dp->value, value); } } else dp->value[0] = value; break; case PANEL_TOGGLE_VALUE: which_choice = (int) *avlist++; if (which_choice < 0 || which_choice > dp->last) return 0; if (*avlist++) ADD_CHOICE(dp->value, which_choice); else REMOVE_CHOICE(dp->value, which_choice); break; case PANEL_DISPLAY_LEVEL: dp->display_level = (Panel_setting) *avlist++; /* ignore PANEL_CURRENT for toggles */ if (dp->display_level == PANEL_CURRENT && !dp->choose_one) dp->display_level = PANEL_ALL; /* set the default feedback */ if (!dp->status.feedback_set) switch (dp->display_level) { case PANEL_NONE: case PANEL_CURRENT: dp->feedback = PANEL_NONE; break; default: dp->feedback = PANEL_MARKED; } choices_changed = TRUE; break; default: /* skip past what we don't care about */ avlist = attr_skip(attr, avlist); break; } } /* layout the choices if they have * changed and no choice or mark has a fixed position. */ if (choices_changed) { dp->status.menu_dirty = TRUE; if (!dp->status.choice_fixed) layout_choices(ip); } /* move any specified choices */ choices_moved = move_specified(ip, orig_avlist); if (choices_changed || choices_moved) update_item_rect(ip); return 1;} /* set_attr */static voidupdate_item_rect(ip)panel_item_handle ip;{ update_value_rect(ip); ip->rect = panel_enclosing_rect(&ip->label_rect, &ip->value_rect);} /* re_alloc_choices allocates dp->choices from choices. The * old info is reused and then freed. */static intre_alloc_choices(ip, type, choices)register panel_item_handle ip; /* the item */int type; /* IM_STRING or IM_PIXRECT */caddr_t choices[]; /* each choice */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -