"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/kbd.c" (22 Nov 2011, 23447 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "kbd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_1.03.

    1 #include "links.h"
    2 
    3 #define OUT_BUF_SIZE    16384
    4 #define IN_BUF_SIZE 16
    5 
    6 #define USE_TWIN_MOUSE  1
    7 #define TW_BUTT_LEFT    1
    8 #define TW_BUTT_MIDDLE  2
    9 #define TW_BUTT_RIGHT   4
   10 
   11 struct itrm {
   12     int std_in;
   13     int std_out;
   14     int sock_in;
   15     int sock_out;
   16     int ctl_in;
   17     int blocked;
   18     struct termios t;
   19     int flags;
   20     unsigned char kqueue[IN_BUF_SIZE];
   21     int qlen;
   22     int tm;
   23     unsigned char *ev_queue;
   24     int eqlen;
   25     void *mouse_h;
   26     unsigned char *orig_title;
   27 };
   28 
   29 void free_trm(struct itrm *);
   30 void in_kbd(struct itrm *);
   31 void in_sock(struct itrm *);
   32 
   33 struct itrm *ditrm = NULL;
   34 
   35 int is_blocked()
   36 {
   37     return ditrm && ditrm->blocked;
   38 }
   39 
   40 void free_all_itrms()
   41 {
   42     if (ditrm) free_trm(ditrm);
   43 }
   44 
   45 void write_ev_queue(struct itrm *itrm)
   46 {
   47     int l;
   48     if (!itrm->eqlen) internal("event queue empty");
   49     if ((l = write(itrm->sock_out, itrm->ev_queue, itrm->eqlen > 128 ? 128 : itrm->eqlen)) == -1) {
   50         free_trm(itrm);
   51         return;
   52     }
   53     memmove(itrm->ev_queue, itrm->ev_queue + l, itrm->eqlen -= l);
   54     if (!itrm->eqlen) set_handlers(itrm->sock_out, get_handler(itrm->sock_out, H_READ), NULL, get_handler(itrm->sock_out, H_ERROR), get_handler(itrm->sock_out, H_DATA));
   55 }
   56 
   57 void queue_event(struct itrm *itrm, unsigned char *data, int len);
   58 
   59 void mouse_queue_event(struct itrm *itrm, unsigned char *data, int len)
   60 {
   61     if (itrm->blocked) return;
   62     queue_event(itrm, data, len);
   63 }
   64 
   65 void queue_event(struct itrm *itrm, unsigned char *data, int len)
   66 {
   67     int w = 0;
   68     if (!len) return;
   69     if (!itrm->eqlen && can_write(itrm->sock_out) && (w = write(itrm->sock_out, data, len)) <= 0) {
   70         /*free_trm(itrm);*/
   71         register_bottom_half((void (*)(void *))free_trm, itrm);
   72         return;
   73     }
   74     if (w < len) {
   75         if ((unsigned)itrm->eqlen + (unsigned)(len - w) > MAXINT) overalloc();
   76         itrm->ev_queue = mem_realloc(itrm->ev_queue, itrm->eqlen + len - w);
   77         memcpy(itrm->ev_queue + itrm->eqlen, data + w, len - w);
   78         itrm->eqlen += len - w;
   79         set_handlers(itrm->sock_out, get_handler(itrm->sock_out, H_READ), (void (*)(void *))write_ev_queue, (void (*)(void *))free_trm, itrm);
   80     }
   81 }
   82 
   83 void kbd_ctrl_c()
   84 {
   85     struct event ev = { EV_KBD, KBD_CTRL_C, 0, 0 };
   86     if (ditrm) queue_event(ditrm, (unsigned char *)&ev, sizeof(struct event));
   87 }
   88 
   89 /*
   90 unsigned char *init_seq = "\033[?1000h\033[?47h\0337";
   91 unsigned char *term_seq = "\033[2J\033[?1000l\033[?47l\0338\b \b";
   92 */
   93 
   94 unsigned char init_seq[] = "\033)0\0337";
   95 unsigned char init_seq_x_mouse[] = "\033[?1000h";
   96 unsigned char init_seq_tw_mouse[] = "\033[?9h";
   97 unsigned char term_seq[] = "\033[2J\0338\r \b";
   98 unsigned char term_seq_x_mouse[] = "\033[?1000l\015       \015";
   99 unsigned char term_seq_tw_mouse[] = "\033[?9l";
  100 
  101 /*unsigned char *term_seq = "\033[2J\033[?1000l\0338\b \b";*/
  102 
  103 void send_init_sequence(int h, int flags)
  104 {
  105     want_draw();
  106     hard_write(h, init_seq, strlen(init_seq));
  107     if (flags & USE_TWIN_MOUSE) {
  108         hard_write(h, init_seq_tw_mouse, strlen(init_seq_tw_mouse));
  109     } else {
  110         hard_write(h, init_seq_x_mouse, strlen(init_seq_x_mouse));
  111     }
  112     done_draw();
  113 }
  114 
  115 void send_term_sequence(int h,int flags)
  116 {
  117     want_draw();
  118     hard_write(h, term_seq, strlen(term_seq));
  119     if (flags & USE_TWIN_MOUSE) {
  120         hard_write(h, term_seq_tw_mouse, strlen(term_seq_tw_mouse));
  121     } else {
  122         hard_write(h, term_seq_x_mouse, strlen(term_seq_x_mouse));
  123     }
  124     done_draw();
  125 }
  126 
  127 void resize_terminal()
  128 {
  129     struct event ev = { EV_RESIZE, 0, 0, 0 };
  130     int x, y;
  131     if (get_terminal_size(ditrm->std_out, &x, &y)) return;
  132     ev.x = x;
  133     ev.y = y;
  134     queue_event(ditrm, (unsigned char *)&ev, sizeof(struct event));
  135 }
  136 
  137 int ttcgetattr(int fd, struct termios *t)
  138 {
  139     int r;
  140 #ifdef SIGTTOU
  141     interruptible_signal(SIGTTOU, 1);
  142 #endif
  143 #ifdef SIGTTIN
  144     interruptible_signal(SIGTTIN, 1);
  145 #endif
  146     r = tcgetattr(fd, t);
  147 #ifdef SIGTTOU
  148     interruptible_signal(SIGTTOU, 0);
  149 #endif
  150 #ifdef SIGTTIN
  151     interruptible_signal(SIGTTIN, 0);
  152 #endif
  153     return r;
  154 }
  155 
  156 int ttcsetattr(int fd, int a, struct termios *t)
  157 {
  158     int r;
  159 #ifdef SIGTTOU
  160     interruptible_signal(SIGTTOU, 1);
  161 #endif
  162 #ifdef SIGTTIN
  163     interruptible_signal(SIGTTIN, 1);
  164 #endif
  165     r = tcsetattr(fd, a, t);
  166 #ifdef SIGTTOU
  167     interruptible_signal(SIGTTOU, 0);
  168 #endif
  169 #ifdef SIGTTIN
  170     interruptible_signal(SIGTTIN, 0);
  171 #endif
  172     return r;
  173 }
  174 
  175 int setraw(int fd, struct termios *p)
  176 {
  177     struct termios t;
  178     memset(&t, 0, sizeof(struct termios));
  179     if (ttcgetattr(fd, &t)) {
  180         /*fprintf(stderr, "getattr result %s\n", strerror(errno));*/
  181         /* If the terminal was destroyed (the user logged off),
  182          * we fake success here so that we can destroy the terminal
  183          * later.
  184          *
  185          * Linux returns EIO
  186          * FreeBSD returns ENXIO
  187          */
  188         if (errno == EIO || errno == ENXIO) return 0;
  189         return -1;
  190     }
  191     if (p) memcpy(p, &t, sizeof(struct termios));
  192     os_cfmakeraw(&t);
  193     t.c_lflag |= ISIG;
  194 #ifdef TOSTOP
  195     t.c_lflag |= TOSTOP;
  196 #endif
  197     t.c_oflag |= OPOST;
  198     if (ttcsetattr(fd, TCSANOW, &t)) {
  199         /*fprintf(stderr, "setattr result %s\n", strerror(errno));*/
  200         return -1;
  201     }
  202     return 0;
  203 }
  204 
  205 void handle_trm(int std_in, int std_out, int sock_in, int sock_out, int ctl_in, void *init_string, int init_len)
  206 {
  207     int x, y;
  208     struct itrm *itrm;
  209     struct event ev = { EV_INIT, 80, 24, 0 };
  210     unsigned char *ts;
  211     int xwin;
  212     if (get_terminal_size(ctl_in, &x, &y)) {
  213         error("ERROR: could not get terminal size");
  214         return;
  215     }
  216     itrm = mem_alloc(sizeof(struct itrm));
  217     ditrm = itrm;
  218     itrm->std_in = std_in;
  219     itrm->std_out = std_out;
  220     itrm->sock_in = sock_in;
  221     itrm->sock_out = sock_out;
  222     itrm->ctl_in = ctl_in;
  223     itrm->blocked = 0;
  224     itrm->qlen = 0;
  225     itrm->tm = -1;
  226     itrm->ev_queue = DUMMY;
  227     itrm->eqlen = 0;
  228     if (ctl_in >= 0) setraw(ctl_in, &itrm->t);
  229     set_handlers(std_in, (void (*)(void *))in_kbd, NULL, (void (*)(void *))free_trm, itrm);
  230     if (sock_in != std_out) set_handlers(sock_in, (void (*)(void *))in_sock, NULL, (void (*)(void *))free_trm, itrm);
  231     ev.x = x;
  232     ev.y = y;
  233     handle_terminal_resize(ctl_in, resize_terminal);
  234     queue_event(itrm, (unsigned char *)&ev, sizeof(struct event));
  235     xwin = is_xterm() * ENV_XWIN + can_twterm() * ENV_TWIN + (!!getenv("STY")) * ENV_SCREEN + get_system_env();
  236     itrm->flags = 0;
  237     if (!(ts = getenv("TERM"))) ts = "";
  238     if ((xwin & ENV_TWIN) && !strcmp(ts,"linux")) itrm->flags |= USE_TWIN_MOUSE;
  239     if (strlen(ts) >= MAX_TERM_LEN) queue_event(itrm, ts, MAX_TERM_LEN);
  240     else {
  241         unsigned char *mm;
  242         int ll = MAX_TERM_LEN - strlen(ts);
  243         queue_event(itrm, ts, strlen(ts));
  244         mm = mem_alloc(ll);
  245         memset(mm, 0, ll);
  246         queue_event(itrm, mm, ll);
  247         mem_free(mm);
  248     }
  249     if (!(ts = get_cwd())) ts = stracpy("");
  250     if (strlen(ts) >= MAX_CWD_LEN) queue_event(itrm, ts, MAX_CWD_LEN);
  251     else {
  252         unsigned char *mm;
  253         int ll = MAX_CWD_LEN - strlen(ts);
  254         queue_event(itrm, ts, strlen(ts));
  255         mm = mem_alloc(ll);
  256         memset(mm, 0, ll);
  257         queue_event(itrm, mm, ll);
  258         mem_free(mm);
  259     }
  260     mem_free(ts);
  261     queue_event(itrm, (unsigned char *)&xwin, sizeof(int));
  262     queue_event(itrm, (unsigned char *)&init_len, sizeof(int));
  263     queue_event(itrm, (unsigned char *)init_string, init_len);
  264     itrm->mouse_h = handle_mouse(0, (void (*)(void *, unsigned char *, int))mouse_queue_event, itrm);
  265     itrm->orig_title = get_window_title();
  266     set_window_title("Links");
  267     send_init_sequence(std_out, itrm->flags);
  268 }
  269 
  270 void unblock_itrm_x(void *h)
  271 {
  272     close_handle(h);
  273     if (!ditrm) return;
  274     unblock_itrm(0);
  275 }
  276 
  277 int unblock_itrm(int fd)
  278 {
  279     struct itrm *itrm = ditrm;
  280     if (!itrm) return -1;
  281     if (itrm->ctl_in >= 0 && setraw(itrm->ctl_in, NULL)) return -1;
  282     if (itrm->blocked != fd + 1) return -2;
  283     itrm->blocked = 0;
  284     send_init_sequence(itrm->std_out, itrm->flags);
  285     set_handlers(itrm->std_in, (void (*)(void *))in_kbd, NULL, (void (*)(void *))free_trm, itrm);
  286     handle_terminal_resize(itrm->ctl_in, resize_terminal);
  287     unblock_stdin();
  288     resize_terminal();
  289     return 0;
  290 }
  291 
  292 void block_itrm(int fd)
  293 {
  294     struct itrm *itrm = ditrm;
  295     if (!itrm) return;
  296     if (itrm->blocked) return;
  297     itrm->blocked = fd + 1;
  298     block_stdin();
  299     unhandle_terminal_resize(itrm->ctl_in);
  300     send_term_sequence(itrm->std_out,itrm->flags);
  301     ttcsetattr(itrm->ctl_in, TCSANOW, &itrm->t);
  302     set_handlers(itrm->std_in, NULL, NULL, (void (*)(void *))free_trm, itrm);
  303 }
  304 
  305 void free_trm(struct itrm *itrm)
  306 {
  307     if (!itrm) return;
  308     set_window_title(itrm->orig_title);
  309     if (itrm->orig_title) mem_free(itrm->orig_title), itrm->orig_title = NULL;
  310     unhandle_terminal_resize(itrm->ctl_in);
  311     send_term_sequence(itrm->std_out,itrm->flags);
  312     ttcsetattr(itrm->ctl_in, TCSANOW, &itrm->t);
  313     if (itrm->mouse_h) unhandle_mouse(itrm->mouse_h);
  314     set_handlers(itrm->std_in, NULL, NULL, NULL, NULL);
  315     set_handlers(itrm->sock_in, NULL, NULL, NULL, NULL);
  316     set_handlers(itrm->std_out, NULL, NULL, NULL, NULL);
  317     set_handlers(itrm->sock_out, NULL, NULL, NULL, NULL);
  318     if (itrm->tm != -1) kill_timer(itrm->tm);
  319     mem_free(itrm->ev_queue);
  320     mem_free(itrm);
  321     if (itrm == ditrm) ditrm = NULL;
  322 }
  323 
  324 void fatal_tty_exit(void)
  325 {
  326     if (ditrm) ttcsetattr(ditrm->ctl_in, TCSANOW, &ditrm->t);
  327 }
  328 
  329 void resize_terminal_x(unsigned char *text)
  330 {
  331     int x, y;
  332     unsigned char *p;
  333     if (!(p = strchr(text, ','))) return;
  334     *p++ = 0;
  335     x = atoi(text);
  336     y = atoi(p);
  337     resize_window(x, y);
  338     resize_terminal();
  339 }
  340 
  341 void dispatch_special(unsigned char *text)
  342 {
  343     switch (text[0]) {
  344         case TERM_FN_TITLE:
  345             set_window_title(text + 1);
  346             break;
  347         case TERM_FN_RESIZE:
  348             resize_terminal_x(text + 1);
  349             break;
  350     }
  351 }
  352 
  353 unsigned char buf[OUT_BUF_SIZE];
  354 
  355 #define RD(xx) { unsigned char cc; if (p < c) cc = buf[p++]; else if ((hard_read(itrm->sock_in, &cc, 1)) <= 0) goto fr; xx = cc; }
  356 
  357 void in_sock(struct itrm *itrm)
  358 {
  359     unsigned char *path, *delete;
  360     int pl, dl;
  361     unsigned char ch;
  362     int fg;
  363     int c, i, p;
  364     if ((c = read(itrm->sock_in, buf, OUT_BUF_SIZE)) <= 0) {
  365         fr:
  366         free_trm(itrm);
  367         terminate = 1;
  368         return;
  369     }
  370     qwerty:
  371     for (i = 0; i < c; i++) if (!buf[i]) goto ex;
  372     if (!is_blocked()) {
  373         want_draw();
  374         hard_write(itrm->std_out, buf, c);
  375         done_draw();
  376     }
  377     return;
  378     ex:
  379     if (!is_blocked()) {
  380         want_draw();
  381         hard_write(itrm->std_out, buf, i);
  382         done_draw();
  383     }
  384     i++;
  385     memmove(buf, buf + i, OUT_BUF_SIZE - i);
  386     c -= i;
  387     p = 0;
  388     /*fg = RD;*/
  389     RD(fg);
  390     path = init_str();
  391     delete = init_str();
  392     pl = dl = 0;
  393     while (1) {
  394         RD(ch);
  395         if (!ch) break;
  396         add_chr_to_str(&path, &pl, ch);
  397     }
  398     while (1) {
  399         RD(ch);
  400         if (!ch) break;
  401         add_chr_to_str(&delete, &dl, ch);
  402     }
  403     if (!*path) {
  404         dispatch_special(delete);
  405     } else {
  406         int blockh;
  407         unsigned char *param;
  408         if (is_blocked() && fg) {
  409             if (*delete) unlink(delete);
  410             goto to_je_ale_hnus;
  411         }
  412         param = mem_alloc(strlen(path) + strlen(delete) + 3);
  413         param[0] = fg;
  414         strcpy(param + 1, path);
  415         strcpy(param + 1 + strlen(path) + 1, delete);
  416         if (fg == 1) block_itrm(0);
  417         if ((blockh = start_thread((void (*)(void *, int))exec_thread, param, strlen(path) + strlen(delete) + 3)) == -1) {
  418             if (fg == 1) unblock_itrm(0);
  419             mem_free(param);
  420             goto to_je_ale_hnus;
  421         }
  422         mem_free(param);
  423         if (fg == 1) {
  424             set_handlers(blockh, (void (*)(void *))unblock_itrm_x, NULL, (void (*)(void *))unblock_itrm_x, (void *)blockh);
  425         } else {
  426             set_handlers(blockh, close_handle, NULL, close_handle, (void *)blockh);
  427         }
  428     }
  429     to_je_ale_hnus:
  430     mem_free(path);
  431     mem_free(delete);
  432     memmove(buf, buf + p, OUT_BUF_SIZE - p);
  433     c -= p;
  434     goto qwerty;
  435 }
  436 
  437 int process_queue(struct itrm *);
  438 
  439 int get_esc_code(unsigned char *str, int len, unsigned char *code, int *num, int *el)
  440 {
  441     int pos;
  442     *num = 0;
  443     for (pos = 2; pos < len; pos++) {
  444         if (str[pos] < '0' || str[pos] > '9' || pos > 7) {
  445             *el = pos + 1;
  446             *code = str[pos];
  447             return 0;
  448         }
  449         *num = *num * 10 + str[pos] - '0';
  450     }
  451     return -1;
  452 }
  453 
  454 void kbd_timeout(struct itrm *itrm)
  455 {
  456     struct event ev = {EV_KBD, KBD_ESC, 0, 0};
  457     unsigned char code;
  458     int num;
  459     int len;
  460     itrm->tm = -1;
  461     if (can_read(itrm->std_in)) {
  462         in_kbd(itrm);
  463         return;
  464     }
  465     if (!itrm->qlen) {
  466         internal("timeout on empty queue");
  467         return;
  468     }
  469     queue_event(itrm, (unsigned char *)&ev, sizeof(struct event));
  470     if (get_esc_code(itrm->kqueue, itrm->qlen, &code, &num, &len)) len = 1;
  471     itrm->qlen -= len;
  472     memmove(itrm->kqueue, itrm->kqueue + len, itrm->qlen);
  473     while (process_queue(itrm)) ;
  474 }
  475 
  476 struct key {
  477     int x, y;
  478 };
  479 
  480 struct key os2xtd[256] = {
  481 /* 0 */
  482 {0,0},{0,0},{' ',KBD_CTRL},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{KBD_BS,KBD_ALT},{0,0},
  483 /* 16 */
  484 {'Q',KBD_ALT},{'W',KBD_ALT},{'E',KBD_ALT},{'R',KBD_ALT},{'T',KBD_ALT},{'Y',KBD_ALT},{'U',KBD_ALT},{'I',KBD_ALT},
  485 /* 24 */
  486 {'O',KBD_ALT},{'P',KBD_ALT},{'[',KBD_ALT},{']',KBD_ALT},{KBD_ENTER,KBD_ALT},{0,0},{'A',KBD_ALT},{'S',KBD_ALT},
  487 /* 32 */
  488 {'D',KBD_ALT},{'F',KBD_ALT},{'G',KBD_ALT},{'H',KBD_ALT},{'J',KBD_ALT},{'K',KBD_ALT},{'L',KBD_ALT},{';',KBD_ALT},
  489 /* 40 */
  490 {'\'',KBD_ALT},{'`',KBD_ALT},{0,0},{'\\',KBD_ALT},{'Z',KBD_ALT},{'X',KBD_ALT},{'C',KBD_ALT},{'V',KBD_ALT},
  491 /* 48 */
  492 {'B',KBD_ALT},{'N',KBD_ALT},{'M',KBD_ALT},{',',KBD_ALT},{'.',KBD_ALT},{'/',KBD_ALT},{0,0},{'*',KBD_ALT},
  493 /* 56 */
  494 {0,0},{' ',KBD_ALT},{0,0},{KBD_F1,0},{KBD_F2,0},{KBD_F3,0},{KBD_F4,0},{KBD_F5,0},
  495 /* 64 */
  496 {KBD_F6,0},{KBD_F7,0},{KBD_F8,0},{KBD_F9,0},{KBD_F10,0},{0,0},{0,0},{KBD_HOME,0},
  497 /* 72 */
  498 {KBD_UP,0},{KBD_PAGE_UP,0},{'-',KBD_ALT},{KBD_LEFT,0},{'5',0},{KBD_RIGHT,0},{'+',KBD_ALT},{KBD_END,0},
  499 /* 80 */
  500 {KBD_DOWN,0},{KBD_PAGE_DOWN,0},{KBD_INS,0},{KBD_DEL,0},{0,0},{0,0},{0,0},{0,0},
  501 /* 88 */
  502 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{KBD_F1,KBD_CTRL},{KBD_F2,KBD_CTRL},
  503 /* 96 */
  504 {KBD_F3,KBD_CTRL},{KBD_F4,KBD_CTRL},{KBD_F5,KBD_CTRL},{KBD_F6,KBD_CTRL},{KBD_F7,KBD_CTRL},{KBD_F8,KBD_CTRL},{KBD_F9,KBD_CTRL},{KBD_F10,KBD_CTRL},
  505 /* 104 */
  506 {KBD_F1,KBD_ALT},{KBD_F2,KBD_ALT},{KBD_F3,KBD_ALT},{KBD_F4,KBD_ALT},{KBD_F5,KBD_ALT},{KBD_F6,KBD_ALT},{KBD_F7,KBD_ALT},{KBD_F8,KBD_ALT},
  507 /* 112 */
  508 {KBD_F9,KBD_ALT},{KBD_F10,KBD_ALT},{0,0},{KBD_LEFT,KBD_CTRL},{KBD_RIGHT,KBD_CTRL},{KBD_END,KBD_CTRL},{KBD_PAGE_DOWN,KBD_CTRL},{KBD_HOME,KBD_CTRL},
  509 /* 120 */
  510 {'1',KBD_ALT},{'2',KBD_ALT},{'3',KBD_ALT},{'4',KBD_ALT},{'5',KBD_ALT},{'6',KBD_ALT},{'7',KBD_ALT},{'8',KBD_ALT},
  511 /* 128 */
  512 {'9',KBD_ALT},{'0',KBD_ALT},{'-',KBD_ALT},{'=',KBD_ALT},{KBD_PAGE_UP,KBD_CTRL},{KBD_F11,0},{KBD_F12,0},{0,0},
  513 /* 136 */
  514 {0,0},{KBD_F11,KBD_CTRL},{KBD_F12,KBD_CTRL},{KBD_F11,KBD_ALT},{KBD_F12,KBD_ALT},{KBD_UP,KBD_CTRL},{'-',KBD_CTRL},{'5',KBD_CTRL},
  515 /* 144 */
  516 {'+',KBD_CTRL},{KBD_DOWN,KBD_CTRL},{KBD_INS,KBD_CTRL},{KBD_DEL,KBD_CTRL},{KBD_TAB,KBD_CTRL},{0,0},{0,0},{KBD_HOME,KBD_ALT},
  517 /* 152 */
  518 {KBD_UP,KBD_ALT},{KBD_PAGE_UP,KBD_ALT},{0,0},{KBD_LEFT,KBD_ALT},{0,0},{KBD_RIGHT,KBD_ALT},{0,0},{KBD_END,KBD_ALT},
  519 /* 160 */
  520 {KBD_DOWN,KBD_ALT},{KBD_PAGE_DOWN,KBD_ALT},{KBD_INS,KBD_ALT},{KBD_DEL,KBD_ALT},{0,0},{KBD_TAB,KBD_ALT},{KBD_ENTER,KBD_ALT},{0,0},
  521 /* 168 */
  522 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  523 /* 176 */
  524 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  525 /* 192 */
  526 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  527 /* 208 */
  528 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  529 /* 224 */
  530 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  531 /* 240 */
  532 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
  533 /* 256 */
  534 };
  535 
  536 int xterm_button = -1;
  537 
  538 int is_interix(void)
  539 {
  540 #ifdef INTERIX
  541     return 1;
  542 #else
  543     unsigned char *term = getenv("TERM");
  544     return term && !strncmp(term, "interix", 7);
  545 #endif
  546 }
  547 
  548 int is_ibm(void)
  549 {
  550     unsigned char *term = getenv("TERM");
  551     return term && !strncmp(term, "ibm", 3);
  552 }
  553 
  554 int process_queue(struct itrm *itrm)
  555 {
  556     struct event ev = { EV_KBD, -1, 0, 0 };
  557     int el = 0;
  558     if (!itrm->qlen) goto end;
  559     /*{
  560         int i;
  561         fprintf(stderr, "queue:");
  562         for (i = 0; i < itrm->qlen; i++) {
  563             fprintf(stderr, " %d", itrm->kqueue[i]);
  564             if (itrm->kqueue[i] >= 32) fprintf(stderr, "[%c]", itrm->kqueue[i]);
  565         }
  566         fprintf(stderr, ".\n");
  567     }*/
  568     if (itrm->kqueue[0] == '\033') {
  569         if (itrm->qlen < 2) goto ret;
  570         if (itrm->kqueue[1] == '[' || itrm->kqueue[1] == 'O') {
  571             unsigned char c = 0;
  572             int v;
  573             if (itrm->qlen >= 4 && itrm->kqueue[2] == '[') {
  574                 if (itrm->kqueue[3] < 'A' || itrm->kqueue[3] > 'L') goto ret;
  575                 ev.x = KBD_F1 + (itrm->kqueue[3] - 'A');
  576                 el = 4;
  577             } else if (get_esc_code(itrm->kqueue, itrm->qlen, &c, &v, &el)) goto ret;
  578             else switch (c) {
  579                 case 'L':
  580                 case '@': ev.x = KBD_INS; break;
  581                 case 'A': ev.x = KBD_UP; break;
  582                 case 'B': ev.x = KBD_DOWN; break;
  583                 case 'C': ev.x = KBD_RIGHT; break;
  584                 case 'D': ev.x = KBD_LEFT; break;
  585                 case 'F':
  586                 case 'K':
  587                 case 'e': ev.x = KBD_END; break;
  588                 case 'H':
  589                 case 0: ev.x = KBD_HOME; break;
  590                 case 'V':
  591                 case 'I': ev.x = KBD_PAGE_UP; break;
  592                 case 'U':
  593                     if (is_interix()) {
  594                         ev.x = KBD_END;
  595                         break;
  596                     }
  597                 case 'G': ev.x = KBD_PAGE_DOWN; break;
  598                 case 'P':
  599                     if (is_ibm()) {
  600                         ev.x = KBD_DEL;
  601                         break;
  602                     }
  603                     ev.x = KBD_F1; break;
  604                 case 'Q': ev.x = KBD_F2; break;
  605                 case 'S':
  606                     if (is_interix()) {
  607                         ev.x = KBD_PAGE_UP;
  608                         break;
  609                     }
  610                     ev.x = KBD_F4; break;
  611                 case 'T':
  612                     if (is_interix()) {
  613                         ev.x = KBD_PAGE_DOWN;
  614                         break;
  615                     }
  616                     ev.x = KBD_F5; break;
  617                 case 'W': ev.x = KBD_F8; break;
  618                 case 'X': ev.x = KBD_F9; break;
  619                 case 'Y': ev.x = KBD_F11; break;
  620 
  621                 case 'q': switch (v) {
  622                     case 139: ev.x = KBD_INS; break;
  623                     case 146: ev.x = KBD_END; break;
  624                     case 150: ev.x = KBD_PAGE_UP; break;
  625                     case 154: ev.x = KBD_PAGE_DOWN; break;
  626                     default: if (v >= 1 && v <= 48) {
  627                             int fn = (v - 1) % 12;
  628                             int mod = (v - 1) / 12;
  629                             ev.x = KBD_F1 + fn;
  630                             if (mod == 1)
  631                                 ev.y |= KBD_SHIFT;
  632                             if (mod == 2)
  633                                 ev.y |= KBD_CTRL;
  634                             if (mod == 3)
  635                                 ev.y |= KBD_ALT;
  636                         } break;
  637                     } break;
  638                 case 'z': switch (v) {
  639                     case 247: ev.x = KBD_INS; break;
  640                     case 214: ev.x = KBD_HOME; break;
  641                     case 220: ev.x = KBD_END; break;
  642                     case 216: ev.x = KBD_PAGE_UP; break;
  643                     case 222: ev.x = KBD_PAGE_DOWN; break;
  644                     case 249: ev.x = KBD_DEL; break;
  645                     } break;
  646                 case '~': switch (v) {
  647                     case 1: ev.x = KBD_HOME; break;
  648                     case 2: ev.x = KBD_INS; break;
  649                     case 3: ev.x = KBD_DEL; break;
  650                     case 4: ev.x = KBD_END; break;
  651                     case 5: ev.x = KBD_PAGE_UP; break;
  652                     case 6: ev.x = KBD_PAGE_DOWN; break;
  653                     case 7: ev.x = KBD_HOME; break;
  654                     case 8: ev.x = KBD_END; break;
  655                     case 17: ev.x = KBD_F6; break;
  656                     case 18: ev.x = KBD_F7; break;
  657                     case 19: ev.x = KBD_F8; break;
  658                     case 20: ev.x = KBD_F9; break;
  659                     case 21: ev.x = KBD_F10; break;
  660                     case 23: ev.x = KBD_F11; break;
  661                     case 24: ev.x = KBD_F12; break;
  662                     } break;
  663                 case 'R':
  664                     resize_terminal();
  665                     break ;
  666                 case 'M': if (itrm->qlen - el < 3) goto ret;
  667                     if (v == 5) {
  668                         if (xterm_button == -1) xterm_button = 0; /* */
  669                         if (itrm->qlen - el < 5) goto ret;
  670                         ev.x = (unsigned char)(itrm->kqueue[el+1]) - ' ' - 1 + ((int)((unsigned char)(itrm->kqueue[el+2]) - ' ' - 1) << 7);
  671                         if ( ev.x & (1 << 13)) ev.x = 0; /* ev.x |= ~0 << 14; */
  672                         ev.y = (unsigned char)(itrm->kqueue[el+3]) - ' ' - 1 + ((int)((unsigned char)(itrm->kqueue[el+4]) - ' ' - 1) << 7);
  673                         if ( ev.y & (1 << 13)) ev.y = 0; /* ev.y |= ~0 << 14; */
  674                         switch ((itrm->kqueue[el] - ' ') ^ xterm_button) { /* Every event changhes only one bit */
  675                             case TW_BUTT_LEFT:   ev.b = B_LEFT | ( (xterm_button & TW_BUTT_LEFT) ? B_UP : B_DOWN ); break; 
  676                             case TW_BUTT_MIDDLE: ev.b = B_MIDDLE | ( (xterm_button & TW_BUTT_MIDDLE) ? B_UP :  B_DOWN ); break;
  677                             case TW_BUTT_RIGHT:  ev.b = B_RIGHT | ( (xterm_button & TW_BUTT_RIGHT) ? B_UP : B_DOWN ); break;
  678                             case 0: ev.b = B_DRAG;
  679                             /* default : Twin protocol error */
  680                         }
  681                         xterm_button = itrm->kqueue[el] - ' ';
  682                         el += 5;
  683                     } else {
  684                         ev.x = itrm->kqueue[el+1] - ' ' - 1;
  685                         ev.y = itrm->kqueue[el+2] - ' ' - 1;
  686                         ev.b = B_DOWN;
  687                         if (itrm->kqueue[el] & 4) ev.b = B_DRAG;
  688                         if ((ev.b |= (itrm->kqueue[el] & BM_BUTT) | B_DOWN) == 3) {
  689                             ev.b = B_UP;
  690                             if (xterm_button != -1) ev.b |= xterm_button;
  691                         }  
  692                         /*if ((itrm->kqueue[el] & 4) && ev.b != B_UP) ev.b |= B_DRAG;*/
  693                         xterm_button = -1;
  694                         if ((ev.b & BM_ACT) == B_DOWN) xterm_button = ev.b & BM_BUTT;
  695                         el += 3;
  696                     }
  697                     ev.ev = EV_MOUSE;
  698                     break;
  699             }
  700         } else {
  701             el = 2;
  702             if (itrm->kqueue[1] == '\033') {
  703                 if (itrm->qlen >= 3 && (itrm->kqueue[2] == '[' || itrm->kqueue[2] == 'O')) el = 1;
  704                 ev.x = KBD_ESC;
  705                 goto l2;
  706             } else if (itrm->kqueue[1] == 127) {
  707                 ev.x = KBD_DEL;
  708                 ev.y = 0;
  709                 goto l2;
  710             } else if (itrm->kqueue[1] == 'F' && is_interix()) {
  711                 int num;
  712                 if (itrm->qlen < 3) goto ret;
  713                 if (itrm->kqueue[2] >= '1' && itrm->kqueue[2] <= '9') {
  714                     num = itrm->kqueue[2] - '1';
  715                 } else if (itrm->kqueue[2] >= 'A' && itrm->kqueue[2] <= 'Z') {
  716                     num = itrm->kqueue[2] - 'A' + 9;
  717                 } else if (itrm->kqueue[2] >= 'a' && itrm->kqueue[2] <= 'k') {
  718                     num = itrm->kqueue[2] - 'a' + 35;
  719                 } else if (itrm->kqueue[2] >= 'm' && itrm->kqueue[2] <= 'z') {
  720                     num = itrm->kqueue[2] - 'a' + 34;
  721                 } else goto do_alt;
  722                 if (num < 12) {
  723                     ev.x = KBD_F1 + num;
  724                 } else if (num < 24) {
  725                     ev.x = KBD_F1 + (num - 12);
  726                     ev.y |= KBD_SHIFT;
  727                 } else if (num < 36) {
  728                     ev.x = KBD_F1 + (num - 24);
  729                     ev.y |= KBD_ALT;
  730                 } else if (num < 48) {
  731                     ev.x = KBD_F1 + (num - 36);
  732                     ev.y |= KBD_CTRL;
  733                 } else {
  734                     ev.x = KBD_F1 + (num - 48);
  735                     ev.y |= KBD_SHIFT | KBD_CTRL;
  736                 }
  737                 el = 3;
  738                 goto l1;
  739             } else {
  740 do_alt:
  741                 ev.x = itrm->kqueue[1];
  742                 ev.y |= KBD_ALT;
  743                 goto l2;
  744             }
  745         }
  746         goto l1;
  747     } else if (itrm->kqueue[0] == 0) {
  748         if (itrm->qlen < 2) goto ret;
  749         if (!(ev.x = os2xtd[itrm->kqueue[1]].x)) ev.x = -1;
  750         ev.y = os2xtd[itrm->kqueue[1]].y;
  751         el = 2;
  752         /*printf("%02x - %02x %02x\n", (int)itrm->kqueue[1], ev.x, ev.y);*/
  753         goto l1;
  754     }
  755     el = 1;
  756     ev.x = itrm->kqueue[0];
  757     l2:
  758     /*if (ev.x == 1) ev.x = KBD_HOME;
  759     if (ev.x == 2) ev.x = KBD_PAGE_UP;
  760     if (ev.x == 4) ev.x = KBD_DEL;
  761     if (ev.x == 5) ev.x = KBD_END;
  762     if (ev.x == 6) ev.x = KBD_PAGE_DOWN;*/
  763     if (ev.x == 8) ev.x = KBD_BS;
  764     if (ev.x == 9) ev.x = KBD_TAB;
  765     if (ev.x == 10) ev.x = KBD_ENTER/*, ev.y = KBD_CTRL*/;
  766     if (ev.x == 13) ev.x = KBD_ENTER;
  767     if (ev.x == 127) {
  768         if (is_interix()) ev.x = KBD_DEL;
  769         else ev.x = KBD_BS;
  770     }
  771     if (ev.x >= 0 && ev.x < ' ') {
  772         ev.x += 'A' - 1;
  773         ev.y |= KBD_CTRL;
  774     }
  775     l1:
  776     if (itrm->qlen < el) {
  777         internal("event queue underflow");
  778         itrm->qlen = el;
  779     }
  780     if (ev.x != -1) {
  781         queue_event(itrm, (unsigned char *)&ev, sizeof(struct event));
  782         memmove(itrm->kqueue, itrm->kqueue + el, itrm->qlen -= el);
  783     } else {
  784         /*printf("%d %d\n", itrm->qlen, el);fflush(stdout);*/
  785         memmove(itrm->kqueue, itrm->kqueue + el, itrm->qlen -= el);
  786     }
  787     end:
  788     if (itrm->qlen < IN_BUF_SIZE && !itrm->blocked) set_handlers(itrm->std_in, (void (*)(void *))in_kbd, NULL, (void (*)(void *))free_trm, itrm);
  789     return el;
  790     ret:
  791     itrm->tm = install_timer(ESC_TIMEOUT, (void (*)(void *))kbd_timeout, itrm);
  792     return 0;
  793 }
  794 
  795 void in_kbd(struct itrm *itrm)
  796 {
  797     int r;
  798     if (!can_read(itrm->std_in)) return;
  799     if (itrm->tm != -1) kill_timer(itrm->tm), itrm->tm = -1;
  800     if (itrm->qlen >= IN_BUF_SIZE) {
  801         set_handlers(itrm->std_in, NULL, NULL, (void (*)(void *))free_trm, itrm);
  802         while (process_queue(itrm));
  803         return;
  804     }
  805     if ((r = read(itrm->std_in, itrm->kqueue + itrm->qlen, IN_BUF_SIZE - itrm->qlen)) <= 0) {
  806         struct event ev = { EV_ABORT, 0, 0, 0 };
  807         set_handlers(itrm->std_in, NULL, NULL, (void (*)(void *))free_trm, itrm);
  808         queue_event(itrm, (unsigned char *)&ev, sizeof(struct event));
  809         return;
  810     }
  811     if ((itrm->qlen += r) > IN_BUF_SIZE) {
  812         error("ERROR: too many bytes read");
  813         itrm->qlen = IN_BUF_SIZE;
  814     }
  815     while (process_queue(itrm));
  816 }