📄 bfu.c
字号:
#include "links.h"struct memory_list *getml(void *p, ...){ struct memory_list *ml; va_list ap; int n = 0; void *q = p; va_start(ap, p); while (q) { if (n == MAXINT) overalloc(); n++, q = va_arg(ap, void *); } if ((unsigned)n > (MAXINT - sizeof(struct memory_list)) / sizeof(void *)) overalloc(); ml = mem_alloc(sizeof(struct memory_list) + n * sizeof(void *)); ml->n = n; n = 0; q = p; va_end(ap); va_start(ap, p); while (q) ml->p[n++] = q, q = va_arg(ap, void *); va_end(ap); return ml;}void add_to_ml(struct memory_list **ml, ...){ struct memory_list *nml; va_list ap; int n = 0; void *q; if (!*ml) { *ml = mem_alloc(sizeof(struct memory_list)); (*ml)->n = 0; } va_start(ap, ml); while ((q = va_arg(ap, void *))) { if (n == MAXINT) overalloc(); n++; } if ((unsigned)n + (unsigned)((*ml)->n) > (MAXINT - sizeof(struct memory_list)) / sizeof(void *)) overalloc(); nml = mem_realloc(*ml, sizeof(struct memory_list) + (n + (*ml)->n) * sizeof(void *)); va_end(ap); va_start(ap, ml); while ((q = va_arg(ap, void *))) nml->p[nml->n++] = q; *ml = nml; va_end(ap);}void freeml(struct memory_list *ml){ int i; if (!ml) return; for (i = 0; i < ml->n; i++) mem_free(ml->p[i]); mem_free(ml);}unsigned char m_bar = 0;void menu_func(struct window *, struct event *, int);void mainmenu_func(struct window *, struct event *, int);void dialog_func(struct window *, struct event *, int);void do_menu_selected(struct terminal *term, struct menu_item *items, void *data, int selected){ struct menu *menu; menu = mem_alloc(sizeof(struct menu)); menu->selected = selected; menu->view = 0; menu->items = items; menu->data = data; add_window(term, menu_func, menu);}void do_menu(struct terminal *term, struct menu_item *items, void *data){ do_menu_selected(term, items, data, 0);}void select_menu(struct terminal *term, struct menu *menu){ /*int x = menu->x + 4; int y = menu->y + menu->selected - menu->view + 2;*/ struct menu_item *it = &menu->items[menu->selected]; void (*func)(struct terminal *, void *, void *) = it->func; void *data1 = it->data; void *data2 = menu->data; if (menu->selected < 0 || menu->selected >= menu->ni || it->hotkey == M_BAR) return; if (!it->in_m) { struct window *win, *win1; for (win = term->windows.next; (void *)win != &term->windows && (win->handler == menu_func || win->handler == mainmenu_func); win1 = win->next, delete_window(win), win = win1) ; } func(term, data1, data2);}void count_menu_size(struct terminal *term, struct menu *menu){ int sx = term->x; int sy = term->y; int mx = 4; int my; for (my = 0; menu->items[my].text; my++) { int s = strlen(_(menu->items[my].text, term)) + strlen(_(menu->items[my].rtext, term)) + MENU_HOTKEY_SPACE * (_(menu->items[my].rtext, term)[0] != 0) + 4; if (s > mx) mx = s; } menu->ni = my; my += 2; if (mx > sx) mx = sx; if (my > sy) my = sy; menu->xw = mx; menu->yw = my; if ((menu->x = menu->xp) < 0) menu->x = 0; if ((menu->y = menu->yp) < 0) menu->y = 0; if (menu->x + mx > sx) menu->x = sx - mx; if (menu->y + my > sy) menu->y = sy - my;}void scroll_menu(struct menu *menu, int d){ int c = 0; int w = menu->yw - 2; int scr_i = SCROLL_ITEMS > (w-1)/2 ? (w-1)/2 : SCROLL_ITEMS; if (scr_i < 0) scr_i = 0; if (w < 0) w = 0; menu->selected += d; while (1) { if (c++ > menu->ni) { menu->selected = -1; menu->view = 0; return; } if (menu->selected < 0) menu->selected = 0; if (menu->selected >= menu->ni) menu->selected = menu->ni - 1; /*if (menu->selected < 0) menu->selected = menu->ni - 1; if (menu->selected >= menu->ni) menu->selected = 0;*/ if (menu->ni && menu->items[menu->selected].hotkey != M_BAR) break; menu->selected += d; } /*debug("1:%d %d %d %d", menu->ni, w, menu->view, menu->selected);*/ if (menu->selected < menu->view + scr_i) menu->view = menu->selected - scr_i; if (menu->selected >= menu->view + w - scr_i - 1) menu->view = menu->selected - w + scr_i + 1; if (menu->view > menu->ni - w) menu->view = menu->ni - w; if (menu->view < 0) menu->view = 0; /*debug("2:%d %d %d %d", menu->ni, w, menu->view, menu->selected);*/}void display_menu(struct terminal *term, struct menu *menu){ int p, s; fill_area(term, menu->x+1, menu->y+1, menu->xw-2, menu->yw-2, COLOR_MENU); draw_frame(term, menu->x, menu->y, menu->xw, menu->yw, COLOR_MENU_FRAME, 1); for (p = menu->view, s = menu->y + 1; p < menu->ni && p < menu->view + menu->yw - 2; p++, s++) { int x; int h = 0; unsigned char c; unsigned char *tmptext = _(menu->items[p].text, term); int co = p == menu->selected ? h = 1, COLOR_MENU_SELECTED : COLOR_MENU; if (h) { set_cursor(term, menu->x+1, s, term->x - 1, term->y - 1); /*set_window_ptr(menu->win, menu->x+3, s+1);*/ set_window_ptr(menu->win, menu->x+menu->xw, s); fill_area(term, menu->x+1, s, menu->xw-2, 1, co); } if (menu->items[p].hotkey != M_BAR || (tmptext && tmptext[0])) { int l = strlen(_(menu->items[p].rtext, term)); for (x = l - 1; x >= 0 && menu->xw - 4 >= l - x && (c = _(menu->items[p].rtext, term)[x]); x--) set_char(term, menu->x + menu->xw - 2 - l + x, s, c | co); for (x = 0; x < menu->xw - 4 && (c = tmptext[x]); x++) set_char(term, menu->x + x + 2, s, !h && strchr(_(menu->items[p].hotkey, term), upcase(c)) ? h = 1, COLOR_MENU_HOTKEY | c : co | c); } else { set_char(term, menu->x, s, COLOR_MENU_FRAME | ATTR_FRAME | 0xc3); fill_area(term, menu->x+1, s, menu->xw-2, 1, COLOR_MENU_FRAME | ATTR_FRAME | 0xc4); set_char(term, menu->x+menu->xw-1, s, COLOR_MENU_FRAME | ATTR_FRAME | 0xb4); } } redraw_from_window(menu->win);}void menu_func(struct window *win, struct event *ev, int fwd){ int s = 0; struct menu *menu = win->data; struct window *w1; menu->win = win; switch (ev->ev) { case EV_INIT: case EV_RESIZE: case EV_REDRAW: get_parent_ptr(win, &menu->xp, &menu->yp); count_menu_size(win->term, menu); menu->selected--; scroll_menu(menu, 1); /*case EV_REDRAW:*/ display_menu(win->term, menu); break; case EV_MOUSE: if (ev->x < menu->x || ev->x >= menu->x+menu->xw || ev->y < menu->y || ev->y >= menu->y+menu->yw) { if ((ev->b & BM_ACT) == B_DOWN) del:delete_window_ev(win, ev); else for (w1 = win; (void *)w1 != &win->term->windows; w1 = w1->next) { struct menu *m1; if (w1->handler == mainmenu_func) { if (!ev->y) goto del; break; } if (w1->handler != menu_func) break; m1 = w1->data; if (ev->x > m1->x && ev->x < m1->x+m1->xw-1 && ev->y > m1->y && ev->y < m1->y+m1->yw-1) goto del; } } else { if (!(ev->x < menu->x || ev->x >= menu->x+menu->xw || ev->y < menu->y+1 || ev->y >= menu->y+menu->yw-1)) { int s = ev->y - menu->y-1 + menu->view; if (s >= 0 && s < menu->ni && menu->items[s].hotkey != M_BAR) { menu->selected = s; scroll_menu(menu, 0); display_menu(win->term, menu); if ((ev->b & BM_ACT) == B_UP/* || menu->items[s].in_m*/) select_menu(win->term, menu); } } } break; case EV_KBD: switch (kbd_action(KM_MENU, ev)) { case ACT_LEFT: case ACT_RIGHT: if ((void *)win->next != &win->term->windows && win->next->handler == mainmenu_func) goto mm; /*for (w1 = win; (void *)w1 != &win->term->windows; w1 = w1->next) { if (w1->handler == mainmenu_func) goto mm; if (w1->handler != menu_func) break; }*/ if (kbd_action(KM_MENU, ev) == ACT_RIGHT) goto enter; delete_window(win); goto break2; case ACT_UP: scroll_menu(menu, -1); break; case ACT_DOWN: scroll_menu(menu, 1); break; case ACT_HOME: menu->selected = -1, scroll_menu(menu, 1); break; case ACT_END: menu->selected = menu->ni, scroll_menu(menu, -1); break; case ACT_PAGE_UP: if ((menu->selected -= menu->yw - 3) < -1) menu->selected = -1; if ((menu->view -= menu->yw - 2) < 0) menu->view = 0; scroll_menu(menu, -1); break; case ACT_PAGE_DOWN: if ((menu->selected += menu->yw - 3) > menu->ni) menu->selected = menu->ni; if ((menu->view += menu->yw - 2) >= menu->ni - menu->yw + 2) menu->view = menu->ni - menu->yw + 2; scroll_menu(menu, 1); break; default: if ((ev->x >= KBD_F1 && ev->x <= KBD_F12) || ev->y == KBD_ALT) { mm: delete_window_ev(win, ev); goto break2; } if (ev->x == KBD_ESC) { delete_window_ev(win, (void *)win->next != &win->term->windows && win->next->handler == mainmenu_func ? ev : NULL); goto break2; } if (ev->x > ' ' && ev->x < 256) { int i; for (i = 0; i < menu->ni; i++) if (strchr(_(menu->items[i].hotkey, win->term), upcase(ev->x))) { menu->selected = i; scroll_menu(menu, 0); s = 1; } } break; } display_menu(win->term, menu); if (s || ev->x == KBD_ENTER || ev->x == ' ') { enter: select_menu(win->term, menu); } break2: break; case EV_ABORT: if (menu->items->free_i) { int i; for (i = 0; menu->items[i].text; i++) { if (menu->items[i].free_i & 2) mem_free(menu->items[i].text); if (menu->items[i].free_i & 4) mem_free(menu->items[i].rtext); } mem_free(menu->items); } break; }}void do_mainmenu(struct terminal *term, struct menu_item *items, void *data, int sel){ struct mainmenu *menu; menu = mem_alloc(sizeof(struct mainmenu)); menu->selected = sel == -1 ? 0 : sel; menu->items = items; menu->data = data; add_window(term, mainmenu_func, menu); if (sel != -1) { struct event ev = {EV_KBD, KBD_ENTER, 0, 0}; struct window *win = term->windows.next; win->handler(win, &ev, 0); }}void display_mainmenu(struct terminal *term, struct mainmenu *menu){ int i; int p = 2; fill_area(term, 0, 0, term->x, 1, COLOR_MAINMENU | ' '); for (i = 0; menu->items[i].text; i++) { int s = 0; int j; unsigned char c; unsigned char *tmptext = _(menu->items[i].text, term); int co = i == menu->selected ? s = 1, COLOR_MAINMENU_SELECTED : COLOR_MAINMENU; if (s) { fill_area(term, p, 0, 2, 1, co); fill_area(term, p+strlen(tmptext)+2, 0, 2, 1, co); menu->sp = p; set_cursor(term, p, 0, term->x - 1, term->y - 1); set_window_ptr(menu->win, p, 1); } p += 2; for (j = 0; (c = tmptext[j]); j++, p++) set_char(term, p, 0, (!s && strchr(_(menu->items[i].hotkey, term), upcase(c)) ? s = 1, COLOR_MAINMENU_HOTKEY : co) | c); p += 2; } menu->ni = i; redraw_from_window(menu->win);}void select_mainmenu(struct terminal *term, struct mainmenu *menu){ struct menu_item *it = &menu->items[menu->selected]; if (menu->selected < 0 || menu->selected >= menu->ni || it->hotkey == M_BAR) return; if (!it->in_m) { struct window *win, *win1; for (win = term->windows.next; (void *)win != &term->windows && (win->handler == menu_func || win->handler == mainmenu_func); win1 = win->next, delete_window(win), win = win1) ; } it->func(term, it->data, menu->data);}void mainmenu_func(struct window *win, struct event *ev, int fwd){ int s = 0; struct mainmenu *menu = win->data; menu->win = win; switch(ev->ev) { case EV_INIT: case EV_RESIZE: case EV_REDRAW: display_mainmenu(win->term, menu); break; case EV_MOUSE: if ((ev->b & BM_ACT) == B_DOWN && ev->y) delete_window_ev(win, ev); else if (!ev->y) { int i; int p = 2; for (i = 0; i < menu->ni; i++) { int o = p; unsigned char *tmptext = _(menu->items[i].text, win->term); p += strlen(tmptext) + 4; if (ev->x >= o && ev->x < p) { menu->selected = i; display_mainmenu(win->term, menu); if ((ev->b & BM_ACT) == B_UP || menu->items[s].in_m) select_mainmenu(win->term, menu); break; } } } break; case EV_KBD: if (ev->x == ' ' || ev->x == KBD_ENTER || ev->x == KBD_DOWN || ev->x == KBD_UP || ev->x == KBD_PAGE_DOWN || ev->x == KBD_PAGE_UP) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -