📄 terminal.c
字号:
win->data = data; win->term = term; win->xp = win->yp = 0; add_at_pos(at, win); win->handler(win, &ev, 0);}void add_window(struct terminal *term, void (*handler)(struct window *, struct event *, int), void *data){ add_window_at_pos(term, handler, data, (struct window *)(void *)&term->windows);}void delete_window(struct window *win){ struct event ev = {EV_ABORT, 0, 0, 0}; win->handler(win, &ev, 1); del_from_list(win); if (win->data) mem_free(win->data); if (!F) redraw_terminal(win->term);#ifdef G else { struct window *w; for (w = win->next; w != (void *)&win->term->windows; w = w->next) unite_rect(&w->redr, &win->pos, &w->redr); register_bottom_half((void (*)(void *))redraw_windows, win->term); }#endif mem_free(win);}void delete_window_ev(struct window *win, struct event *ev){ struct window *w = win->next; if ((void *)w == &win->term->windows) w = NULL; delete_window(win); if (ev && w && w->next != w) w->handler(w, ev, 1);}void set_window_ptr(struct window *win, int x, int y){ if (win->xp == x && win->yp == y) return; win->xp = x; win->yp = y;#ifdef G if (F && win->prev != (void *)&win->term->windows) { memcpy(&win->prev->redr, &win->term->dev->size, sizeof(struct rect)); register_bottom_half((void (*)(void *))redraw_windows, win->term); }#endif}void get_parent_ptr(struct window *win, int *x, int *y){ if ((void *)win->next != &win->term->windows) { *x = win->next->xp; *y = win->next->yp; } else { *x = *y = 0; }}struct ewd { void (*fn)(void *); void *data; int b;};void empty_window_handler(struct window *win, struct event *ev, int fwd){ struct window *n; struct ewd *ewd = win->data; int x, y; void (*fn)(void *) = ewd->fn; void *data = ewd->data; if (ewd->b) return; switch ((int)ev->ev) { case EV_INIT: case EV_RESIZE: case EV_REDRAW: get_parent_ptr(win, &x, &y); set_window_ptr(win, x, y); return; case EV_ABORT: fn(data); return; } ewd->b = 1; n = win->next; delete_window(win); fn(data); if (n->next != n) n->handler(n, ev, fwd);}void add_empty_window(struct terminal *term, void (*fn)(void *), void *data){ struct ewd *ewd; ewd = mem_alloc(sizeof(struct ewd)); ewd->fn = fn; ewd->data = data; ewd->b = 0; add_window(term, empty_window_handler, ewd);}void free_term_specs(void){ free_list(term_specs);}struct list_head term_specs = {&term_specs, &term_specs};struct term_spec dumb_term = { NULL, NULL, "", 0, 1, 0, 0, 0, 0, 0 };struct term_spec *get_term_spec(unsigned char *term){ struct term_spec *t; NO_GFX; foreach(t, term_specs) if (!strcasecmp(t->term, term)) return t; return &dumb_term;}struct term_spec *new_term_spec(unsigned char *term){ struct term_spec *t; foreach(t, term_specs) if (!strcasecmp(t->term, term)) return t; t = mem_alloc(sizeof(struct term_spec)); memcpy(t, &dumb_term, sizeof(struct term_spec)); if (strlen(term) < MAX_TERM_LEN) strcpy(t->term, term); else memcpy(t->term, term, MAX_TERM_LEN - 1), t->term[MAX_TERM_LEN - 1] = 0; add_to_list(term_specs, t); sync_term_specs(); return t;}void sync_term_specs(void){ struct terminal *term; foreach(term, terminals) term->spec = get_term_spec(term->term);}struct terminal *init_term(int fdin, int fdout, void (*root_window)(struct window *, struct event *, int)){ static tcount terminal_count = 0; struct terminal *term; struct window *win; NO_GFX; term = mem_calloc(sizeof (struct terminal)); term->count = terminal_count++; term->fdin = fdin; term->fdout = fdout; term->master = term->fdout == get_output_handle(); term->lcx = -1; term->lcy = -1; term->dirty = 1; term->blocked = -1; term->screen = DUMMY; term->last_screen = DUMMY; term->spec = &dumb_term; term->input_queue = DUMMY; init_list(term->windows); win = mem_calloc(sizeof(struct window)); win->handler = root_window; win->term = term; add_to_list(term->windows, win); /*alloc_term_screen(term, 80, 25);*/ add_to_list(terminals, term); set_handlers(fdin, (void (*)(void *))in_term, NULL, (void (*)(void *))destroy_terminal, term); return term;}#ifdef Gstruct term_spec gfx_term = { NULL, NULL, "", 0, 0, 0, 0, 0, 0, 0 };struct terminal *init_gfx_term(void (*root_window)(struct window *, struct event *, int), void *info, int len){ static tcount terminal_count = 0; struct terminal *term; struct graphics_device *dev; struct window *win; unsigned char *cwd; NO_TXT; term = mem_calloc(sizeof (struct terminal)); term->count = terminal_count++; term->fdin = -1; if (!(term->dev = dev = drv->init_device())) { mem_free(term); check_if_no_terminal(); return NULL; } dev->user_data = term; term->master = 1; term->blocked = -1; term->x = dev->size.x2; term->y = dev->size.y2; term->environment = !(drv->flags & GD_ONLY_1_WINDOW) ? ENV_G : 0; if (!strcasecmp(drv->name, "x")) term->environment |= ENV_XWIN; term->spec = &gfx_term; if ((cwd = get_cwd())) { safe_strncpy(term->cwd, cwd, MAX_CWD_LEN); mem_free(cwd); } gfx_term.charset = get_cp_index("utf-8"); if (gfx_term.charset == -1) gfx_term.charset = 0; init_list(term->windows); win = mem_calloc(sizeof (struct window)); win->handler = root_window; win->term = term; win->pos.x2 = dev->size.x2; win->pos.y2 = dev->size.y2; add_to_list(term->windows, win); add_to_list(terminals, term); dev->redraw_handler = t_redraw; dev->resize_handler = t_resize; dev->keyboard_handler = t_kbd; dev->mouse_handler = t_mouse; { int *ptr; struct event ev = { EV_INIT, 0, 0, 0 }; ev.x = dev->size.x2; ev.y = dev->size.y2; if ((unsigned)len > MAXINT - sizeof(int)) overalloc(); ptr = mem_alloc(sizeof(int) + len); *ptr = len; memcpy(ptr + 1, info, len); ev.b = (long)ptr; root_window(win, &ev, 0); mem_free(ptr); } return term;}void t_redraw(struct graphics_device *dev, struct rect *r){ struct terminal *term = dev->user_data; struct window *win; /*debug("%d %d %d %d", r->x1, r->x2, r->y1, r->y2);*/ /*fprintf(stderr, "t_redraw: %d,%d %d,%d\n", r->x1, r->y1, r->x2, r->y2);*/ foreach(win, term->windows) unite_rect(&win->redr, r, &win->redr); register_bottom_half((void (*)(void *))redraw_windows, term);}void t_resize(struct graphics_device *dev){ struct terminal *term = dev->user_data; struct window *win; struct event ev = {EV_RESIZE, 0, 0, 0}; term->x = ev.x = dev->size.x2; term->y = ev.y = dev->size.y2; drv->set_clip_area(dev, &dev->size); foreach(win, term->windows) { win->handler(win, &ev, 0); } drv->set_clip_area(dev, &dev->size);}void t_kbd(struct graphics_device *dev, int key, int flags){ struct terminal *term = dev->user_data; struct event ev = {EV_KBD, 0, 0, 0}; struct rect r = {0, 0, 0, 0}; r.x2 = dev->size.x2, r.y2 = dev->size.y2; ev.x = key; ev.y = flags; if (upcase(key) == 'L' && flags == KBD_CTRL) { t_redraw(dev, &r); return; } else { drv->set_clip_area(dev, &r); if (list_empty(term->windows)) return; if (ev.x == KBD_CTRL_C || ev.x == KBD_CLOSE) ((struct window *)(void *)&term->windows)->prev->handler(term->windows.prev, &ev, 0); else ((struct window *)(void *)&term->windows)->next->handler(term->windows.next, &ev, 0); }}void t_mouse(struct graphics_device *dev, int x, int y, int b){ struct terminal *term = dev->user_data; struct event ev = {EV_MOUSE, 0, 0, 0}; struct rect r = {0, 0, 0, 0}; r.x2 = dev->size.x2, r.y2 = dev->size.y2; ev.x = x, ev.y = y, ev.b = b; drv->set_clip_area(dev, &r); if (list_empty(term->windows)) return; ((struct window *)(void *)&term->windows)->next->handler(term->windows.next, &ev, 0);}#endifvoid in_term(struct terminal *term){ struct event *ev; int r; unsigned char *iq; NO_GFX; if ((unsigned)term->qlen + ALLOC_GR > MAXINT) overalloc(); iq = mem_realloc(term->input_queue, term->qlen + ALLOC_GR); term->input_queue = iq; if ((r = read(term->fdin, iq + term->qlen, ALLOC_GR)) <= 0) { if (r == -1 && errno != ECONNRESET) error("ERROR: error %d on terminal: could not read event", errno); destroy_terminal(term); return; } term->qlen += r; test_queue: if ((size_t)term->qlen < sizeof(struct event)) return; ev = (struct event *)iq; r = sizeof(struct event); if (ev->ev != EV_INIT && ev->ev != EV_RESIZE && ev->ev != EV_REDRAW && ev->ev != EV_KBD && ev->ev != EV_MOUSE && ev->ev != EV_ABORT) { error("ERROR: error on terminal: bad event %d", ev->ev); goto mm; } if (ev->ev == EV_INIT) { int init_len; if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int)) return; init_len = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len) return; memcpy(term->term, iq + sizeof(struct event), MAX_TERM_LEN); term->term[MAX_TERM_LEN - 1] = 0; memcpy(term->cwd, iq + sizeof(struct event) + MAX_TERM_LEN, MAX_CWD_LEN); term->cwd[MAX_CWD_LEN - 1] = 0; term->environment = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN); ev->b = (long)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); r = sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len; sync_term_specs(); } if (ev->ev == EV_REDRAW || ev->ev == EV_RESIZE || ev->ev == EV_INIT) { struct window *win; send_redraw: if (ev->x < 0 || ev->y < 0) { error("ERROR: bad terminal size: %d, %d", (int)ev->x, (int)ev->y); goto mm; } alloc_term_screen(term, ev->x, ev->y); clear_terminal(term); erase_screen(term); term->redrawing = 1; foreachback(win, term->windows) win->handler(win, ev, 0); term->redrawing = 0; } if (ev->ev == EV_KBD || ev->ev == EV_MOUSE) { if (ev->ev == EV_KBD && upcase(ev->x) == 'L' && ev->y & KBD_CTRL) { ev->ev = EV_REDRAW; ev->x = term->x; ev->y = term->y; goto send_redraw; } else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)(void *)&term->windows)->prev->handler(term->windows.prev, ev, 0); else ((struct window *)(void *)&term->windows)->next->handler(term->windows.next, ev, 0); } if (ev->ev == EV_ABORT) { destroy_terminal(term); return; } /*redraw_screen(term);*/ mm: if (term->qlen == r) term->qlen = 0; else memmove(iq, iq + r, term->qlen -= r); goto test_queue;}static inline int getcompcode(int c){ return (c<<1 | (c&4)>>2) & 7;}unsigned char frame_dumb[48] = " ||||++||++++++--|-+||++--|-+----++++++++ ";unsigned char frame_vt100[48] = "aaaxuuukkuxkjjjkmvwtqnttmlvwtqnvvwwmmllnnjla ";unsigned char frame_koi[48] = { 144,145,146,129,135,178,180,167, 166,181,161,168,174,173,172,131, 132,137,136,134,128,138,175,176, 171,165,187,184,177,160,190,185, 186,182,183,170,169,162,164,189, 188,133,130,141,140,142,143,139,};unsigned char frame_freebsd[48] = { 130,138,128,153,150,150,150,140, 140,150,153,140,139,139,139,140, 142,151,152,149,146,143,149,149, 142,141,151,152,149,146,143,151, 151,152,152,142,142,141,141,143, 143,139,141,128,128,128,128,128,};unsigned char frame_restrict[48] = { 0, 0, 0, 0, 0, 179, 186, 186, 205, 0, 0, 0, 0, 186, 205, 0, 0, 0, 0, 0, 0, 0, 179, 186, 0, 0, 0, 0, 0, 0, 0, 205, 196, 205, 196, 186, 205, 205, 186, 186, 179, 0, 0, 0, 0, 0, 0, 0,};#define PRINT_CHAR(p) \{ \ unsigned ch = term->screen[p]; \ unsigned char c = ch & 0xff; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -