📄 kbd.c
字号:
#define RD(xx) { \ unsigned char cc; \ \ if (p < bytes_read) \ cc = buf[p++]; \ else if ((hard_read(itrm->sock_in, &cc, 1)) <= 0) \ goto free_and_return; \ xx = cc; \ } RD(fg); if (!init_string(&path)) goto free_and_return; while (1) { RD(ch); if (!ch) break; add_char_to_string(&path, ch); } if (!init_string(&delete)) { done_string(&path); goto free_and_return; } while (1) { RD(ch); if (!ch) break; add_char_to_string(&delete, ch); }#undef RD if (!*path.source) { dispatch_special(delete.source); } else { int blockh; unsigned char *param; int path_len, del_len, param_len; if (is_blocked() && fg) { if (*delete.source) unlink(delete.source); goto nasty_thing; } path_len = path.length; del_len = delete.length; param_len = path_len + del_len + 3; param = mem_alloc(param_len); if (!param) goto nasty_thing; param[0] = fg; memcpy(param + 1, path.source, path_len + 1); memcpy(param + 1 + path_len + 1, delete.source, del_len + 1); if (fg == 1) block_itrm(itrm->ctl_in); blockh = start_thread((void (*)(void *, int)) exec_thread, param, param_len); if (blockh == -1) { if (fg == 1) unblock_itrm(itrm->ctl_in); mem_free(param); goto nasty_thing; } mem_free(param); if (fg == 1) { set_handlers(blockh, (void (*)(void *)) unblock_itrm_x, NULL, (void (*)(void *)) unblock_itrm_x, (void *) (long) blockh); /* block_itrm(itrm->ctl_in); */ } else { set_handlers(blockh, close_handle, NULL, close_handle, (void *) (long) blockh); } }nasty_thing: done_string(&path); done_string(&delete); assert(OUT_BUF_SIZE - p > 0); memmove(buf, buf + p, OUT_BUF_SIZE - p); bytes_read -= p; goto qwerty;free_and_return: free_trm(itrm);}static voidkbd_timeout(struct itrm *itrm){ struct term_event ev = INIT_TERM_EVENT(EVENT_KBD, KBD_ESC, 0, 0); itrm->timer = -1; if (can_read(itrm->std_in)) { in_kbd(itrm); return; } assertm(itrm->qlen, "timeout on empty queue"); if_assert_failed return; queue_event(itrm, (char *) &ev, sizeof(ev)); if (--itrm->qlen) memmove(itrm->kqueue, itrm->kqueue + 1, itrm->qlen); while (process_queue(itrm));}/* Returns the length of the escape sequence */static inline intget_esc_code(unsigned char *str, int len, unsigned char *code, int *num){ int pos; *num = 0; *code = '\0'; for (pos = 2; pos < len; pos++) { if (!isdigit(str[pos]) || pos > 7) { *code = str[pos]; return pos + 1; } *num = *num * 10 + str[pos] - '0'; } return 0;}/* Define it to dump queue content in a readable form, * it may help to determine terminal sequences, and see what goes on. --Zas *//* #define DEBUG_ITRM_QUEUE */#ifdef DEBUG_ITRM_QUEUE#include <ctype.h> /* isprint() isspace() */#endif#ifdef CONFIG_MOUSEstatic intdecode_mouse_position(struct itrm *itrm, int from){ int position; position = (unsigned char) (itrm->kqueue[from]) - ' ' - 1 + ((int) ((unsigned char) (itrm->kqueue[from + 1]) - ' ' - 1) << 7); return (position & (1 << 13)) ? 0 : position;}#define get_mouse_x_position(itrm, esclen) decode_mouse_position(itrm, (esclen) + 1)#define get_mouse_y_position(itrm, esclen) decode_mouse_position(itrm, (esclen) + 3)/* Returns length of the escape sequence or -1 if the caller needs to set up * the ESC delay timer. */static intdecode_terminal_mouse_escape_sequence(struct itrm *itrm, struct term_event *ev, int el, int v){ static int xterm_button = -1; struct term_event_mouse *mouse = &ev->info.mouse; if (itrm->qlen - el < 3) return -1; if (v == 5) { if (xterm_button == -1) xterm_button = 0; if (itrm->qlen - el < 5) return -1; mouse->x = get_mouse_x_position(itrm, el); mouse->y = get_mouse_y_position(itrm, el); switch ((itrm->kqueue[el] - ' ') ^ xterm_button) { /* Every event changes only one bit */ case TW_BUTT_LEFT: mouse->button = B_LEFT | ( (xterm_button & TW_BUTT_LEFT) ? B_UP : B_DOWN ); break; case TW_BUTT_MIDDLE: mouse->button = B_MIDDLE | ( (xterm_button & TW_BUTT_MIDDLE) ? B_UP : B_DOWN ); break; case TW_BUTT_RIGHT: mouse->button = B_RIGHT | ( (xterm_button & TW_BUTT_RIGHT) ? B_UP : B_DOWN ); break; case 0: mouse->button = B_DRAG; /* default : Twin protocol error */ } xterm_button = itrm->kqueue[el] - ' '; el += 5; } else { /* See terminal/mouse.h about details of the mouse reporting * protocol and {struct term_event_mouse->button} bitmask * structure. */ mouse->x = itrm->kqueue[el+1] - ' ' - 1; mouse->y = itrm->kqueue[el+2] - ' ' - 1; /* There are rumours arising from remnants of code dating to * the ancient Mikulas' times that bit 4 indicated B_DRAG. * However, I didn't find on what terminal it should be ever * supposed to work and it conflicts with wheels. So I removed * the last remnants of the code as well. --pasky */ mouse->button = (itrm->kqueue[el] & 7) | B_DOWN; /* smartglasses1 - rxvt wheel: */ if (mouse->button == 3 && xterm_button != -1) { mouse->button = xterm_button | B_UP; } /* xterm wheel: */ if ((itrm->kqueue[el] & 96) == 96) { mouse->button = (itrm->kqueue[el] & 1) ? B_WHEEL_DOWN : B_WHEEL_UP; } xterm_button = -1; /* XXX: Eterm/aterm uses rxvt-like reporting, but sends the * release sequence for wheel. rxvt itself sends only press * sequence. Since we can't reliably guess what we're talking * with from $TERM, we will rather support Eterm/aterm, as in * rxvt, at least each second wheel up move will work. */ if (check_mouse_action(ev, B_DOWN))#if 0 && !(getenv("TERM") && strstr("rxvt", getenv("TERM")) && (ev->b & BM_BUTT) >= B_WHEEL_UP))#endif xterm_button = get_mouse_button(ev); el += 3; } /* Postpone changing of the event type until all sanity * checks have been done. */ ev->ev = EVENT_MOUSE; return el;}#endif /* CONFIG_MOUSE *//* Returns length of the escape sequence or -1 if the caller needs to set up * the ESC delay timer. */static intdecode_terminal_escape_sequence(struct itrm *itrm, struct term_event *ev){ unsigned char c; int key = -1, modifier = 0; int v; int el; if (itrm->qlen < 3) return -1; if (itrm->kqueue[2] == '[') { if (itrm->qlen >= 4 && itrm->kqueue[3] >= 'A' && itrm->kqueue[3] <= 'L') { ev->info.keyboard.key = KBD_F1 + itrm->kqueue[3] - 'A'; return 4; } return -1; } el = get_esc_code(itrm->kqueue, itrm->qlen, &c, &v);#ifdef DEBUG_ITRM_QUEUE fprintf(stderr, "esc code: %c v=%d c=%c el=%d\n", itrm->kqueue[1], v, c, el); fflush(stderr);#endif switch (c) { case 0: return -1; case 'A': key = KBD_UP; break; case 'B': key = KBD_DOWN; break; case 'C': key = KBD_RIGHT; break; case 'D': key = KBD_LEFT; break; case 'F': case 'e': key = KBD_END; break; case 'H': key = KBD_HOME; break; case 'I': key = KBD_PAGE_UP; break; case 'G': key = KBD_PAGE_DOWN; break; case 'z': switch (v) { case 247: key = KBD_INS; break; case 214: key = KBD_HOME; break; case 220: key = KBD_END; break; case 216: key = KBD_PAGE_UP; break; case 222: key = KBD_PAGE_DOWN; break; case 249: key = KBD_DEL; break; } break; case '~': switch (v) { case 1: key = KBD_HOME; break; case 2: key = KBD_INS; break; case 3: key = KBD_DEL; break; case 4: key = KBD_END; break; case 5: key = KBD_PAGE_UP; break; case 6: key = KBD_PAGE_DOWN; break; case 7: key = KBD_HOME; break; case 8: key = KBD_END; break; case 11: key = KBD_F1; break; case 12: key = KBD_F2; break; case 13: key = KBD_F3; break; case 14: key = KBD_F4; break; case 15: key = KBD_F5; break; case 17: key = KBD_F6; break; case 18: key = KBD_F7; break; case 19: key = KBD_F8; break; case 20: key = KBD_F9; break; case 21: key = KBD_F10; break; case 23: key = KBD_F11; break; case 24: key = KBD_F12; break; /* Give preference to F11 and F12 over shifted F1 and F2. */ /* case 23: key = KBD_F1; modifier = KBD_SHIFT; break; case 24: key = KBD_F2; modifier = KBD_SHIFT; break; */ case 25: key = KBD_F3; modifier = KBD_SHIFT; break; case 26: key = KBD_F4; modifier = KBD_SHIFT; break; case 28: key = KBD_F5; modifier = KBD_SHIFT; break; case 29: key = KBD_F6; modifier = KBD_SHIFT; break; case 31: key = KBD_F7; modifier = KBD_SHIFT; break; case 32: key = KBD_F8; modifier = KBD_SHIFT; break; case 33: key = KBD_F9; modifier = KBD_SHIFT; break; case 34: key = KBD_F10; modifier = KBD_SHIFT; break; } break; case 'R': resize_terminal(); break; case 'M':#ifdef CONFIG_MOUSE el = decode_terminal_mouse_escape_sequence(itrm, ev, el, v);#endif /* CONFIG_MOUSE */ break; } /* The event might have been changed to a mouse event */ if (ev->ev == EVENT_KBD && key != -1) { ev->info.keyboard.key = key; ev->info.keyboard.modifier = modifier; } return el;}static voidset_kbd_event(struct term_event *ev, int key, int modifier){ switch (key) { case ASCII_TAB: key = KBD_TAB; break; case ASCII_BS: case ASCII_DEL: key = KBD_BS; break; case ASCII_LF: case ASCII_CR: key = KBD_ENTER; break; default: if (key < ' ') { key += 'A' - 1; modifier = KBD_CTRL; } } ev->info.keyboard.key = key; ev->info.keyboard.modifier = modifier;}/* I feeeeeel the neeeed ... to rewrite this ... --pasky *//* Just Do it ! --Zas */static intprocess_queue(struct itrm *itrm){ struct term_event ev = INIT_TERM_EVENT(EVENT_KBD, -1, 0, 0); int el = 0; if (!itrm->qlen) goto end;#ifdef DEBUG_ITRM_QUEUE { int i; /* Dump current queue in a readable form to stderr. */ for (i = 0; i < itrm->qlen; i++) if (itrm->kqueue[i] == ASCII_ESC) fprintf(stderr, "ESC "); else if (isprint(itrm->kqueue[i]) && !isspace(itrm->kqueue[i])) fprintf(stderr, "%c ", itrm->kqueue[i]); else fprintf(stderr, "0x%02x ", itrm->kqueue[i]); fprintf(stderr, "\n"); fflush(stderr); }#endif /* DEBUG_ITRM_QUEUE */ if (itrm->kqueue[0] == ASCII_ESC) { if (itrm->qlen < 2) goto ret; if (itrm->kqueue[1] == '[' || itrm->kqueue[1] == 'O') { el = decode_terminal_escape_sequence(itrm, &ev); if (el == -1) goto ret; } else { el = 2; if (itrm->kqueue[1] == ASCII_ESC) { if (itrm->qlen >= 3 && (itrm->kqueue[2] == '[' || itrm->kqueue[2] == 'O')) { el = 1; } set_kbd_event(&ev, KBD_ESC, 0); } else { set_kbd_event(&ev, itrm->kqueue[1], KBD_ALT); } } } else if (itrm->kqueue[0] == 0) { static const struct { int key, modifier; } os2xtd[256] = {#include "terminal/key.inc" }; if (itrm->qlen < 2) goto ret; ev.info.keyboard.key = os2xtd[itrm->kqueue[1]].key; if (!ev.info.keyboard.key) ev.info.keyboard.key = -1; ev.info.keyboard.modifier = os2xtd[itrm->kqueue[1]].modifier; el = 2; } else { el = 1; set_kbd_event(&ev, itrm->kqueue[0], 0); } assertm(itrm->qlen >= el, "event queue underflow"); if_assert_failed { itrm->qlen = el; } itrm->qlen -= el; /* The call to decode_terminal_escape_sequence() might have changed the * keyboard event to a mouse event. */ if (ev.ev == EVENT_MOUSE || ev.info.keyboard.key != -1) queue_event(itrm, (char *) &ev, sizeof(ev)); if (itrm->qlen) memmove(itrm->kqueue, itrm->kqueue + el, itrm->qlen);end: if (itrm->qlen < IN_BUF_SIZE) set_handlers(itrm->std_in, (void (*)(void *)) in_kbd, NULL, (void (*)(void *)) free_trm, itrm); return el;ret: itrm->timer = install_timer(ESC_TIMEOUT, (void (*)(void *)) kbd_timeout, itrm); return 0;}static voidin_kbd(struct itrm *itrm){ int r; if (!can_read(itrm->std_in)) return; if (itrm->timer != -1) { kill_timer(itrm->timer); itrm->timer = -1; } if (itrm->qlen >= IN_BUF_SIZE) { set_handlers(itrm->std_in, NULL, NULL, (void (*)(void *)) free_trm, itrm); while (process_queue(itrm)); return; } r = safe_read(itrm->std_in, itrm->kqueue + itrm->qlen, IN_BUF_SIZE - itrm->qlen); if (r <= 0) { free_trm(itrm); return; } itrm->qlen += r; if (itrm->qlen > IN_BUF_SIZE) { ERROR(gettext("Too many bytes read from the itrm!")); itrm->qlen = IN_BUF_SIZE; } while (process_queue(itrm));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -