⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menu.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 2 页
字号:
			scroll_menu(menu, 0, 1);			display_menu(win->term, menu);			select_menu(win->term, menu);		}	}}#endif#define DIST 5static voidmenu_page_up(struct menu *menu){	int current = int_max(0, int_min(menu->selected, menu->size - 1));	int step;	int i;	int next_sep = 0;	for (i = current - 1; i > 0; i--)		if (mi_is_horizontal_bar(&menu->items[i])) {			next_sep = i;			break;		}	step = current - next_sep + 1;	int_bounds(&step, 0, int_min(current, DIST));	scroll_menu(menu, -step, 0);}static voidmenu_page_down(struct menu *menu){	int current = int_max(0, int_min(menu->selected, menu->size - 1));	int step;	int i;	int next_sep = menu->size - 1;	for (i = current + 1; i < menu->size; i++)		if (mi_is_horizontal_bar(&menu->items[i])) {			next_sep = i;			break;		}	step = next_sep - current + 1;	int_bounds(&step, 0, int_min(menu->size - 1 - current, DIST));	scroll_menu(menu, step, 0);}#undef DISTstatic inline intsearch_menu_item(struct menu_item *item, unsigned char *buffer,		 struct terminal *term){	unsigned char *text, *match;	if (!mi_has_left_text(item)) return 0;	text = mi_text_translate(item) ? _(item->text, term) : item->text;	/* Crap. We have to remove the hotkey markers '~' */	text = stracpy(text);	if (!text) return 0;	match = strchr(text, '~');	if (match)		memmove(match, match + 1, strlen(match));	match = strcasestr(text, buffer);	mem_free(text);	return !!match;}static enum input_line_codemenu_search_handler(struct input_line *line, int action){	struct menu *menu = line->data;	struct terminal *term = menu->win->term;	unsigned char *buffer = line->buffer;	struct window *win;	int pos = menu->selected;	int direction;	switch (action) {	case ACT_EDIT_REDRAW:		return INPUT_LINE_PROCEED;	case ACT_EDIT_ENTER:		/* XXX: The input line dialog window is above the menu window.		 * Remove it from the top, so that select_menu() will correctly		 * remove all the windows it has to and then readd it. */		win = term->windows.next;		del_from_list(win);		select_menu(term, menu);		add_to_list(term->windows, win);		return INPUT_LINE_CANCEL;	case ACT_EDIT_PREVIOUS_ITEM:		pos--;		direction = -1;		break;	case ACT_EDIT_NEXT_ITEM:		pos++;	default:		direction = 1;	}	/* If there is nothing to match with don't start searching */	if (!*buffer) return INPUT_LINE_PROCEED;	pos %= menu->size;	do {		struct menu_item *item = &menu->items[pos];		if (search_menu_item(item, buffer, term)) {			scroll_menu(menu, pos - menu->selected, 0);			display_menu(term, menu);			return INPUT_LINE_PROCEED;		}		pos += direction;		if (pos == menu->size) pos = 0;		else if (pos < 0) pos = menu->size - 1;	} while (pos != menu->selected);	return INPUT_LINE_CANCEL;}static voidsearch_menu(struct menu *menu){	struct terminal *term = menu->win->term;	struct window *tab = get_current_tab(term);	struct session *ses = tab ? tab->data : NULL;	unsigned char *prompt = _("Search menu/", term);	if (menu->size < 1 || !ses) return;	input_field_line(ses, prompt, menu, NULL, menu_search_handler);}static voidmenu_kbd_handler(struct menu *menu, struct term_event *ev){	struct window *win = menu->win;	enum menu_action action = kbd_action(KEYMAP_MENU, ev, NULL);	int s = 0;	switch (action) {		case ACT_MENU_LEFT:		case ACT_MENU_RIGHT:			if (list_has_next(win->term->windows, win)			    && win->next->handler == mainmenu_handler) {				struct window *next_win = win->next;				delete_window_ev(win, ev);				select_menu(next_win->term, next_win->data);				return;			}			if (action == ACT_MENU_RIGHT)				goto enter;			delete_window(win);			return;		case ACT_MENU_UP:			scroll_menu(menu, -1, 1);			break;		case ACT_MENU_DOWN:			scroll_menu(menu, 1, 1);			break;		case ACT_MENU_HOME:			scroll_menu(menu, -menu->selected, 0);			break;		case ACT_MENU_END:			scroll_menu(menu, menu->size - menu->selected - 1, 0);			break;		case ACT_MENU_PAGE_UP:			menu_page_up(menu);			break;		case ACT_MENU_PAGE_DOWN:			menu_page_down(menu);			break;		case ACT_MENU_ENTER:		case ACT_MENU_SELECT:			goto enter;		case ACT_MENU_SEARCH:			search_menu(menu);			break;		case ACT_MENU_CANCEL:			if (list_has_next(win->term->windows, win)			    && win->next->handler == mainmenu_handler)				delete_window_ev(win, ev);			else				delete_window_ev(win, NULL);			return;		default:		{			int key = get_kbd_key(ev);			if ((key >= KBD_F1 && key <= KBD_F12)			    || check_kbd_modifier(ev, KBD_ALT)) {				delete_window_ev(win, ev);				return;			}			if (!check_kbd_label_key(ev))				break;			s = check_hotkeys(menu, key, win->term);			if (s || check_not_so_hot_keys(menu, key, win->term))				scroll_menu(menu, 0, 1);		}	}	display_menu(win->term, menu);	if (s) {enter:		select_menu(win->term, menu);	}}static voidmenu_handler(struct window *win, struct term_event *ev){	struct menu *menu = win->data;	menu->win = win;	switch (ev->ev) {		case EVENT_INIT:		case EVENT_RESIZE:		case EVENT_REDRAW:			get_parent_ptr(win, &menu->parent_x, &menu->parent_y);			count_menu_size(win->term, menu);			menu->selected--;			scroll_menu(menu, 1, 1);			display_menu(win->term, menu);			break;		case EVENT_MOUSE:#ifdef CONFIG_MOUSE			menu_mouse_handler(menu, ev);#endif /* CONFIG_MOUSE */			break;		case EVENT_KBD:			menu_kbd_handler(menu, ev);			break;		case EVENT_ABORT:			if (menu->items->flags & FREE_ANY)				free_menu_items(menu->items);			break;	}}voiddo_mainmenu(struct terminal *term, struct menu_item *items,	    void *data, int sel){	struct menu *menu = mem_calloc(1, sizeof(*menu));	if (!menu) return;	menu->selected = (sel == -1 ? 0 : sel);	menu->items = items;	menu->data = data;	menu->size = count_items(items);	menu->hotkeys = 1;#ifdef ENABLE_NLS	clear_hotkeys_cache(menu);#endif	init_hotkeys(term, menu);	add_window(term, mainmenu_handler, menu);	if (sel != -1) {		select_menu(term, menu);	}}static voiddisplay_mainmenu(struct terminal *term, struct menu *menu){	struct color_pair *normal_color = get_bfu_color(term, "menu.normal");	struct color_pair *selected_color = get_bfu_color(term, "menu.selected");	int p = 0;	int i;	struct box box;	/* FIXME: menu horizontal scrolling do not work well yet, we need to cache	 * menu items width and recalculate them only when needed (ie. language change)	 * instead of looping and calculate them each time. --Zas */	/* Try to make current selected menu entry visible. */	if (menu->selected < menu->first) {		int num_items_offscreen = menu->selected - menu->first;		menu->first += num_items_offscreen;		menu->last += num_items_offscreen;	} else if (menu->selected > menu->last) {		int num_items_offscreen = menu->last - menu->selected;		menu->first -= num_items_offscreen;		menu->last -= num_items_offscreen;	}	if (menu->last <= 0)		menu->last = menu->size - 1;	int_bounds(&menu->last, 0, menu->size - 1);	int_bounds(&menu->first, 0, menu->last);	set_box(&box, 0, 0, term->width, 1);	draw_box(term, &box, ' ', 0, normal_color);	if (menu->first != 0) {		box.width = L_MAINMENU_SPACE;		draw_box(term, &box, '<', 0, normal_color);	}	p += L_MAINMENU_SPACE;	for (i = menu->first; i < menu->size; i++) {		struct menu_item *mi = &menu->items[i];		struct color_pair *color = normal_color;		unsigned char *text = mi->text;		int l = mi->hotkey_pos;		int textlen;		int selected = (i == menu->selected);		if (mi_text_translate(mi))			text = _(text, term);		textlen = strlen(text) - !!l;		if (selected) {			color = selected_color;			box.x = p;			box.width = L_MAINTEXT_SPACE + L_TEXT_SPACE				    + textlen				    + R_TEXT_SPACE + R_MAINTEXT_SPACE;			draw_box(term, &box, ' ', 0, color);			set_cursor(term, p, 0, 1);			set_window_ptr(menu->win, p, 1);		}		p += L_MAINTEXT_SPACE;		if (l) {			draw_menu_left_text_hk(term, text, l,					       p, 0, textlen + R_TEXT_SPACE + L_TEXT_SPACE,					       color, selected);		} else {			draw_menu_left_text(term, text, textlen,					    p, 0, textlen + R_TEXT_SPACE + L_TEXT_SPACE,					    color);		}		p += textlen;		if (p >= term->width - R_MAINMENU_SPACE)			break;		p += R_MAINTEXT_SPACE + R_TEXT_SPACE + L_TEXT_SPACE;	}	menu->last = i - 1;	int_lower_bound(&menu->last, menu->first);	if (menu->last < menu->size - 1) {		set_box(&box,			term->width - R_MAINMENU_SPACE, 0,			R_MAINMENU_SPACE, 1);		draw_box(term, &box, '>', 0, normal_color);	}	redraw_from_window(menu->win);}#ifdef CONFIG_MOUSEstatic voidmainmenu_mouse_handler(struct menu *menu, struct term_event *ev){	struct window *win = menu->win;	struct menu_item *item;	int scroll = 0;	if (check_mouse_wheel(ev))		return;	/* Mouse was clicked outside the mainmenu bar */	if (ev->info.mouse.y) {		if (check_mouse_action(ev, B_DOWN))			delete_window_ev(win, NULL);		return;	}	/* First check if the mouse button was pressed in the side of the	 * terminal and simply scroll one step in that direction else iterate	 * through the menu items to see if it was pressed on a label. */	if (ev->info.mouse.x < L_MAINMENU_SPACE) {		scroll = -1;	} else if (ev->info.mouse.x >= win->term->width - R_MAINMENU_SPACE) {		scroll = 1;	} else {		int p = L_MAINMENU_SPACE;		/* We don't initialize to menu->first here, since it breaks		 * horizontal scrolling using mouse in some cases. --Zas */		foreach_menu_item (item, menu->items) {			unsigned char *text = item->text;			if (!mi_has_left_text(item)) continue;			if (mi_text_translate(item))				text = _(item->text, win->term);			/* The label width is made up of a little padding on			 * the sides followed by the text width substracting			 * one char if it has hotkeys (the '~' char) */			p += L_MAINTEXT_SPACE + L_TEXT_SPACE			  + strlen(text) - !!item->hotkey_pos			  + R_TEXT_SPACE + R_MAINTEXT_SPACE;			if (ev->info.mouse.x < p) {				scroll = (item - menu->items) - menu->selected;				break;			}		}	}	if (scroll) {		scroll_menu(menu, scroll, 1);		display_mainmenu(win->term, menu);	}	/* We need to select the menu item even if we didn't scroll	 * apparently because we will delete any drop down menus	 * in the clicking process. */	select_menu(win->term, menu);}#endifstatic voidmainmenu_kbd_handler(struct menu *menu, struct term_event *ev){	struct window *win = menu->win;	enum menu_action action = kbd_action(KEYMAP_MENU, ev, NULL);	switch (action) {	case ACT_MENU_ENTER:	case ACT_MENU_DOWN:	case ACT_MENU_UP:	case ACT_MENU_PAGE_UP:	case ACT_MENU_PAGE_DOWN:	case ACT_MENU_SELECT:		select_menu(win->term, menu);		return;	case ACT_MENU_HOME:		scroll_menu(menu, -menu->selected, 0);		break;	case ACT_MENU_END:		scroll_menu(menu, menu->size - menu->selected - 1, 0);		break;	case ACT_MENU_NEXT_ITEM:	case ACT_MENU_PREVIOUS_ITEM:		/* This is pretty western centric since `what is next'?		 * Anyway we cycle clockwise by resetting the action ... */		action = (action == ACT_MENU_NEXT_ITEM)		       ? ACT_MENU_RIGHT : ACT_MENU_LEFT;		/* ... and then letting left/right handling take over. */	case ACT_MENU_LEFT:	case ACT_MENU_RIGHT:		scroll_menu(menu, action == ACT_MENU_LEFT ? -1 : 1, 1);		break;	case ACT_MENU_REDRAW:		/* Just call display_mainmenu() */		break;	default:		/* Fallback to see if any hotkey matches the pressed key */		if (check_kbd_label_key(ev)		    && check_hotkeys(menu, get_kbd_key(ev), win->term)) {			display_mainmenu(win->term, menu);			select_menu(win->term, menu);			return;		}	case ACT_MENU_CANCEL:		delete_window_ev(win, action != ACT_MENU_CANCEL ? ev : NULL);		return;	}	/* Redraw the menu */	display_mainmenu(win->term, menu);}static voidmainmenu_handler(struct window *win, struct term_event *ev){	struct menu *menu = win->data;	menu->win = win;	switch (ev->ev) {		case EVENT_INIT:		case EVENT_RESIZE:		case EVENT_REDRAW:			display_mainmenu(win->term, menu);			break;		case EVENT_MOUSE:#ifdef CONFIG_MOUSE			mainmenu_mouse_handler(menu, ev);#endif /* CONFIG_MOUSE */			break;		case EVENT_KBD:			mainmenu_kbd_handler(menu, ev);			break;		case EVENT_ABORT:			break;	}}/* For dynamic menus the last (cleared) item is used to mark the end. */#define realloc_menu_items(mi_, size) \	mem_align_alloc(mi_, size, (size) + 2, struct menu_item, 0xF)struct menu_item *new_menu(enum menu_item_flags flags){	struct menu_item *mi = NULL;	if (realloc_menu_items(&mi, 0)) mi->flags = flags;	return mi;}voidadd_to_menu(struct menu_item **mi, unsigned char *text, unsigned char *rtext,	    enum main_action action, menu_func func, void *data,	    enum menu_item_flags flags){	int n = count_items(*mi);	/* XXX: Don't clear the last and special item. */	struct menu_item *item = realloc_menu_items(mi, n + 1);	if (!item) return;	item += n;	/* Shift current last item by one place. */	copy_struct(item + 1, item);	/* Setup the new item. All menu items share the item_free value. */	SET_MENU_ITEM(item, text, rtext, action, func, data,		      item->flags | flags, HKS_SHOW, 0);}#undef L_MAINMENU_SPACE#undef R_MAINMENU_SPACE#undef L_MAINTEXT_SPACE#undef R_MAINTEXT_SPACE#undef L_RTEXT_SPACE#undef R_RTEXT_SPACE#undef L_TEXT_SPACE#undef R_TEXT_SPACE#undef MENU_BORDER_SIZE

⌨️ 快捷键说明

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