1 /* 2 * Copyright 2001-2007, Haiku, Inc. 3 * Copyright (c) 2003-4 Kian Duffy <myob@users.sourceforge.net> 4 * Parts Copyright (C) 1998,99 Kazuho Okui and Takashi Murai. 5 * Distributed under the terms of the MIT license. 6 */ 7 #include "TermParse.h" 8 9 #include "CodeConv.h" 10 #include "TermConst.h" 11 #include "TermView.h" 12 #include "VTparse.h" 13 14 #include <ctype.h> 15 #include <errno.h> 16 #include <stdio.h> 17 #include <signal.h> 18 #include <unistd.h> 19 20 #include <Beep.h> 21 #include <Message.h> 22 23 24 ////////////////////////////////////////////////////////////////////////////// 25 // EscParse ... Escape sequence parse and character encoding. 26 // 27 ////////////////////////////////////////////////////////////////////////////// 28 29 30 extern int gUTF8GroundTable[]; /* UTF8 Ground table */ 31 extern int gCS96GroundTable[]; /* CS96 Ground table */ 32 extern int gISO8859GroundTable[]; /* ISO8859 & EUC Ground table */ 33 extern int gSJISGroundTable[]; /* Shift-JIS Ground table */ 34 35 extern int gEscTable[]; /* ESC */ 36 extern int gCsiTable[]; /* ESC [ */ 37 extern int gDecTable[]; /* ESC [ ? */ 38 extern int gScrTable[]; /* ESC # */ 39 extern int gIgnoreTable[]; /* ignore table */ 40 extern int gIesTable[]; /* ignore ESC table */ 41 extern int gEscIgnoreTable[]; /* ESC ignore table */ 42 extern int gMbcsTable[]; /* ESC $ */ 43 44 45 46 #define DEFAULT -1 47 #define NPARAM 10 // Max parameters 48 49 50 TermParse::TermParse(int fd) 51 : 52 fFd(fd), 53 fParseThread(-1), 54 fReaderThread(-1), 55 fReaderSem(-1), 56 fReaderLocker(-1), 57 fBufferPosition(0), 58 fLockFlag(0), 59 fView(NULL), 60 fQuitting(true) 61 { 62 } 63 64 65 TermParse::~TermParse() 66 { 67 StopThreads(); 68 } 69 70 71 status_t 72 TermParse::StartThreads(TermView *view) 73 { 74 if (fView != NULL) 75 return B_ERROR; 76 77 fQuitting = false; 78 fView = view; 79 80 status_t status = InitPtyReader(); 81 if (status < B_OK) { 82 fView = NULL; 83 return status; 84 } 85 86 status = InitTermParse(); 87 if (status < B_OK) { 88 StopPtyReader(); 89 fView = NULL; 90 return status; 91 } 92 93 return B_OK; 94 } 95 96 97 status_t 98 TermParse::StopThreads() 99 { 100 if (fView == NULL) 101 return B_ERROR; 102 103 fQuitting = true; 104 105 StopPtyReader(); 106 StopTermParse(); 107 108 fView = NULL; 109 110 return B_OK; 111 } 112 113 114 //! Get char from pty reader buffer. 115 status_t 116 TermParse::GetReaderBuf(uchar &c) 117 { 118 status_t status; 119 do { 120 status = acquire_sem_etc(fReaderSem, 1, B_TIMEOUT, 10000); 121 } while (status == B_INTERRUPTED); 122 123 if (status == B_TIMED_OUT) { 124 fView->ScrollAtCursor(); 125 fView->UpdateLine(); 126 127 // Reset cursor blinking time and turn on cursor blinking. 128 fView->SetCurDraw(true); 129 130 // wait new input from pty. 131 do { 132 status = acquire_sem(fReaderSem); 133 } while (status == B_INTERRUPTED); 134 if (status < B_OK) 135 return status; 136 } else if (status == B_OK) { 137 // Do nothing 138 } else 139 return status; 140 141 c = fReadBuffer[fBufferPosition % READ_BUF_SIZE]; 142 fBufferPosition++; 143 // If PtyReader thread locked, decrement counter and unlock thread. 144 if (fLockFlag != 0) { 145 if (--fLockFlag == 0) 146 release_sem(fReaderLocker); 147 } 148 149 fView->SetCurDraw(false); 150 return B_OK; 151 } 152 153 154 //! Initialize and spawn EscParse thread. 155 status_t 156 TermParse::InitTermParse() 157 { 158 if (fParseThread >= 0) 159 return B_ERROR; // we might want to return B_OK instead ? 160 161 fParseThread = spawn_thread(_escparse_thread, "EscParse", 162 B_DISPLAY_PRIORITY, this); 163 164 resume_thread(fParseThread); 165 166 return B_OK; 167 } 168 169 170 //! Initialize and spawn PtyReader thread. 171 status_t 172 TermParse::InitPtyReader() 173 { 174 if (fReaderThread >= 0) 175 return B_ERROR; // same as above 176 177 fReaderSem = create_sem(0, "pty_reader_sem"); 178 if (fReaderSem < 0) 179 return fReaderSem; 180 181 fReaderLocker = create_sem(0, "pty_locker_sem"); 182 if (fReaderLocker < 0) { 183 delete_sem(fReaderSem); 184 fReaderSem = -1; 185 return fReaderLocker; 186 } 187 188 fReaderThread = spawn_thread(_ptyreader_thread, "PtyReader", 189 B_NORMAL_PRIORITY, this); 190 if (fReaderThread < 0) { 191 delete_sem(fReaderSem); 192 fReaderSem = -1; 193 delete_sem(fReaderLocker); 194 fReaderLocker = -1; 195 return fReaderThread; 196 } 197 198 resume_thread(fReaderThread); 199 200 return B_OK; 201 } 202 203 204 void 205 TermParse::StopTermParse() 206 { 207 if (fParseThread >= 0) { 208 status_t dummy; 209 wait_for_thread(fParseThread, &dummy); 210 fParseThread = -1; 211 } 212 } 213 214 215 void 216 TermParse::StopPtyReader() 217 { 218 if (fReaderSem >= 0) { 219 delete_sem(fReaderSem); 220 fReaderSem = -1; 221 } 222 if (fReaderLocker >= 0) { 223 delete_sem(fReaderLocker); 224 fReaderLocker = -1; 225 } 226 227 if (fReaderThread >= 0) { 228 suspend_thread(fReaderThread); 229 230 status_t status; 231 wait_for_thread(fReaderThread, &status); 232 233 fReaderThread = -1; 234 } 235 } 236 237 238 //! Get data from pty device. 239 int32 240 TermParse::PtyReader() 241 { 242 uint read_p = 0; 243 while (!fQuitting) { 244 // If Pty Buffer nearly full, snooze this thread, and continue. 245 if ((read_p - fBufferPosition) > READ_BUF_SIZE - 16) { 246 fLockFlag = READ_BUF_SIZE / 2; 247 status_t status; 248 do { 249 status = acquire_sem(fReaderLocker); 250 } while (status == B_INTERRUPTED); 251 if (status < B_OK) 252 return status; 253 } 254 255 // Read PTY 256 uchar buf[READ_BUF_SIZE]; 257 int nread = read(fFd, buf, READ_BUF_SIZE - (read_p - fBufferPosition)); 258 if (nread <= 0) { 259 fView->NotifyQuit(errno); 260 return B_OK; 261 } 262 263 // Copy read string to PtyBuffer. 264 265 int left = READ_BUF_SIZE - (read_p % READ_BUF_SIZE); 266 int mod = read_p % READ_BUF_SIZE; 267 268 if (nread >= left) { 269 memcpy(fReadBuffer + mod, buf, left); 270 memcpy(fReadBuffer, buf + left, nread - left); 271 } else 272 memcpy(fReadBuffer + mod, buf, nread); 273 274 read_p += nread; 275 276 // Release semaphore. Number of semaphore counter is nread. 277 release_sem_etc(fReaderSem, nread, 0); 278 } 279 280 return B_OK; 281 } 282 283 284 void 285 TermParse::DumpState(int *groundtable, int *parsestate, uchar c) 286 { 287 static const struct { 288 int *p; 289 const char *name; 290 } tables[] = { 291 #define T(t) \ 292 { t, #t } 293 T(gUTF8GroundTable), 294 T(gCS96GroundTable), 295 T(gISO8859GroundTable), 296 T(gSJISGroundTable), 297 T(gEscTable), 298 T(gCsiTable), 299 T(gDecTable), 300 T(gScrTable), 301 T(gIgnoreTable), 302 T(gIesTable), 303 T(gEscIgnoreTable), 304 T(gMbcsTable), 305 { NULL, NULL } 306 }; 307 int i; 308 fprintf(stderr, "groundtable: "); 309 for (i = 0; tables[i].p; i++) 310 if (tables[i].p == groundtable) 311 fprintf(stderr, "%s\t", tables[i].name); 312 fprintf(stderr, "parsestate: "); 313 for (i = 0; tables[i].p; i++) 314 if (tables[i].p == parsestate) 315 fprintf(stderr, "%s\t", tables[i].name); 316 fprintf(stderr, "char: 0x%02x (%d)\n", c, c); 317 } 318 319 320 int32 321 TermParse::EscParse() 322 { 323 int tmp; 324 int top, bot; 325 int cs96 = 0; 326 uchar curess = 0; 327 328 uchar cbuf[4], dstbuf[4]; 329 uchar *ptr; 330 331 int now_coding = -1; 332 333 ushort attr = BACKCOLOR; 334 335 int param[NPARAM]; 336 int nparam = 1; 337 338 int row, col; 339 340 /* default coding system is UTF8 */ 341 int *groundtable = gUTF8GroundTable; 342 int *parsestate = groundtable; 343 344 while (!fQuitting) { 345 uchar c; 346 if (GetReaderBuf(c) < B_OK) 347 break; 348 349 //DumpState(groundtable, parsestate, c); 350 351 if (now_coding != fView->Encoding()) { 352 /* 353 * Change coding, change parse table. 354 */ 355 switch (fView->Encoding()) { 356 case B_ISO1_CONVERSION: 357 case B_ISO2_CONVERSION: 358 case B_ISO3_CONVERSION: 359 case B_ISO4_CONVERSION: 360 case B_ISO5_CONVERSION: 361 case B_ISO6_CONVERSION: 362 case B_ISO7_CONVERSION: 363 case B_ISO8_CONVERSION: 364 case B_ISO9_CONVERSION: 365 case B_ISO10_CONVERSION: 366 groundtable = gISO8859GroundTable; 367 break; 368 case B_SJIS_CONVERSION: 369 groundtable = gSJISGroundTable; 370 break; 371 case B_EUC_CONVERSION: 372 case B_EUC_KR_CONVERSION: 373 case B_JIS_CONVERSION: 374 groundtable = gISO8859GroundTable; 375 break; 376 case M_UTF8: 377 default: 378 groundtable = gUTF8GroundTable; 379 break; 380 } 381 parsestate = groundtable; 382 now_coding = fView->Encoding(); 383 } 384 385 switch (parsestate[c]) { 386 case CASE_PRINT: 387 cbuf[0] = c; 388 cbuf[1] = '\0'; 389 fView->Insert(cbuf, attr); 390 break; 391 392 case CASE_PRINT_GR: 393 /* case iso8859 gr character, or euc */ 394 ptr = cbuf; 395 if (now_coding == B_EUC_CONVERSION || now_coding == B_EUC_KR_CONVERSION 396 || now_coding == B_JIS_CONVERSION) { 397 switch (parsestate[curess]) { 398 case CASE_SS2: /* JIS X 0201 */ 399 *ptr++ = curess; 400 *ptr++ = c; 401 *ptr = 0; 402 curess = 0; 403 break; 404 405 case CASE_SS3: /* JIS X 0212 */ 406 *ptr++ = curess; 407 *ptr++ = c; 408 GetReaderBuf(*ptr++); 409 *ptr = 0; 410 curess = 0; 411 break; 412 413 default: /* JIS X 0208 */ 414 *ptr++ = c; 415 GetReaderBuf(*ptr++); 416 *ptr = 0; 417 break; 418 } 419 } else { 420 /* ISO-8859-1...10 and MacRoman */ 421 *ptr++ = c; 422 *ptr = 0; 423 } 424 425 if (now_coding != B_JIS_CONVERSION) 426 CodeConv::ConvertToInternal((char*)cbuf, -1, (char*)dstbuf, now_coding); 427 else 428 CodeConv::ConvertToInternal((char*)cbuf, -1, (char*)dstbuf, B_EUC_CONVERSION); 429 430 fView->Insert(dstbuf, attr); 431 break; 432 433 case CASE_PRINT_CS96: 434 cbuf[0] = c | 0x80; 435 GetReaderBuf(cbuf[1]); 436 cbuf[1] |= 0x80; 437 cbuf[2] = 0; 438 CodeConv::ConvertToInternal((char*)cbuf, 2, (char*)dstbuf, B_EUC_CONVERSION); 439 fView->Insert(dstbuf, attr); 440 break; 441 442 case CASE_LF: 443 fView->InsertLF(); 444 break; 445 446 case CASE_CR: 447 fView->InsertCR(); 448 break; 449 450 case CASE_SJIS_KANA: 451 cbuf[0] = (uchar)c; 452 cbuf[1] = '\0'; 453 CodeConv::ConvertToInternal((char*)cbuf, 1, (char*)dstbuf, now_coding); 454 fView->Insert(dstbuf, attr); 455 break; 456 457 case CASE_SJIS_INSTRING: 458 cbuf[0] = (uchar)c; 459 GetReaderBuf(cbuf[1]); 460 cbuf[2] = '\0'; 461 CodeConv::ConvertToInternal((char*)cbuf, 2, (char*)dstbuf, now_coding); 462 fView->Insert(dstbuf, attr); 463 break; 464 465 case CASE_UTF8_2BYTE: 466 cbuf[0] = (uchar)c; 467 GetReaderBuf(c); 468 if (groundtable[c] != CASE_UTF8_INSTRING) 469 break; 470 cbuf[1] = (uchar)c; 471 cbuf[2] = '\0'; 472 473 fView->Insert(cbuf, attr); 474 break; 475 476 case CASE_UTF8_3BYTE: 477 cbuf[0] = c; 478 GetReaderBuf(c); 479 if (groundtable[c] != CASE_UTF8_INSTRING) 480 break; 481 cbuf[1] = c; 482 483 GetReaderBuf(c); 484 if (groundtable[c] != CASE_UTF8_INSTRING) 485 break; 486 cbuf[2] = c; 487 cbuf[3] = '\0'; 488 fView->Insert(cbuf, attr); 489 break; 490 491 case CASE_MBCS: 492 /* ESC $ */ 493 parsestate = gMbcsTable; 494 break; 495 496 case CASE_GSETS: 497 /* ESC $ ? */ 498 parsestate = gCS96GroundTable; 499 cs96 = 1; 500 break; 501 502 case CASE_SCS_STATE: 503 { 504 cs96 = 0; 505 uchar dummy; 506 GetReaderBuf(dummy); 507 parsestate = groundtable; 508 break; 509 } 510 case CASE_GROUND_STATE: 511 /* exit ignore mode */ 512 parsestate = groundtable; 513 break; 514 515 case CASE_BELL: 516 beep(); 517 break; 518 519 case CASE_BS: 520 fView->MoveCurLeft(1); 521 break; 522 523 case CASE_TAB: 524 tmp = fView->GetCurX(); 525 tmp %= 8; 526 fView->MoveCurRight(8 - tmp); 527 break; 528 529 case CASE_ESC: 530 /* escape */ 531 parsestate = gEscTable; 532 break; 533 534 case CASE_IGNORE_STATE: 535 /* Ies: ignore anything else */ 536 parsestate = gIgnoreTable; 537 break; 538 539 case CASE_IGNORE_ESC: 540 /* Ign: escape */ 541 parsestate = gIesTable; 542 break; 543 544 case CASE_IGNORE: 545 /* Ignore character */ 546 break; 547 548 case CASE_SI: 549 break; 550 551 case CASE_SO: 552 break; 553 554 case CASE_SCR_STATE: // ESC # 555 /* enter scr state */ 556 parsestate = gScrTable; 557 break; 558 559 case CASE_ESC_IGNORE: 560 /* unknown escape sequence */ 561 parsestate = gEscIgnoreTable; 562 break; 563 564 case CASE_ESC_DIGIT: // ESC [ number 565 /* digit in csi or dec mode */ 566 if ((row = param[nparam - 1]) == DEFAULT) 567 row = 0; 568 param[nparam - 1] = 10 * row + (c - '0'); 569 break; 570 571 case CASE_ESC_SEMI: // ESC ; 572 /* semicolon in csi or dec mode */ 573 if (nparam < NPARAM) 574 param[nparam++] = DEFAULT; 575 break; 576 577 case CASE_DEC_STATE: 578 /* enter dec mode */ 579 parsestate = gDecTable; 580 break; 581 582 case CASE_ICH: // ESC [@ insert charactor 583 /* ICH */ 584 if ((row = param[0]) < 1) 585 row = 1; 586 fView->InsertSpace(row); 587 parsestate = groundtable; 588 break; 589 590 case CASE_CUU: // ESC [A cursor up, up arrow key. 591 /* CUU */ 592 if ((row = param[0]) < 1) 593 row = 1; 594 fView->MoveCurUp(row); 595 parsestate = groundtable; 596 break; 597 598 case CASE_CUD: // ESC [B cursor down, down arrow key. 599 /* CUD */ 600 if ((row = param[0]) < 1) 601 row = 1; 602 fView->MoveCurDown(row); 603 parsestate = groundtable; 604 break; 605 606 case CASE_CUF: // ESC [C cursor forword 607 /* CUF */ 608 if ((row = param[0]) < 1) 609 row = 1; 610 fView->MoveCurRight(row); 611 parsestate = groundtable; 612 break; 613 614 case CASE_CUB: // ESC [D cursor backword 615 /* CUB */ 616 if ((row = param[0]) < 1) 617 row = 1; 618 fView->MoveCurLeft(row); 619 parsestate = groundtable; 620 break; 621 622 case CASE_CUP: // ESC [...H move cursor 623 /* CUP | HVP */ 624 if ((row = param[0]) < 1) 625 row = 1; 626 if (nparam < 2 || (col = param[1]) < 1) 627 col = 1; 628 629 fView->SetCurPos(col - 1, row - 1 ); 630 parsestate = groundtable; 631 break; 632 633 case CASE_ED: // ESC [ ...J clear screen 634 /* ED */ 635 switch (param[0]) { 636 case DEFAULT: 637 case 0: 638 fView->EraseBelow(); 639 break; 640 641 case 1: 642 break; 643 644 case 2: 645 fView->SetCurPos(0, 0); 646 fView->EraseBelow(); 647 break; 648 } 649 parsestate = groundtable; 650 break; 651 652 case CASE_EL: // delete line 653 /* EL */ 654 fView->DeleteColumns(); 655 parsestate = groundtable; 656 break; 657 658 case CASE_IL: 659 /* IL */ 660 if ((row = param[0]) < 1) 661 row = 1; 662 fView->InsertNewLine(row); 663 parsestate = groundtable; 664 break; 665 666 case CASE_DL: 667 /* DL */ 668 if ((row = param[0]) < 1) 669 row = 1; 670 fView->DeleteLine(row); 671 parsestate = groundtable; 672 break; 673 674 case CASE_DCH: 675 /* DCH */ 676 if ((row = param[0]) < 1) 677 row = 1; 678 fView->DeleteChar(row); 679 parsestate = groundtable; 680 break; 681 682 case CASE_SET: 683 /* SET */ 684 fView->SetInsertMode(MODE_INSERT); 685 parsestate = groundtable; 686 break; 687 688 case CASE_RST: 689 /* RST */ 690 fView->SetInsertMode(MODE_OVER); 691 parsestate = groundtable; 692 break; 693 694 case CASE_SGR: 695 /* SGR */ 696 for (row = 0; row < nparam; ++row) { 697 switch (param[row]) { 698 case DEFAULT: 699 case 0: /* Reset attribute */ 700 attr = 0; 701 break; 702 703 case 1: 704 case 5: /* Bold */ 705 attr |= BOLD; 706 break; 707 708 case 4: /* Underline */ 709 attr |= UNDERLINE; 710 break; 711 712 case 7: /* Inverse */ 713 attr |= INVERSE; 714 break; 715 716 case 22: /* Not Bold */ 717 attr &= ~BOLD; 718 break; 719 720 case 24: /* Not Underline */ 721 attr &= ~UNDERLINE; 722 break; 723 724 case 27: /* Not Inverse */ 725 attr &= ~INVERSE; 726 break; 727 728 case 30: 729 case 31: 730 case 32: 731 case 33: 732 case 34: 733 case 35: 734 case 36: 735 case 37: 736 attr &= ~FORECOLOR; 737 attr |= FORECOLORED(param[row] - 30); 738 attr |= FORESET; 739 break; 740 741 case 39: 742 attr &= ~FORESET; 743 break; 744 745 case 40: 746 case 41: 747 case 42: 748 case 43: 749 case 44: 750 case 45: 751 case 46: 752 case 47: 753 attr &= ~BACKCOLOR; 754 attr |= BACKCOLORED(param[row] - 40); 755 attr |= BACKSET; 756 break; 757 758 case 49: 759 attr &= ~BACKSET; 760 break; 761 } 762 } 763 parsestate = groundtable; 764 break; 765 766 case CASE_CPR: 767 // Q & D hack by Y.Hayakawa (hida@sawada.riec.tohoku.ac.jp) 768 // 21-JUL-99 769 fView->DeviceStatusReport(param[0]); 770 parsestate = groundtable; 771 break; 772 773 case CASE_DECSTBM: 774 /* DECSTBM - set scrolling region */ 775 776 if ((top = param[0]) < 1) 777 top = 1; 778 779 if (nparam < 2) 780 bot = -1; 781 else 782 bot = param[1]; 783 784 top--; 785 bot--; 786 787 if (bot > top) 788 fView->SetScrollRegion(top, bot); 789 790 parsestate = groundtable; 791 break; 792 793 case CASE_DECREQTPARM: 794 parsestate = groundtable; 795 break; 796 797 case CASE_DECSET: 798 /* DECSET */ 799 // dpmodes(term, bitset); 800 parsestate = groundtable; 801 break; 802 803 case CASE_DECRST: 804 /* DECRST */ 805 // dpmodes(term, bitclr); 806 parsestate = groundtable; 807 break; 808 809 case CASE_DECALN: 810 /* DECALN */ 811 // if(screen->cursor_state) 812 // HideCursor(); 813 // ScrnRefresh(screen, 0, 0, screen->max_row + 1, 814 // screen->max_col + 1, False); 815 parsestate = groundtable; 816 break; 817 818 // case CASE_GSETS: 819 // screen->gsets[scstype] = GSET(c) | cs96; 820 // parsestate = groundtable; 821 // break; 822 823 case CASE_DECSC: 824 /* DECSC */ 825 fView->SaveCursor(); 826 parsestate = groundtable; 827 break; 828 829 case CASE_DECRC: 830 /* DECRC */ 831 fView->RestoreCursor(); 832 parsestate = groundtable; 833 break; 834 835 case CASE_HTS: 836 /* HTS */ 837 // TabSet(term->tabs, screen->cur_col); 838 parsestate = groundtable; 839 break; 840 841 case CASE_RI: 842 /* RI */ 843 fView->ScrollRegion(-1, -1, SCRDOWN, 1); 844 parsestate = groundtable; 845 break; 846 847 case CASE_SS2: 848 /* SS2 */ 849 curess = c; 850 parsestate = groundtable; 851 break; 852 853 case CASE_SS3: 854 /* SS3 */ 855 curess = c; 856 parsestate = groundtable; 857 break; 858 859 case CASE_CSI_STATE: 860 /* enter csi state */ 861 nparam = 1; 862 param[0] = DEFAULT; 863 parsestate = gCsiTable; 864 break; 865 866 case CASE_OSC: 867 { 868 /* Operating System Command: ESC ] */ 869 char string[512]; 870 uint32 len = 0; 871 uchar mode_char; 872 GetReaderBuf(mode_char); 873 if (mode_char != '0' 874 && mode_char != '1' 875 && mode_char != '2') { 876 parsestate = groundtable; 877 break; 878 } 879 uchar current_char; 880 GetReaderBuf(current_char); 881 while (GetReaderBuf(current_char) == B_OK 882 && current_char != 0x7) { 883 if (!isprint(current_char & 0x7f) 884 || len+2 >= sizeof(string)) 885 break; 886 string[len++] = current_char; 887 } 888 if (current_char == 0x7) { 889 string[len] = '\0'; 890 switch (mode_char) { 891 case '0': 892 case '2': 893 fView->SetTitle(string); 894 break; 895 case '1': 896 break; 897 } 898 } 899 parsestate = groundtable; 900 break; 901 } 902 903 case CASE_RIS: // ESC c ... Reset terminal. 904 break; 905 906 case CASE_LS2: 907 /* LS2 */ 908 // screen->curgl = 2; 909 parsestate = groundtable; 910 break; 911 912 case CASE_LS3: 913 /* LS3 */ 914 // screen->curgl = 3; 915 parsestate = groundtable; 916 break; 917 918 case CASE_LS3R: 919 /* LS3R */ 920 // screen->curgr = 3; 921 parsestate = groundtable; 922 break; 923 924 case CASE_LS2R: 925 /* LS2R */ 926 // screen->curgr = 2; 927 parsestate = groundtable; 928 break; 929 930 case CASE_LS1R: 931 /* LS1R */ 932 // screen->curgr = 1; 933 parsestate = groundtable; 934 break; 935 936 case CASE_VPA: // ESC [...d move cursor absolute vertical 937 /* VPA (CV) */ 938 if ((row = param[0]) < 1) 939 row = 1; 940 941 // note beterm wants it 1-based unlike usual terminals 942 fView->SetCurY(row - 1); 943 parsestate = groundtable; 944 break; 945 946 case CASE_HPA: // ESC [...G move cursor absolute horizontal 947 /* HPA (CH) */ 948 if ((col = param[0]) < 1) 949 col = 1; 950 951 // note beterm wants it 1-based unlike usual terminals 952 fView->SetCurX(col - 1); 953 parsestate = groundtable; 954 break; 955 956 default: 957 break; 958 } 959 } 960 961 return B_OK; 962 } 963 964 965 /*static*/ int32 966 TermParse::_ptyreader_thread(void *data) 967 { 968 return reinterpret_cast<TermParse *>(data)->PtyReader(); 969 } 970 971 972 /*static*/ int32 973 TermParse::_escparse_thread(void *data) 974 { 975 return reinterpret_cast<TermParse *>(data)->EscParse(); 976 } 977