📄 panel_choice.c
字号:
{ register choice_data *dp = choice_dp(ip); panel_image_handle old_choices = dp->choices; int old_last = dp->last; u_int *old_value = dp->value; Rect *old_choice_rects = dp->choice_rects; Rect *old_mark_rects = dp->mark_rects; struct pixrect **old_mark_on = dp->mark_on; struct pixrect **old_mark_off = dp->mark_off; register int num_choices, i, old_slot; /* counters */ struct pr_size size; /* count the # of choices */ for (num_choices = 0; choices[num_choices]; num_choices++); /* allocate the panel_image[] storage for the choices */ if ((dp->choices = (panel_image_handle) LINT_CAST(calloc((u_int) num_choices, sizeof(struct panel_image)))) == NULL) return 0; /* allocate the enclosing rectangles for each choice */ if ((dp->choice_rects = (Rect *) LINT_CAST(calloc((u_int) num_choices, sizeof(Rect)))) == NULL) return 0; /* allocate the enclosing rectangles for each mark */ if ((dp->mark_rects = (Rect *) LINT_CAST(calloc((u_int) num_choices, sizeof(Rect)))) == NULL) return 0; /* allocate the on mark images */ if ((dp->mark_on = (struct pixrect **) LINT_CAST(calloc((u_int) num_choices, sizeof(struct pixrect *)))) == NULL) return 0; /* allocate the off mark images */ if ((dp->mark_off = (struct pixrect **) LINT_CAST(calloc((u_int) num_choices, sizeof(struct pixrect *)))) == NULL) return 0; dp->last = num_choices - 1; /* last slot used in base[] */ /* allocate the value set */ if ((dp->value = CREATE_SET(dp->last)) == NULL) return 0; /* copy the old values */ COPY_SET(old_value, dp->value, min(dp->last, old_last)); /* Copy the choices to the allocated storage. * Here we reuse the old mark and font info * if it was given. */ for (i = 0; i <= dp->last; i++) { old_slot = (i <= old_last) ? i : old_last; dp->mark_on[i] = old_mark_on[old_slot]; dp->mark_off[i] = old_mark_off[old_slot]; dp->mark_rects[i] = old_mark_rects[old_slot]; dp->choice_rects[i] = old_choice_rects[old_slot]; size = panel_make_image(is_string(&old_choices[old_slot]) ? image_font(&old_choices[old_slot]) : ip->panel->font, &dp->choices[i], type, choices[i], dp->choices_bold, FALSE); dp->choice_rects[i].r_width = size.x; dp->choice_rects[i].r_height = size.y; } /* if there are fewer choices now, * and this is not a toggle item, * make sure the value is <= the number * of the last choice. */ if (dp->choose_one && (dp->last < old_last) && (choice_number(old_value, old_last) > dp->last)) { CLEAR_SET(dp->value, dp->last); ADD_CHOICE(dp->value, dp->last); } /* now free the old info */ (void)panel_free_choices(old_choices, 0, old_last); free((char *) old_choice_rects); free((char *) old_mark_rects); free((char *) old_mark_on); free((char *) old_mark_off); free((char *) old_value); return 1;} /* re_alloc_choices *//* modify_choice modifies the specified choice string or image. * If the specified choice does not already exist, the list of choices * is extended by adding empty choice strings. */static intmodify_choice(ip, type, which_choice, choice_info)register panel_item_handle ip; /* the item */int type; /* IM_STRING or IM_PIXRECT */int which_choice; /* choice to change */caddr_t choice_info; /* new choice string or pixrect */{ register choice_data *dp = choice_dp(ip); panel_image_handle old_choices = dp->choices; char *old_string = NULL; int old_last = dp->last; u_int *old_value = dp->value; Rect *old_choice_rects = dp->choice_rects; Rect *old_mark_rects = dp->mark_rects; struct pixrect **old_mark_on = dp->mark_on; struct pixrect **old_mark_off = dp->mark_off; register int num_choices, i, old_slot; /* counters */ struct pr_size size; /* expand the list if not big enough */ if (which_choice > dp->last) { num_choices = which_choice + 1; /* allocate the panel_image[] storage for the choices */ if ((dp->choices = (panel_image_handle) LINT_CAST(calloc((u_int) num_choices, sizeof(struct panel_image)))) == NULL) return 0; /* allocate the enclosing rectangles for each choice */ if ((dp->choice_rects = (Rect *) LINT_CAST(calloc((u_int) num_choices, sizeof(Rect)))) == NULL) return 0; /* allocate the enclosing rectangles for each mark */ if ((dp->mark_rects = (Rect *) LINT_CAST(calloc((u_int) num_choices, sizeof(Rect)))) == NULL) return 0; /* allocate the on mark images */ if ((dp->mark_on = (struct pixrect **) LINT_CAST(calloc((u_int) num_choices, sizeof(struct pixrect *)))) == NULL) return 0; /* allocate the off mark images */ if ((dp->mark_off = (struct pixrect **) LINT_CAST(calloc((u_int) num_choices, sizeof(struct pixrect *)))) == NULL) return 0; dp->last = num_choices - 1; /* last slot used in choices[] */ /* allocate the value set */ if ((dp->value = CREATE_SET(dp->last)) == NULL) return 0; /* copy the old values */ COPY_SET(old_value, dp->value, min(dp->last, old_last)); /* Copy the choices to the allocated storage. * Here we reuse the old mark and font info * if it was given. */ for (i = 0; i <= dp->last; i++) { old_slot = (i <= old_last) ? i : old_last; dp->mark_on[i] = old_mark_on[old_slot]; dp->mark_off[i] = old_mark_off[old_slot]; dp->mark_rects[i] = old_mark_rects[old_slot]; dp->choice_rects[i] = old_choice_rects[old_slot]; if (i <= old_last) dp->choices[i] = old_choices[old_slot]; else { size = panel_make_image(is_string(&old_choices[old_slot]) ? image_font(&old_choices[old_slot]) : ip->panel->font, &dp->choices[i], IM_STRING, "", dp->choices_bold, FALSE); dp->choice_rects[i].r_width = size.x; dp->choice_rects[i].r_height = size.y; } } } if (is_string(&dp->choices[which_choice])) old_string = image_string(&dp->choices[which_choice]); size = panel_make_image(is_string(&dp->choices[which_choice]) ? image_font(&dp->choices[which_choice]) : ip->panel->font, &dp->choices[which_choice], type, choice_info, dp->choices_bold, FALSE); dp->choice_rects[which_choice].r_width = size.x; dp->choice_rects[which_choice].r_height = size.y; if (old_string) free(old_string); if (dp->last != old_last) { /* now free the old info */ /* if new array is smaller, free the unused strings */ /* in any case, free old_choices */ (void)panel_free_choices(old_choices, (int) (dp->last + 1), old_last); free((char *) old_choice_rects); free((char *) old_mark_rects); free((char *) old_mark_on); free((char *) old_mark_off); free((char *) old_value); } return 1;} /* modify_choice */staticlayout_choices(ip)register panel_item_handle ip; /* the item *//* layout_choices lays out the choices and marks in ip.*/{ register struct choice_data *dp; /* choice data */ register int i; /* counter */ struct panel_image *image; /* each choice image */ struct pr_size size; /* each choice size */ Rect *rect; /* each choice rect */ Rect *mark_rect; /* each mark rect */ int left, top; /* corner of each choice */ int above_baseline; /* amount above baseline */ register int max_above; /* max. amount above baseline */ dp = choice_dp(ip); /* initialize above baseline offset */ max_above = 0; /* make sure the label is in the right place. * This is a hack to account for the baseline label * adjustment done below. */ panel_fix_label_position(ip); /* account for label size */ if (ip->label_rect.r_top == ip->value_rect.r_top) { size = image_size(&ip->label, &above_baseline); max_above = max(max_above, above_baseline); } /* initalize the value width & height */ ip->value_rect.r_width = 0; ip->value_rect.r_height = 0; left = ip->value_rect.r_left; /* layout each choice & mark */ for (i = 0; i <= dp->last; i++) { image = &(dp->choices[i]); rect = &(dp->choice_rects[i]); mark_rect = &(dp->mark_rects[i]); size = image_size(image, &above_baseline); /* compute maximum above baseline */ max_above = max(max_above, above_baseline); /* construct the mark rect */ rect_construct(mark_rect, left, 0, MARK_XOFFSET + max(dp->mark_on[i]->pr_width, dp->mark_off[i]->pr_width), max(dp->mark_on[i]->pr_height, dp->mark_off[i]->pr_height) ); /* adjust for the mark, if any */ if (dp->feedback == PANEL_MARKED) { /* update maximum above baseline */ max_above = max(max_above, mark_rect->r_height); } rect_construct(rect, dp->feedback == PANEL_MARKED ? rect_right(mark_rect) + 1 : left, 0, size.x, size.y); /* compute the position of the next choice */ if (dp->display_level == PANEL_ALL && ip->layout == PANEL_HORIZONTAL) left = rect_right(rect) + 1 + dp->choice_gap; } /* compute the top of each mark and choice rect */ top = ip->value_rect.r_top; /* adjust label rect height only if horizontal with value rect */ if (ip->label_rect.r_top == ip->value_rect.r_top) { size = image_size(&ip->label, &above_baseline); ip->label_rect.r_top += max_above - above_baseline; } for (i = 0; i <= dp->last; i++) { size = image_size(&dp->choices[i], &above_baseline); rect = &dp->choice_rects[i]; rect->r_top = top + max_above - above_baseline; mark_rect = &dp->mark_rects[i]; mark_rect->r_top = top + max_above - mark_rect->r_height; if (dp->display_level == PANEL_ALL && ip->layout == PANEL_VERTICAL) /* move down one row */ top = rect_bottom(rect) + 1 + dp->choice_gap; }} /* layout_choices *//* move_specified moves the specified choices marks in ip. * If any choices are moved, TRUE is returned. */static intmove_specified(ip, avlist)register panel_item_handle ip;register Attr_avlist avlist;{ register choice_data *dp = choice_dp(ip); register Panel_attribute attr; register int which_choice; /* index of current choice */ register int i; /* counter */ int *xs; /* choice x coordinates */ int *ys; /* choice y coordinates */ int *mark_xs; /* mark x coordinates */ int *mark_ys; /* mark y coordinates */ int moved = FALSE; /* TRUE if moved */ while (attr = (Panel_attribute) *avlist++) { switch (attr) { case PANEL_CHOICE_X: i = (int)*avlist++; dp->choice_rects[i].r_left = (int)*avlist++; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_X_FIXED; moved = TRUE; break; case PANEL_CHOICE_Y: i = (int)*avlist++; dp->choice_rects[i].r_top = (int)*avlist++; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_Y_FIXED; moved = TRUE; break; case PANEL_MARK_X: i = (int)*avlist++; dp->mark_rects[i].r_left = (int)*avlist++; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_X_FIXED; moved = TRUE; break; case PANEL_MARK_Y: i = (int)*avlist++; dp->mark_rects[i].r_top = (int)*avlist++; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_Y_FIXED; moved = TRUE; break; case PANEL_CHOICE_XS: xs = (int *) avlist; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_X_FIXED; if (xs[0]) for (which_choice = i = 0; which_choice <= dp->last; which_choice++, i += xs[i + 1] ? 1 : 0) dp->choice_rects[which_choice].r_left = xs[i]; while (*avlist++); moved = TRUE; break; case PANEL_CHOICE_YS: ys = (int *) avlist; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_Y_FIXED; if (ys[0]) for (which_choice = i = 0; which_choice <= dp->last; which_choice++, i += ys[i + 1] ? 1 : 0) dp->choice_rects[which_choice].r_top = ys[i]; while (*avlist++); moved = TRUE; break; case PANEL_MARK_XS: mark_xs = (int *) avlist; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_X_FIXED; if (mark_xs[0]) for (which_choice = i = 0; which_choice <= dp->last; which_choice++, i += mark_xs[i + 1] ? 1 : 0) dp->mark_rects[which_choice].r_left = mark_xs[i]; while (*avlist++); moved = TRUE; break; case PANEL_MARK_YS: mark_ys = (int *) avlist; dp->status.choice_fixed = TRUE; ip->flags |= VALUE_Y_FIXED; if (mark_ys[0]) for (which_choice = i = 0; which_choice <= dp->last; which_choice++, i += mark_ys[i + 1] ? 1 : 0) dp->mark_rects[which_choice].r_top = mark_ys[i]; while (*avlist++); moved = TRUE; break; default: /* skip past what we don't care about */ avlist = attr_skip(attr, avlist); break; } } return moved;} /* move_specified */staticupdate_value_rect(ip)panel_item_handle ip;/* update_value_rect computes the width & height of the value rect to enclose all of the choices & marks.*/{ register choice_data *dp = choice_dp(ip); Rect rect; register int i; if (dp->display_level != PANEL_NONE) { rect = ip->value_rect; rect.r_width = rect.r_height = 0; for (i = 0; i <= dp->last; i++) rect = panel_enclosing_rect(&rect, &dp->choice_rects[i]); if (dp->feedback == PANEL_MARKED) for (i = 0; i <= dp->last; i++) rect = panel_enclosing_rect(&rect, &dp->mark_rects[i]); ip->value_rect = rect; }} /* update_value_rect */staticpr_ycenter(dest, src)struct pixrect *dest, *src;/* pr_ycenter writes src into dest centered in the y direction.*/{ (void)pr_rop(dest, 0, (dest->pr_height - src->pr_height + 1) / 2, src->pr_width, src->pr_height, PIX_SRC, src, 0, 0);} /* pr_ycenter *//* ops vector routines */staticdestroy(dp)register choice_data *dp;{ (void)panel_free_choices(dp->choices, 0, (int) dp->last); free((char *) dp->choice_rects); free((char *) dp->mark_rects); free((char *) dp->mark_on); free((char *) dp->mark_off); free((char *) dp->value); free((char *) dp);} /* destroy */staticlayout(ip, deltas)panel_item_handle ip;Rect *deltas;{ register choice_data *dp = choice_dp(ip); register int i; /* bump each choice & mark rect */ for (i = 0; i <= dp->last; i++) { dp->choice_rects[i].r_left += deltas->r_left; dp->choice_rects[i].r_top += deltas->r_top; dp->mark_rects[i].r_left += deltas->r_left; dp->mark_rects[i].r_top += deltas->r_top; }} /* layout */staticpaint(ip)register panel_item_handle ip;{ register choice_data *dp = choice_dp(ip); register int i; /* paint the label */ (void)panel_paint_image(ip->panel, &ip->label, &ip->label_rect,PIX_COLOR(ip->color_index)); /* paint the choices */ switch (dp->display_level) { case PANEL_NONE: /* don't draw the choices */ break; case PANEL_CURRENT: /* draw the current choice */ if (dp->choose_one) paint_choice(ip->panel, dp, choice_number(dp->value, dp->last),ip); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -