listbox.c

来自「一个很有名的浏览器」· C语言 代码 · 共 715 行 · 第 1/2 页

C
715
字号
		for (i = depth - d; i; i--) {			child = root;			if (root) root = data->box->ops->get_root(root);		}		/* XXX */		x = data->widget_data->box.x + d * 5;		draw_text(data->term, x, y, "     ", 5, 0, color);		if (root ? root->child.prev == child			 : data->box->items->prev == child)			continue; /* We were the last branch. */		draw_border_char(data->term, x + 1, y, BORDER_SVLINE, color);	}	if (depth) {		enum border_char str[5] =			{ 32, BORDER_SRTEE, BORDER_SHLINE, BORDER_SHLINE, 32 };		int i;		switch (item->type) {		case BI_LEAF:		case BI_SEPARATOR:		{			struct listbox_item *root = data->box->ops->get_root(item);			if (root) {				if (item == root->child.prev) {					str[1] = BORDER_SDLCORNER;				}			} else {				struct list_head *p = data->box->items;				if (p->next == item) {					str[1] = BORDER_SULCORNER;				} else if (p->prev == item) {					str[1] = BORDER_SDLCORNER;				}			}			break;		}		case BI_FOLDER:			str[0] = '[';			str[1] = (item->expanded) ? '-' : '+';			str[2] = ']';			break;		default:			INTERNAL("Unknown item type");			break;		}		if (item->marked) str[4] = '*';		x = data->widget_data->box.x + (depth - 1) * 5;		for (i = 0; i < 5; i++) {			draw_border_char(data->term, x + i, y, str[i], color);		}	}	x = data->widget_data->box.x + depth * 5;	if (item->type == BI_SEPARATOR) {		int i;		int width = data->widget_data->box.width - depth * 5;		for (i = 0; i < width; i++) {			draw_border_char(data->term, x + i, y, BORDER_SHLINE, color);		}	} else if (data->box->ops && data->box->ops->draw) {		int width = data->widget_data->box.width - depth * 5;		data->box->ops->draw(item, data, x, y, width);	} else {		unsigned char *text;		struct listbox_ops *ops = data->box->ops;		assert(ops && ops->get_info);		text = ops->get_text(item, data->term);		if (!text) return 0;		len = strlen(text);		int_upper_bound(&len, int_max(0, data->widget_data->box.width - depth * 5));		draw_text(data->term, x, y, text, len, 0, color);		mem_free(text);	}	if (item == data->box->sel) {		x = data->widget_data->box.x;		/* For blind users: */		set_cursor(data->term, x, y, 1);		set_window_ptr(data->dlg_data->win, x, y);	}	data->offset++;	return 0;}/* Displays a dialog box */static t_handler_event_statusdisplay_listbox(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct terminal *term = dlg_data->win->term;	struct listbox_data *box = get_listbox_widget_data(widget_data);	struct listbox_context data;	/* Add one to offset to get the actual height of the selected item */	int moves = box->sel_offset + 1 - widget_data->box.height;	if (moves > 0) {		/* Move selected listbox to visible and update box->top while we're		 * at it. Fixes bug 58. */		listbox_sel_move(widget_data, -moves);	} else if (!list_empty(*box->items)) {		if (!box->top) box->top = box->items->next;		if (!box->sel) box->sel = box->top;	}	draw_box(term, &widget_data->box, ' ', 0,		 get_bfu_color(term, "menu.normal"));	/* We want to have these visible if possible. */	if (box->top && !box->top->visible) {		/* DBG("top: %s - (%d) %p\n", box->top->text, box->top->visible, box->top); */		box->top = traverse_listbox_items_list(box->top, box, 1,				1, NULL, NULL);		box->sel = box->top;	}	memset(&data, 0, sizeof(data));	data.term = term;	data.widget_data = widget_data;	data.box = box;	data.dlg_data = dlg_data;	traverse_listbox_items_list(box->top, box, widget_data->box.height,				    1, display_listbox_item, &data);	return EVENT_PROCESSED;}static intcheck_old_state(struct listbox_item *item, void *info_, int *offset){	struct listbox_data *box = info_;	if (box->sel == item)		box->sel = NULL;	else if (box->top == item)		box->top = NULL;	if (!box->sel && !box->top)		*offset = 0;	return 0;}static t_handler_event_statusinit_listbox(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct hierbox_browser *browser = dlg_data->dlg->udata2;	struct listbox_data *box = get_listbox_widget_data(widget_data);	/* Try to restore the position from last time */	if (!list_empty(browser->root.child) && browser->box_data.items) {		copy_struct(box, &browser->box_data);		traverse_listbox_items_list(browser->root.child.next, box, 0, 0,					    check_old_state, box);		box->sel = (!box->sel) ? browser->box_data.sel : NULL;		box->top = (!box->top) ? browser->box_data.top : NULL;		if (!box->sel) box->sel = box->top;		if (!box->top) box->top = box->sel;	}	box->ops = browser->ops;	box->items = &browser->root.child;	add_to_list(browser->boxes, box);	return EVENT_PROCESSED;}static t_handler_event_statusmouse_listbox(struct dialog_data *dlg_data, struct widget_data *widget_data){#ifdef CONFIG_MOUSE	struct listbox_data *box = get_listbox_widget_data(widget_data);	struct term_event *ev = dlg_data->term_event;	if (!list_empty(*box->items)) {		if (!box->top) box->top = box->items->next;		if (!box->sel) box->sel = box->top;	}	if (check_mouse_action(ev, B_DOWN)) {		struct widget_data *dlg_item = dlg_data->widgets_data;		switch (get_mouse_button(ev)) {			case B_WHEEL_DOWN:				listbox_sel_move(dlg_item, 1);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			case B_WHEEL_UP:				listbox_sel_move(dlg_item, -1);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;		}	}	if (check_mouse_wheel(ev))		return EVENT_NOT_PROCESSED;	if (check_mouse_position(ev, &widget_data->box)) {		/* Clicked in the box. */		int offset = ev->info.mouse.y - widget_data->box.y;		box->sel_offset = offset;		box->sel = offset ? traverse_listbox_items_list(box->top, box,								offset, 1,								NULL, NULL)				  : box->top;		if (box->sel && box->sel->type == BI_FOLDER) {			int xdepth = widget_data->box.x + box->sel->depth * 5;			int x = ev->info.mouse.x;			if (x >= xdepth && x <= xdepth + 2)				box->sel->expanded = !box->sel->expanded;		}		display_widget(dlg_data, widget_data);		return EVENT_PROCESSED;	}#endif /* CONFIG_MOUSE */	return EVENT_NOT_PROCESSED;}static t_handler_event_statuskbd_listbox(struct dialog_data *dlg_data, struct widget_data *widget_data){	struct widget_data *dlg_item = dlg_data->widgets_data;	struct term_event *ev = dlg_data->term_event;	/* Not a pure listbox, but you're not supposed to use this outside of	 * the listbox browser anyway, so what.. */	switch (ev->ev) {		enum menu_action action;		case EVENT_KBD:			action = kbd_action(KEYMAP_MENU, ev, NULL);			/* Moving the box */			if (action == ACT_MENU_DOWN) {				listbox_sel_move(dlg_item, 1);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_UP) {				listbox_sel_move(dlg_item, -1);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_PAGE_DOWN) {				listbox_sel_move(dlg_item, dlg_item->box.height / 2);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_PAGE_UP) {				listbox_sel_move(dlg_item, -dlg_item->box.height / 2);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_HOME) {				listbox_sel_move(dlg_item, -INT_MAX);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_END) {				listbox_sel_move(dlg_item, INT_MAX);				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_MARK_ITEM) {				struct listbox_data *box;				box = get_listbox_widget_data(dlg_item);				if (box->sel) {					box->sel->marked = !box->sel->marked;					listbox_sel_move(dlg_item, 1);				}				display_widget(dlg_data, dlg_item);				return EVENT_PROCESSED;			}			if (action == ACT_MENU_DELETE) {				struct listbox_data *box;				box = get_listbox_widget_data(dlg_item);				if (box->ops				    && box->ops->delete				    && box->ops->can_delete)					push_hierbox_delete_button(dlg_data,								   widget_data);				return EVENT_PROCESSED;			}			/* Selecting a button; most probably ;). */			break;		case EVENT_INIT:		case EVENT_RESIZE:		case EVENT_REDRAW:		case EVENT_MOUSE:		case EVENT_ABORT:			break;	}	return EVENT_NOT_PROCESSED;}struct widget_ops listbox_ops = {	display_listbox,	init_listbox,	mouse_listbox,	kbd_listbox,	NULL,	NULL,};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?