kbd.c (22003B)
1 /* kbd.c 2 * (c) 2002 Mikulas Patocka 3 * This file is a part of the Links program, released under GPL. 4 */ 5 6 #include <limits.h> 7 8 #include "links.h" 9 10 #define OUT_BUF_SIZE 10240 11 #define IN_BUF_SIZE 64 12 13 #define USE_TWIN_MOUSE 1 14 #define BRACKETED_PASTE 2 15 16 #define TW_BUTT_LEFT 1 17 #define TW_BUTT_MIDDLE 2 18 #define TW_BUTT_RIGHT 4 19 20 struct itrm { 21 int std_in; 22 int std_out; 23 int sock_in; 24 int sock_out; 25 int ctl_in; 26 int blocked; 27 int flags; 28 unsigned char kqueue[IN_BUF_SIZE]; 29 int qlen; 30 struct timer *tm; 31 void (*queue_event)(struct itrm *, unsigned char *, int); 32 unsigned char *ev_queue; 33 int eqlen; 34 void *mouse_h; 35 unsigned char *orig_title; 36 void (*free_trm)(struct itrm *); 37 }; 38 39 static void free_trm(struct itrm *); 40 static void in_kbd(void *); 41 42 static struct itrm *ditrm = NULL; 43 44 int 45 is_blocked(void) 46 { 47 return ditrm && ditrm->blocked; 48 } 49 50 void 51 free_all_itrms(void) 52 { 53 if (ditrm) 54 ditrm->free_trm(ditrm); 55 } 56 57 static void 58 itrm_error(void *itrm_) 59 { 60 struct itrm *itrm = (struct itrm *)itrm_; 61 itrm->free_trm(itrm); 62 terminate_loop = 1; 63 } 64 65 static void 66 write_ev_queue(void *itrm_) 67 { 68 struct itrm *itrm = (struct itrm *)itrm_; 69 int l, to_write; 70 if (!itrm->eqlen) 71 internal("event queue empty"); 72 to_write = itrm->eqlen; 73 retry: 74 EINTRLOOP(l, (int)write(itrm->sock_out, itrm->ev_queue, to_write)); 75 if (l <= 0) { 76 if (to_write > 1) { 77 to_write >>= 1; 78 goto retry; 79 } 80 itrm_error(itrm); 81 } 82 memmove(itrm->ev_queue, itrm->ev_queue + l, itrm->eqlen -= l); 83 if (!itrm->eqlen) 84 set_handlers(itrm->sock_out, 85 get_handler(itrm->sock_out, H_READ), NULL, 86 get_handler_data(itrm->sock_out)); 87 } 88 89 static void 90 queue_event(struct itrm *itrm, unsigned char *data, int len) 91 { 92 int w = 0; 93 if (!len) 94 return; 95 if (!itrm->eqlen && can_write(itrm->sock_out)) { 96 int to_write = len; 97 retry: 98 EINTRLOOP(w, (int)write(itrm->sock_out, data, to_write)); 99 if (w <= 0) { 100 if (to_write > 1) { 101 to_write >>= 1; 102 goto retry; 103 } 104 register_bottom_half(itrm_error, itrm); 105 return; 106 } 107 } 108 if (w < len) { 109 if ((unsigned)itrm->eqlen + (unsigned)(len - w) > INT_MAX) 110 overalloc(); 111 itrm->ev_queue = 112 xrealloc(itrm->ev_queue, itrm->eqlen + len - w); 113 memcpy(itrm->ev_queue + itrm->eqlen, data + w, len - w); 114 itrm->eqlen += len - w; 115 set_handlers(itrm->sock_out, 116 get_handler(itrm->sock_out, H_READ), 117 write_ev_queue, itrm); 118 } 119 } 120 121 void 122 kbd_ctrl_c(void) 123 { 124 struct links_event ev = { EV_KBD, KBD_CTRL_C, 0, 0 }; 125 if (ditrm) 126 ditrm->queue_event(ditrm, (unsigned char *)&ev, 127 sizeof(struct links_event)); 128 } 129 130 unsigned char init_seq[] = "\033)0\0337"; 131 unsigned char init_seq_x_mouse[] = 132 "\033[?1000h\033[?1002h\033[?1005l\033[?1015l\033[?1006h\033[?2004h"; 133 unsigned char init_seq_tw_mouse[] = "\033[?9h"; 134 unsigned char term_seq[] = "\033[2J\0338\r \b"; 135 unsigned char term_seq_x_mouse[] = 136 "\033[?1000l\r \r\033[?1002l\r \r\033[?1006l\r " 137 "\r\033[?2004l\r \r"; 138 unsigned char term_seq_tw_mouse[] = "\033[?9l"; 139 140 static void 141 send_init_sequence(int h, int flags) 142 { 143 hard_write(h, init_seq, (int)strlen(cast_const_char init_seq)); 144 if (flags & USE_TWIN_MOUSE) 145 hard_write(h, init_seq_tw_mouse, 146 (int)strlen(cast_const_char init_seq_tw_mouse)); 147 else 148 hard_write(h, init_seq_x_mouse, 149 (int)strlen(cast_const_char init_seq_x_mouse)); 150 } 151 152 static void 153 send_term_sequence(int h, int flags) 154 { 155 hard_write(h, term_seq, (int)strlen(cast_const_char term_seq)); 156 if (flags & USE_TWIN_MOUSE) 157 hard_write(h, term_seq_tw_mouse, 158 (int)strlen(cast_const_char term_seq_tw_mouse)); 159 else 160 hard_write(h, term_seq_x_mouse, 161 (int)strlen(cast_const_char term_seq_x_mouse)); 162 } 163 164 static void 165 resize_terminal(int x, int y) 166 { 167 struct links_event ev = { EV_RESIZE, 0, 0, 0 }; 168 ev.x = x; 169 ev.y = y; 170 queue_event(ditrm, (unsigned char *)&ev, sizeof(struct links_event)); 171 } 172 173 static void 174 os_cfmakeraw(struct termios *t) 175 { 176 cfmakeraw(t); 177 #ifdef VMIN 178 t->c_cc[VMIN] = 1; 179 #endif 180 #if defined(NO_CTRL_Z) && defined(VSUSP) 181 t->c_cc[VSUSP] = 0; 182 #endif 183 } 184 185 static int 186 ttcgetattr(int fd, struct termios *t) 187 { 188 int r; 189 block_signals( 190 #ifdef SIGTTOU 191 SIGTTOU 192 #else 193 0 194 #endif 195 , 196 #ifdef SIGTTIN 197 SIGTTIN 198 #else 199 0 200 #endif 201 ); 202 #ifdef SIGTTOU 203 interruptible_signal(SIGTTOU, 1); 204 #endif 205 #ifdef SIGTTIN 206 interruptible_signal(SIGTTIN, 1); 207 #endif 208 r = tcgetattr(fd, t); 209 #ifdef SIGTTOU 210 interruptible_signal(SIGTTOU, 0); 211 #endif 212 #ifdef SIGTTIN 213 interruptible_signal(SIGTTIN, 0); 214 #endif 215 unblock_signals(); 216 return r; 217 } 218 219 static int 220 ttcsetattr(int fd, int a, struct termios *t) 221 { 222 int r; 223 block_signals( 224 #ifdef SIGTTOU 225 SIGTTOU 226 #else 227 0 228 #endif 229 , 230 #ifdef SIGTTIN 231 SIGTTIN 232 #else 233 0 234 #endif 235 ); 236 #ifdef SIGTTOU 237 interruptible_signal(SIGTTOU, 1); 238 #endif 239 #ifdef SIGTTIN 240 interruptible_signal(SIGTTIN, 1); 241 #endif 242 r = tcsetattr(fd, a, t); 243 #ifdef SIGTTOU 244 interruptible_signal(SIGTTOU, 0); 245 #endif 246 #ifdef SIGTTIN 247 interruptible_signal(SIGTTIN, 0); 248 #endif 249 unblock_signals(); 250 return r; 251 } 252 253 static struct termios saved_termios; 254 255 static int 256 setraw(int ctl, int save) 257 { 258 struct termios t; 259 if (ctl < 0) 260 return 0; 261 memset(&t, 0, sizeof(struct termios)); 262 if (ttcgetattr(ctl, &t)) { 263 /*fprintf(stderr, "getattr result %s\n", strerror(errno));*/ 264 /* If the terminal was destroyed (the user logged off), 265 * we fake success here so that we can destroy the terminal 266 * later. 267 * 268 * Linux returns EIO 269 * FreeBSD returns ENXIO 270 */ 271 if (errno == EIO || errno == ENXIO) 272 return 0; 273 return -1; 274 } 275 if (save) 276 memcpy(&saved_termios, &t, sizeof(struct termios)); 277 os_cfmakeraw(&t); 278 t.c_lflag |= ISIG; 279 #ifdef TOSTOP 280 t.c_lflag |= TOSTOP; 281 #endif 282 t.c_oflag |= OPOST; 283 if (ttcsetattr(ctl, TCSANOW, &t)) { 284 return -1; 285 } 286 return 0; 287 } 288 289 static void 290 setcooked(int ctl) 291 { 292 if (ctl < 0) 293 return; 294 ttcsetattr(ctl, TCSANOW, &saved_termios); 295 } 296 297 void 298 handle_trm(int sock_out, void *init_string, int init_len) 299 { 300 struct itrm *itrm; 301 struct links_event ev = { EV_INIT, 0, 0, 0 }; 302 unsigned char *ts; 303 int xwin, def_charset; 304 itrm = xmalloc(sizeof(struct itrm)); 305 itrm->queue_event = queue_event; 306 itrm->free_trm = free_trm; 307 ditrm = itrm; 308 itrm->std_in = 0; 309 itrm->std_out = 1; 310 itrm->sock_in = 1; 311 itrm->sock_out = sock_out; 312 itrm->ctl_in = 0; 313 itrm->blocked = 0; 314 itrm->qlen = 0; 315 itrm->tm = NULL; 316 itrm->ev_queue = NULL; 317 itrm->eqlen = 0; 318 setraw(itrm->ctl_in, 1); 319 set_handlers(0, in_kbd, NULL, itrm); 320 handle_terminal_resize(resize_terminal, &ev.x, &ev.y); 321 queue_event(itrm, (unsigned char *)&ev, sizeof(struct links_event)); 322 xwin = is_xterm() * ENV_XWIN + is_screen() * ENV_SCREEN; 323 itrm->flags = 0; 324 if (!(ts = cast_uchar getenv("TERM"))) 325 ts = cast_uchar ""; 326 if (strlen(cast_const_char ts) >= MAX_TERM_LEN) 327 queue_event(itrm, ts, MAX_TERM_LEN); 328 else { 329 unsigned char *mm; 330 int ll = MAX_TERM_LEN - (int)strlen(cast_const_char ts); 331 queue_event(itrm, ts, (int)strlen(cast_const_char ts)); 332 mm = mem_calloc(ll); 333 queue_event(itrm, mm, ll); 334 free(mm); 335 } 336 if (!(ts = get_cwd())) 337 ts = stracpy(cast_uchar ""); 338 if (strlen(cast_const_char ts) >= MAX_CWD_LEN) 339 queue_event(itrm, ts, MAX_CWD_LEN); 340 else { 341 unsigned char *mm; 342 int ll = MAX_CWD_LEN - (int)strlen(cast_const_char ts); 343 queue_event(itrm, ts, (int)strlen(cast_const_char ts)); 344 mm = mem_calloc(ll); 345 queue_event(itrm, mm, ll); 346 free(mm); 347 } 348 free(ts); 349 queue_event(itrm, (unsigned char *)&xwin, sizeof(int)); 350 def_charset = 0; 351 queue_event(itrm, (unsigned char *)&def_charset, sizeof(int)); 352 queue_event(itrm, (unsigned char *)&init_len, sizeof(int)); 353 queue_event(itrm, (unsigned char *)init_string, init_len); 354 itrm->orig_title = get_window_title(); 355 set_window_title(cast_uchar "Links"); 356 itrm->mouse_h = NULL; 357 send_init_sequence(1, itrm->flags); 358 } 359 360 int 361 unblock_itrm(int fd) 362 { 363 struct itrm *itrm = ditrm; 364 int x, y; 365 if (!itrm) 366 return -1; 367 if (setraw(itrm->ctl_in, 0)) 368 return -1; 369 if (itrm->blocked != fd + 1) 370 return -2; 371 itrm->blocked = 0; 372 send_init_sequence(itrm->std_out, itrm->flags); 373 set_handlers(itrm->std_in, in_kbd, NULL, itrm); 374 handle_terminal_resize(resize_terminal, &x, &y); 375 itrm->mouse_h = NULL; 376 resize_terminal(x, y); 377 return 0; 378 } 379 380 void 381 block_itrm(int fd) 382 { 383 struct itrm *itrm = ditrm; 384 if (!itrm) 385 return; 386 if (itrm->blocked) 387 return; 388 itrm->blocked = fd + 1; 389 unhandle_terminal_resize(); 390 itrm->mouse_h = NULL; 391 send_term_sequence(itrm->std_out, itrm->flags); 392 setcooked(itrm->ctl_in); 393 set_handlers(itrm->std_in, NULL, NULL, itrm); 394 } 395 396 static void 397 free_trm(struct itrm *itrm) 398 { 399 if (!itrm) 400 return; 401 set_window_title(itrm->orig_title); 402 free(itrm->orig_title); 403 itrm->orig_title = NULL; 404 unhandle_terminal_resize(); 405 send_term_sequence(itrm->std_out, itrm->flags); 406 setcooked(itrm->ctl_in); 407 set_handlers(itrm->std_in, NULL, NULL, NULL); 408 set_handlers(itrm->sock_in, NULL, NULL, NULL); 409 set_handlers(itrm->std_out, NULL, NULL, NULL); 410 set_handlers(itrm->sock_out, NULL, NULL, NULL); 411 unregister_bottom_half(itrm_error, itrm); 412 if (itrm->tm != NULL) 413 kill_timer(itrm->tm); 414 free(itrm->ev_queue); 415 free(itrm); 416 if (itrm == ditrm) 417 ditrm = NULL; 418 } 419 420 static void 421 refresh_terminal_size(void) 422 { 423 int new_x, new_y; 424 if (!ditrm->blocked) { 425 unhandle_terminal_resize(); 426 handle_terminal_resize(resize_terminal, &new_x, &new_y); 427 resize_terminal(new_x, new_y); 428 } 429 } 430 431 static void 432 resize_terminal_x(unsigned char *text) 433 { 434 unsigned char *p; 435 if (!(p = cast_uchar strchr(cast_const_char text, ','))) 436 return; 437 *p++ = 0; 438 refresh_terminal_size(); 439 } 440 441 void 442 dispatch_special(unsigned char *text) 443 { 444 switch (text[0]) { 445 case TERM_FN_TITLE: 446 set_window_title(text + 1); 447 break; 448 case TERM_FN_RESIZE: 449 resize_terminal_x(text + 1); 450 break; 451 } 452 } 453 454 static int process_queue(struct itrm *); 455 static int get_esc_code(unsigned char *, int, unsigned char *, int *, int *); 456 457 static void 458 kbd_timeout(void *itrm_) 459 { 460 struct itrm *itrm = (struct itrm *)itrm_; 461 struct links_event ev = { EV_KBD, KBD_ESC, 0, 0 }; 462 unsigned char code; 463 int num; 464 int len = 0; /* against warning */ 465 itrm->tm = NULL; 466 if (can_read(itrm->std_in)) { 467 in_kbd(itrm); 468 return; 469 } 470 if (!itrm->qlen) { 471 internal("timeout on empty queue"); 472 return; 473 } 474 if (itrm->kqueue[0] != 27) { 475 len = 1; 476 goto skip_esc; 477 } 478 itrm->queue_event(itrm, (unsigned char *)&ev, 479 sizeof(struct links_event)); 480 if (get_esc_code(itrm->kqueue, itrm->qlen, &code, &num, &len)) 481 len = 1; 482 skip_esc: 483 itrm->qlen -= len; 484 memmove(itrm->kqueue, itrm->kqueue + len, itrm->qlen); 485 while (process_queue(itrm)) 486 ; 487 } 488 489 static int 490 get_esc_code(unsigned char *str, int len, unsigned char *code, int *num, 491 int *el) 492 { 493 int pos; 494 *num = 0; 495 for (pos = 2; pos < len; pos++) { 496 if (str[pos] < '0' || str[pos] > '9' || pos > 7) { 497 *el = pos + 1; 498 *code = str[pos]; 499 return 0; 500 } 501 *num = *num * 10 + str[pos] - '0'; 502 } 503 return -1; 504 } 505 506 static int xterm_button = -1; 507 508 static int 509 process_queue(struct itrm *itrm) 510 { 511 struct links_event ev = { EV_KBD, -1, 0, 0 }; 512 int el = 0; 513 if (!itrm->qlen) 514 goto end; 515 if (itrm->kqueue[0] == '\033') { 516 if (itrm->qlen < 2) 517 goto ret; 518 if (itrm->kqueue[1] == '[' || itrm->kqueue[1] == 'O') { 519 unsigned char c = 0; 520 int v; 521 if (itrm->qlen >= 4 && itrm->kqueue[2] == '[') { 522 if (itrm->kqueue[3] < 'A' 523 || itrm->kqueue[3] > 'L') 524 goto ret; 525 ev.x = KBD_F1 - (itrm->kqueue[3] - 'A'); 526 el = 4; 527 } else if (get_esc_code(itrm->kqueue, itrm->qlen, &c, 528 &v, &el)) 529 goto ret; 530 else 531 switch (c) { 532 case 'L': 533 case '@': 534 ev.x = KBD_INS; 535 break; 536 case 'A': 537 ev.x = KBD_UP; 538 break; 539 case 'B': 540 ev.x = KBD_DOWN; 541 break; 542 case 'C': 543 ev.x = KBD_RIGHT; 544 break; 545 case 'D': 546 ev.x = KBD_LEFT; 547 break; 548 case 'F': 549 case 'K': 550 case 'e': 551 ev.x = KBD_END; 552 break; 553 case 'H': 554 case 0: 555 ev.x = KBD_HOME; 556 break; 557 case 'V': 558 case 'I': 559 ev.x = KBD_PAGE_UP; 560 break; 561 case 'U': 562 case 'G': 563 ev.x = KBD_PAGE_DOWN; 564 break; 565 case 'P': 566 ev.x = KBD_F1; 567 break; 568 case 'Q': 569 ev.x = KBD_F2; 570 break; 571 case 'S': 572 ev.x = KBD_F4; 573 break; 574 case 'T': 575 ev.x = KBD_F5; 576 break; 577 case 'W': 578 ev.x = KBD_F8; 579 break; 580 case 'X': 581 ev.x = KBD_F9; 582 break; 583 case 'Y': 584 ev.x = KBD_F11; 585 break; 586 587 case 'q': 588 switch (v) { 589 case 139: 590 ev.x = KBD_INS; 591 break; 592 case 146: 593 ev.x = KBD_END; 594 break; 595 case 150: 596 ev.x = KBD_PAGE_UP; 597 break; 598 case 154: 599 ev.x = KBD_PAGE_DOWN; 600 break; 601 default: 602 if (v >= 1 && v <= 48) { 603 int fn = (v - 1) % 12; 604 int mod = (v - 1) / 12; 605 ev.x = KBD_F1 - fn; 606 if (mod == 1) 607 ev.y |= 608 KBD_SHIFT; 609 if (mod == 2) 610 ev.y |= 611 KBD_CTRL; 612 if (mod == 3) 613 ev.y |= KBD_ALT; 614 } 615 break; 616 } 617 break; 618 case 'z': 619 switch (v) { 620 case 247: 621 ev.x = KBD_INS; 622 break; 623 case 214: 624 ev.x = KBD_HOME; 625 break; 626 case 220: 627 ev.x = KBD_END; 628 break; 629 case 216: 630 ev.x = KBD_PAGE_UP; 631 break; 632 case 222: 633 ev.x = KBD_PAGE_DOWN; 634 break; 635 case 249: 636 ev.x = KBD_DEL; 637 break; 638 } 639 break; 640 case '~': 641 switch (v) { 642 case 1: 643 ev.x = KBD_HOME; 644 break; 645 case 2: 646 ev.x = KBD_INS; 647 break; 648 case 3: 649 ev.x = KBD_DEL; 650 break; 651 case 4: 652 ev.x = KBD_END; 653 break; 654 case 5: 655 ev.x = KBD_PAGE_UP; 656 break; 657 case 6: 658 ev.x = KBD_PAGE_DOWN; 659 break; 660 case 7: 661 ev.x = KBD_HOME; 662 break; 663 case 8: 664 ev.x = KBD_END; 665 break; 666 case 17: 667 ev.x = KBD_F6; 668 break; 669 case 18: 670 ev.x = KBD_F7; 671 break; 672 case 19: 673 ev.x = KBD_F8; 674 break; 675 case 20: 676 ev.x = KBD_F9; 677 break; 678 case 21: 679 ev.x = KBD_F10; 680 break; 681 case 23: 682 ev.x = KBD_F11; 683 break; 684 case 24: 685 ev.x = KBD_F12; 686 break; 687 case 200: 688 itrm->flags |= BRACKETED_PASTE; 689 break; 690 case 201: 691 itrm->flags &= ~BRACKETED_PASTE; 692 break; 693 } 694 break; 695 case 'R': 696 refresh_terminal_size(); 697 break; 698 case 'M': 699 case '<': 700 if (c == 'M' && v == 5) { 701 if (xterm_button == -1) 702 xterm_button = 0; 703 if (itrm->qlen - el < 5) 704 goto ret; 705 ev.x = 706 (unsigned char)(itrm->kqueue 707 [el 708 + 1]) 709 - ' ' - 1 710 + ((int)((unsigned char)(itrm->kqueue 711 [el 712 + 2]) 713 - ' ' - 1) 714 << 7); 715 if (ev.x & (1 << 13)) 716 ev.x = 0; 717 ev.y = 718 (unsigned char)(itrm->kqueue 719 [el 720 + 3]) 721 - ' ' - 1 722 + ((int)((unsigned char)(itrm->kqueue 723 [el 724 + 4]) 725 - ' ' - 1) 726 << 7); 727 if (ev.y & (1 << 13)) 728 ev.y = 0; 729 switch ( 730 (itrm->kqueue[el] - ' ') 731 ^ xterm_button) { /* Every 732 event 733 changhes 734 only 735 one bit 736 */ 737 case TW_BUTT_LEFT: 738 ev.b = 739 B_LEFT 740 | ((xterm_button 741 & TW_BUTT_LEFT) 742 ? B_UP 743 : B_DOWN); 744 break; 745 case TW_BUTT_MIDDLE: 746 ev.b = 747 B_MIDDLE 748 | ((xterm_button 749 & TW_BUTT_MIDDLE) 750 ? B_UP 751 : B_DOWN); 752 break; 753 case TW_BUTT_RIGHT: 754 ev.b = 755 B_RIGHT 756 | ((xterm_button 757 & TW_BUTT_RIGHT) 758 ? B_UP 759 : B_DOWN); 760 break; 761 case 0: 762 ev.b = B_DRAG; 763 /* default : Twin 764 * protocol error */ 765 } 766 xterm_button = 767 itrm->kqueue[el] - ' '; 768 el += 5; 769 } else { 770 int x = 0, y = 0, b = 0; 771 int button; 772 unsigned char ch; 773 if (c == 'M') { 774 /* Legacy mouse 775 * protocol: \e[Mbxy 776 * whereas b, x and y 777 * are raw bytes, offset 778 * by 32. */ 779 if (itrm->qlen - el < 3) 780 goto ret; 781 b = itrm->kqueue[el++] 782 - ' '; 783 x = itrm->kqueue[el++] 784 - ' '; 785 y = itrm->kqueue[el++] 786 - ' '; 787 } else if (c == '<') { 788 /* SGR 1006 mouse 789 extension: \e[<b;x;yM 790 where b, x and y are 791 in decimal, no longer 792 offset by 32, and the 793 trailing letter is 794 'm' instead of 'M' 795 for mouse release so 796 that the released 797 button is reported. 798 */ 799 int eel; 800 eel = el; 801 while (1) { 802 if (el 803 == itrm->qlen) 804 goto ret; 805 if (el - eel 806 >= 9) 807 goto l1; 808 ch = 809 itrm->kqueue 810 [el++]; 811 if (ch == ';') 812 break; 813 if (ch < '0' 814 || ch > '9') 815 goto l1; 816 b = 10 * b 817 + (ch 818 - '0'); 819 } 820 eel = el; 821 while (1) { 822 if (el 823 == itrm->qlen) 824 goto ret; 825 if (el - eel 826 >= 9) 827 goto l1; 828 ch = 829 itrm->kqueue 830 [el++]; 831 if (ch == ';') 832 break; 833 if (ch < '0' 834 || ch > '9') 835 goto l1; 836 x = 10 * x 837 + (ch 838 - '0'); 839 } 840 eel = el; 841 while (1) { 842 if (el 843 == itrm->qlen) 844 goto ret; 845 if (el - eel 846 >= 9) 847 goto l1; 848 ch = 849 itrm->kqueue 850 [el++]; 851 if (ch == 'M' 852 || ch == 'm') 853 break; 854 if (ch < '0' 855 || ch > '9') 856 goto l1; 857 y = 10 * y 858 + (ch 859 - '0'); 860 } 861 } else { 862 break; 863 } 864 x--; 865 y--; 866 if (x < 0 || y < 0 || b < 0) 867 break; 868 if (c == 'M' && b == 3) 869 button = B_UP; 870 else if (c == '<' && ch == 'm') 871 button = B_UP; 872 else if ((b & 0x20) == 0x20) 873 button = B_DRAG, 874 b &= ~0x20; 875 else 876 button = B_DOWN; 877 if (b == 0) 878 button |= B_LEFT; 879 else if (b == 1) 880 button |= B_MIDDLE; 881 else if (b == 2) 882 button |= B_RIGHT; 883 else if (b == 3 884 && xterm_button >= 0) 885 button |= xterm_button; 886 else if (b == 0x40) 887 button |= B_WHEELUP; 888 else if (b == 0x41) 889 button |= B_WHEELDOWN; 890 else if (b == 0x42) 891 button |= B_WHEELLEFT; 892 else if (b == 0x43) 893 button |= B_WHEELRIGHT; 894 else if (b == 0x80) 895 button |= B_FOURTH; 896 else if (b == 0x81) 897 button |= B_FIFTH; 898 else if (b == 0x82) 899 button |= B_SIXTH; 900 else 901 break; 902 if ((b == 0x80 || b == 0x81 903 || b == 0x82) 904 && (button & BM_ACT) 905 == B_DOWN 906 && xterm_button 907 == (button 908 & BM_BUTT)) { 909 /* xterm has a bug that 910 * it reports down 911 * events for both click 912 * and release */ 913 button &= ~BM_ACT; 914 button |= B_UP; 915 } 916 if ((button & BM_ACT) == B_DOWN) 917 xterm_button = 918 button & BM_BUTT; 919 if ((button & BM_ACT) == B_UP) 920 xterm_button = -1; 921 ev.b = button; 922 ev.x = x; 923 ev.y = y; 924 } 925 ev.ev = EV_MOUSE; 926 break; 927 } 928 } else { 929 el = 2; 930 if (itrm->kqueue[1] == '\033') { 931 if (itrm->qlen >= 3 932 && (itrm->kqueue[2] == '[' 933 || itrm->kqueue[2] == 'O')) 934 el = 1; 935 ev.x = KBD_ESC; 936 goto l2; 937 } else if (itrm->kqueue[1] == 127) { 938 ev.x = KBD_DEL; 939 ev.y = 0; 940 goto l2; 941 } else { 942 ev.x = itrm->kqueue[1]; 943 ev.y |= KBD_ALT; 944 goto l2; 945 } 946 } 947 goto l1; 948 } else if (itrm->kqueue[0] == 0) { 949 el = 1; 950 goto l1; 951 } 952 el = 1; 953 ev.x = itrm->kqueue[0]; 954 l2: 955 if (ev.x == 3) 956 ev.x = KBD_CTRL_C; 957 if (ev.x == 8) 958 ev.x = KBD_BS; 959 if (ev.x == 9) 960 ev.x = KBD_TAB; 961 if (ev.x == 10) 962 ev.x = KBD_ENTER; 963 if (ev.x == 13) 964 ev.x = KBD_ENTER; 965 if (ev.x == 127) 966 ev.x = KBD_BS; 967 if (ev.x >= 0 && ev.x < ' ') { 968 ev.x += 'A' - 1; 969 ev.y |= KBD_CTRL; 970 } 971 l1: 972 if (itrm->qlen < el) { 973 internal("event queue underflow"); 974 itrm->qlen = el; 975 } 976 if (ev.x != -1) { 977 if (itrm->flags & BRACKETED_PASTE && ev.ev == EV_KBD) 978 ev.y |= KBD_PASTING; 979 itrm->queue_event(itrm, (unsigned char *)&ev, 980 sizeof(struct links_event)); 981 } 982 memmove(itrm->kqueue, itrm->kqueue + el, itrm->qlen -= el); 983 end: 984 if (itrm->qlen < IN_BUF_SIZE && !itrm->blocked) 985 set_handlers(itrm->std_in, in_kbd, NULL, itrm); 986 return el; 987 ret: 988 itrm->tm = install_timer(ESC_TIMEOUT, kbd_timeout, itrm); 989 return 0; 990 } 991 992 static void 993 in_kbd(void *itrm_) 994 { 995 struct itrm *itrm = (struct itrm *)itrm_; 996 int r; 997 if (!can_read(itrm->std_in)) 998 return; 999 if (itrm->tm != NULL) { 1000 kill_timer(itrm->tm); 1001 itrm->tm = NULL; 1002 } 1003 if (itrm->qlen >= IN_BUF_SIZE) { 1004 set_handlers(itrm->std_in, NULL, NULL, itrm); 1005 while (process_queue(itrm)) 1006 ; 1007 return; 1008 } 1009 EINTRLOOP(r, (int)read(itrm->std_in, itrm->kqueue + itrm->qlen, 1010 IN_BUF_SIZE - itrm->qlen)); 1011 if (r <= 0) { 1012 struct links_event ev = { EV_ABORT, 0, 0, 0 }; 1013 set_handlers(itrm->std_in, NULL, NULL, itrm); 1014 itrm->queue_event(itrm, (unsigned char *)&ev, 1015 sizeof(struct links_event)); 1016 return; 1017 } 1018 more_data: 1019 if ((itrm->qlen += r) > IN_BUF_SIZE) { 1020 error("ERROR: too many bytes read"); 1021 itrm->qlen = IN_BUF_SIZE; 1022 } 1023 if (itrm->qlen < IN_BUF_SIZE && can_read(itrm->std_in)) { 1024 EINTRLOOP(r, (int)read(itrm->std_in, itrm->kqueue + itrm->qlen, 1025 IN_BUF_SIZE - itrm->qlen)); 1026 if (r > 0) 1027 goto more_data; 1028 } 1029 while (process_queue(itrm)) 1030 ; 1031 }