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 + -
显示快捷键?