📄 tty.c
字号:
12348 /* Leftover characters in the buffer. */
12349 count = bp - buf;
12350 phys_copy(buf_phys, user_base + tp->tty_in_vir, (phys_bytes) count);
12351 tp->tty_in_vir += count;
12352 tp->tty_incum += count;
12353 }
12354
12355 /* Usually reply to the reader, possibly even if incum == 0 (EOF). */
12356 if (tp->tty_inleft == 0) {
12357 tty_reply(tp->tty_inrepcode, tp->tty_incaller, tp->tty_inproc,
12358 tp->tty_incum);
12359 tp->tty_inleft = tp->tty_incum = 0;
12360 }
12361 }
12364 /*===========================================================================*
12365 * in_process *
12366 *===========================================================================*/
12367 PUBLIC int in_process(tp, buf, count)
12368 register tty_t *tp; /* terminal on which character has arrived */
12369 char *buf; /* buffer with input characters */
12370 int count; /* number of input characters */
12371 {
12372 /* Characters have just been typed in. Process, save, and echo them. Return
12373 * the number of characters processed.
12374 */
12375
12376 int ch, sig, ct;
12377 int timeset = FALSE;
12378 static unsigned char csize_mask[] = { 0x1F, 0x3F, 0x7F, 0xFF };
12379
12380 for (ct = 0; ct < count; ct++) {
12381 /* Take one character. */
12382 ch = *buf++ & BYTE;
12383
12384 /* Strip to seven bits? */
12385 if (tp->tty_termios.c_iflag & ISTRIP) ch &= 0x7F;
12386
12387 /* Input extensions? */
12388 if (tp->tty_termios.c_lflag & IEXTEN) {
12389
12390 /* Previous character was a character escape? */
12391 if (tp->tty_escaped) {
12392 tp->tty_escaped = NOT_ESCAPED;
12393 ch |= IN_ESC; /* protect character */
12394 }
12395
12396 /* LNEXT (^V) to escape the next character? */
12397 if (ch == tp->tty_termios.c_cc[VLNEXT]) {
12398 tp->tty_escaped = ESCAPED;
12399 rawecho(tp, '^');
12400 rawecho(tp, '\b');
12401 continue; /* do not store the escape */
12402 }
12403
12404 /* REPRINT (^R) to reprint echoed characters? */
12405 if (ch == tp->tty_termios.c_cc[VREPRINT]) {
12406 reprint(tp);
12407 continue;
12408 }
12409 }
12410
12411 /* _POSIX_VDISABLE is a normal character value, so better escape it. */
12412 if (ch == _POSIX_VDISABLE) ch |= IN_ESC;
12413
12414 /* Map CR to LF, ignore CR, or map LF to CR. */
12415 if (ch == '\r') {
12416 if (tp->tty_termios.c_iflag & IGNCR) continue;
12417 if (tp->tty_termios.c_iflag & ICRNL) ch = '\n';
12418 } else
12419 if (ch == '\n') {
12420 if (tp->tty_termios.c_iflag & INLCR) ch = '\r';
12421 }
12422
12423 /* Canonical mode? */
12424 if (tp->tty_termios.c_lflag & ICANON) {
12425
12426 /* Erase processing (rub out of last character). */
12427 if (ch == tp->tty_termios.c_cc[VERASE]) {
12428 (void) back_over(tp);
12429 if (!(tp->tty_termios.c_lflag & ECHOE)) {
12430 (void) echo(tp, ch);
12431 }
12432 continue;
12433 }
12434
12435 /* Kill processing (remove current line). */
12436 if (ch == tp->tty_termios.c_cc[VKILL]) {
12437 while (back_over(tp)) {}
12438 if (!(tp->tty_termios.c_lflag & ECHOE)) {
12439 (void) echo(tp, ch);
12440 if (tp->tty_termios.c_lflag & ECHOK)
12441 rawecho(tp, '\n');
12442 }
12443 continue;
12444 }
12445
12446 /* EOF (^D) means end-of-file, an invisible "line break". */
12447 if (ch == tp->tty_termios.c_cc[VEOF]) ch |= IN_EOT | IN_EOF;
12448
12449 /* The line may be returned to the user after an LF. */
12450 if (ch == '\n') ch |= IN_EOT;
12451
12452 /* Same thing with EOL, whatever it may be. */
12453 if (ch == tp->tty_termios.c_cc[VEOL]) ch |= IN_EOT;
12454 }
12455
12456 /* Start/stop input control? */
12457 if (tp->tty_termios.c_iflag & IXON) {
12458
12459 /* Output stops on STOP (^S). */
12460 if (ch == tp->tty_termios.c_cc[VSTOP]) {
12461 tp->tty_inhibited = STOPPED;
12462 tp->tty_events = 1;
12463 continue;
12464 }
12465
12466 /* Output restarts on START (^Q) or any character if IXANY. */
12467 if (tp->tty_inhibited) {
12468 if (ch == tp->tty_termios.c_cc[VSTART]
12469 || (tp->tty_termios.c_iflag & IXANY)) {
12470 tp->tty_inhibited = RUNNING;
12471 tp->tty_events = 1;
12472 if (ch == tp->tty_termios.c_cc[VSTART])
12473 continue;
12474 }
12475 }
12476 }
12477
12478 if (tp->tty_termios.c_lflag & ISIG) {
12479 /* Check for INTR (^?) and QUIT (^\) characters. */
12480 if (ch == tp->tty_termios.c_cc[VINTR]
12481 || ch == tp->tty_termios.c_cc[VQUIT]) {
12482 sig = SIGINT;
12483 if (ch == tp->tty_termios.c_cc[VQUIT]) sig = SIGQUIT;
12484 sigchar(tp, sig);
12485 (void) echo(tp, ch);
12486 continue;
12487 }
12488 }
12489
12490 /* Is there space in the input buffer? */
12491 if (tp->tty_incount == buflen(tp->tty_inbuf)) {
12492 /* No space; discard in canonical mode, keep in raw mode. */
12493 if (tp->tty_termios.c_lflag & ICANON) continue;
12494 break;
12495 }
12496
12497 if (!(tp->tty_termios.c_lflag & ICANON)) {
12498 /* In raw mode all characters are "line breaks". */
12499 ch |= IN_EOT;
12500
12501 /* Start an inter-byte timer? */
12502 if (!timeset && tp->tty_termios.c_cc[VMIN] > 0
12503 && tp->tty_termios.c_cc[VTIME] > 0) {
12504 lock();
12505 settimer(tp, TRUE);
12506 unlock();
12507 timeset = TRUE;
12508 }
12509 }
12510
12511 /* Perform the intricate function of echoing. */
12512 if (tp->tty_termios.c_lflag & (ECHO|ECHONL)) ch = echo(tp, ch);
12513
12514 /* Save the character in the input queue. */
12515 *tp->tty_inhead++ = ch;
12516 if (tp->tty_inhead == bufend(tp->tty_inbuf))
12517 tp->tty_inhead = tp->tty_inbuf;
12518 tp->tty_incount++;
12519 if (ch & IN_EOT) tp->tty_eotct++;
12520
12521 /* Try to finish input if the queue threatens to overflow. */
12522 if (tp->tty_incount == buflen(tp->tty_inbuf)) in_transfer(tp);
12523 }
12524 return ct;
12525 }
12528 /*===========================================================================*
12529 * echo *
12530 *===========================================================================*/
12531 PRIVATE int echo(tp, ch)
12532 register tty_t *tp; /* terminal on which to echo */
12533 register int ch; /* pointer to character to echo */
12534 {
12535 /* Echo the character if echoing is on. Some control characters are echoed
12536 * with their normal effect, other control characters are echoed as "^X",
12537 * normal characters are echoed normally. EOF (^D) is echoed, but immediately
12538 * backspaced over. Return the character with the echoed length added to its
12539 * attributes.
12540 */
12541 int len, rp;
12542
12543 ch &= ~IN_LEN;
12544 if (!(tp->tty_termios.c_lflag & ECHO)) {
12545 if (ch == ('\n' | IN_EOT) && (tp->tty_termios.c_lflag
12546 & (ICANON|ECHONL)) == (ICANON|ECHONL))
12547 (*tp->tty_echo)(tp, '\n');
12548 return(ch);
12549 }
12550
12551 /* "Reprint" tells if the echo output has been messed up by other output. */
12552 rp = tp->tty_incount == 0 ? FALSE : tp->tty_reprint;
12553
12554 if ((ch & IN_CHAR) < ' ') {
12555 switch (ch & (IN_ESC|IN_EOF|IN_EOT|IN_CHAR)) {
12556 case '\t':
12557 len = 0;
12558 do {
12559 (*tp->tty_echo)(tp, ' ');
12560 len++;
12561 } while (len < TAB_SIZE && (tp->tty_position & TAB_MASK) != 0);
12562 break;
12563 case '\r' | IN_EOT:
12564 case '\n' | IN_EOT:
12565 (*tp->tty_echo)(tp, ch & IN_CHAR);
12566 len = 0;
12567 break;
12568 default:
12569 (*tp->tty_echo)(tp, '^');
12570 (*tp->tty_echo)(tp, '@' + (ch & IN_CHAR));
12571 len = 2;
12572 }
12573 } else
12574 if ((ch & IN_CHAR) == '\177') {
12575 /* A DEL prints as "^?". */
12576 (*tp->tty_echo)(tp, '^');
12577 (*tp->tty_echo)(tp, '?');
12578 len = 2;
12579 } else {
12580 (*tp->tty_echo)(tp, ch & IN_CHAR);
12581 len = 1;
12582 }
12583 if (ch & IN_EOF) while (len > 0) { (*tp->tty_echo)(tp, '\b'); len--; }
12584
12585 tp->tty_reprint = rp;
12586 return(ch | (len << IN_LSHIFT));
12587 }
12590 /*==========================================================================*
12591 * rawecho *
12592 *==========================================================================*/
12593 PRIVATE void rawecho(tp, ch)
12594 register tty_t *tp;
12595 int ch;
12596 {
12597 /* Echo without interpretation if ECHO is set. */
12598 int rp = tp->tty_reprint;
12599 if (tp->tty_termios.c_lflag & ECHO) (*tp->tty_echo)(tp, ch);
12600 tp->tty_reprint = rp;
12601 }
12604 /*==========================================================================*
12605 * back_over *
12606 *==========================================================================*/
12607 PRIVATE int back_over(tp)
12608 register tty_t *tp;
12609 {
12610 /* Backspace to previous character on screen and erase it. */
12611 u16_t *head;
12612 int len;
12613
12614 if (tp->tty_incount == 0) return(0); /* queue empty */
12615 head = tp->tty_inhead;
12616 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
12617 if (*--head & IN_EOT) return(0); /* can't erase "line breaks" */
12618 if (tp->tty_reprint) reprint(tp); /* reprint if messed up */
12619 tp->tty_inhead = head;
12620 tp->tty_incount--;
12621 if (tp->tty_termios.c_lflag & ECHOE) {
12622 len = (*head & IN_LEN) >> IN_LSHIFT;
12623 while (len > 0) {
12624 rawecho(tp, '\b');
12625 rawecho(tp, ' ');
12626 rawecho(tp, '\b');
12627 len--;
12628 }
12629 }
12630 return(1); /* one character erased */
12631 }
12634 /*==========================================================================*
12635 * reprint *
12636 *==========================================================================*/
12637 PRIVATE void reprint(tp)
12638 register tty_t *tp; /* pointer to tty struct */
12639 {
12640 /* Restore what has been echoed to screen before if the user input has been
12641 * messed up by output, or if REPRINT (^R) is typed.
12642 */
12643 int count;
12644 u16_t *head;
12645
12646 tp->tty_reprint = FALSE;
12647
12648 /* Find the last line break in the input. */
12649 head = tp->tty_inhead;
12650 count = tp->tty_incount;
12651 while (count > 0) {
12652 if (head == tp->tty_inbuf) head = bufend(tp->tty_inbuf);
12653 if (head[-1] & IN_EOT) break;
12654 head--;
12655 count--;
12656 }
12657 if (count == tp->tty_incount) return; /* no reason to reprint */
12658
12659 /* Show REPRINT (^R) and move to a new line. */
12660 (void) echo(tp, tp->tty_termios.c_cc[VREPRINT] | IN_ESC);
12661 rawecho(tp, '\r');
12662 rawecho(tp, '\n');
12663
12664 /* Reprint from the last break onwards. */
12665 do {
12666 if (head == bufend(tp->tty_inbuf)) head = tp->tty_inbuf;
12667 *head = echo(tp, *head);
12668 head++;
12669 count++;
12670 } while (count < tp->tty_incount);
12671 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -