hedrick@athos.rutgers.edu (Charles Hedrick) (09/04/88)
Here are a few more tty-related changes. You must have installed my previous tty diffs. As far as I know, only the insert-delete char depends upon them, so you should be able to take the other changes from this file alone if you are interested in one of them specifically. (That is possible, since lots of people have asked for line wrap.) - removing locks from at_wini and xt_wini. (Yet another attempt to avoid losing RS232 input characters. These are from brucee. I'm fairly confident of the patches to at_wini. I have no way to check the patches for xt_wini, but Bruce believes they are right.) - allow you to type null's on the console. Don't turn nulls into ^D. There was a basic design problem in handling nulls. It's not possible to fix it completely, but after my changes, the only problem is that you won't be able to generate 0200 from the console keyboard when in cooked mode. I believe that's not going to be a problem. In raw or cbreak mode, you will be able to (if you can figure out the right combination of shift and control keys). - added line wrap. That is, when output is too long for a line it will go onto a new line. This is the simple form. When you put a character in the last position on the line, the cursor goes to the next line. So if you put out lines of exactly 80 chars, you'll get an extra blank line between them. It's possible to keep this from happening by creating a phantom 81-st position on the line, but that complicates the code and in my opinion doesn't gain enough to make it worth doing. Some real terminals seem to do it each way. - added insert/delete character ANSI escape codes. Tested only on EGA with my hardware scrolling, but I don't think there will be problems with other configurations. ESC [ n @ inserts n blanks at the cursor, moving the right of the line to the right. ESC [ n P deletes the next n characters starting at the cursor, filling the right end of the line with blanks. Here are Unix termcap entries to describe the result. This assumes that color users are running with black on white characters and monochrome with white on black. This is probably a reasonable assumption, since most monochrome monitors are amber or green, and black on green looks really wierd. However with a good color monitor, black on white is noticably more readable than white on black. (To go into black on white mode, use \E[30m\E[47m, where \E represents "escape" (octal 33).) In|minix|minix console support for color monitor:\ :do=^J:up=^K:co#80:li#25:am:cl=\E[;H\E[J:\ :al=\E[L:dl=\E[M:AL=\E[%dL:DL=\E[%dM:\ :ic=\E[@:dc=\E[P:IC=\E[%d@:DC=\E[%dP:\ :le=^H:nd=^N:bs:am:cm=\E[%i%d;%dH:\ :ce=\E[K:cd=\E[J:so=\E[42m:se=\E[47m:us=\E[4m:ue=\E[m:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[0m\E[47m:\ :ho=\E[H: Im|minix-bw|minix console support for monochrome monitor:\ :do=^J:up=^K:co#80:li#25:am:cl=\E[;H\E[J:\ :al=\E[L:dl=\E[M:AL=\E[%dL:DL=\E[%dM:\ :ic=\E[@:dc=\E[P:IC=\E[%d@:DC=\E[%dP:\ :le=^H:nd=^N:bs:am:cm=\E[%i%d;%dH:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[m:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[0m:\ :ho=\E[H: *** at_wini.c.ORIG Thu Jan 1 00:11:21 1970 --- at_wini.c Thu Sep 1 06:00:34 1988 *************** *** 212,220 **** if (wn->wn_opcode == DISK_READ) { for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) { receive(HARDWARE, &w_mess); ! old_state = lock(); ! dma_read((unsigned)(usr_buf >> 4), (unsigned)(usr_buf & 0x0F)); ! restore(old_state); usr_buf += 0x200; if (win_results() != OK) { w_need_reset = TRUE; --- 212,220 ---- if (wn->wn_opcode == DISK_READ) { for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) { receive(HARDWARE, &w_mess); ! /* old_state = lock(); */ ! dma_read((unsigned)(usr_buf >> 4), (unsigned)(usr_buf & 0x0F)); ! /* restore(old_state); */ usr_buf += 0x200; if (win_results() != OK) { w_need_reset = TRUE; *************** *** 230,238 **** return(ERR); } for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) { ! old_state = lock(); ! dma_write((unsigned)(usr_buf >> 4), (unsigned)(usr_buf&0x0F)); ! restore(old_state); usr_buf += 0x200; receive(HARDWARE, &w_mess); if (win_results() != OK) { --- 230,238 ---- return(ERR); } for (i=0; i<BLOCK_SIZE/SECTOR_SIZE; i++) { ! /* old_state = lock(); */ ! dma_write((unsigned)(usr_buf >> 4), (unsigned)(usr_buf&0x0F)); ! /* restore(old_state); */ usr_buf += 0x200; receive(HARDWARE, &w_mess); if (win_results() != OK) { *** xt_wini.c.ORIG Thu Jan 1 00:12:15 1970 --- xt_wini.c Thu Sep 1 06:02:15 1988 *************** *** 615,621 **** } ! old_state = lock(); for (i=0; i<6; i++) { if(hd_wait(WST_REQ) != OK) --- 615,621 ---- } ! /* old_state = lock(); */ for (i=0; i<6; i++) { if(hd_wait(WST_REQ) != OK) *************** *** 630,636 **** port_out(WIN_DATA, command[i]); } ! restore(old_state); if(i != 6) { return(ERR); --- 630,636 ---- port_out(WIN_DATA, command[i]); } ! /* restore(old_state); */ if(i != 6) { return(ERR); *** tty.c.HOLD Thu Jan 1 00:11:12 1970 --- tty.c Fri Sep 2 00:18:26 1988 *************** *** 74,81 **** #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */ #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */ #define EOT_CHAR (char) 004 /* CTRL-D */ ! #define MARKER (char) 000 /* non-escaped CTRL-D stored as MARKER */ ! #define AT_SIGN 0200 /* code to yield for CTRL-@ */ #define SCODE1 71 /* scan code for Home on numeric pad */ #define SCODE2 81 /* scan code for PgDn on numeric pad */ #define DEL_CODE (char) 83 /* DEL for use in CTRL-ALT-DEL reboot */ --- 74,89 ---- #define XOFF_CHAR (char) 023 /* default x-off character (CTRL-S) */ #define XON_CHAR (char) 021 /* default x-on character (CTRL-Q) */ #define EOT_CHAR (char) 004 /* CTRL-D */ ! /* ! * This MARKER is used as an unambiguous flag for an unescaped end of ! * file character. It is meaningful only in cooked mode. That's ! * fairly safe because cooked mode isn't supposed to return things ! * with the high-order bit on anyway. Be careful that code only checks ! * for MARKER in cooked mode. This kludge is needed because ! * chars are stored in char arrays, so there's no way to have a ! * completely out of band value. ! */ ! #define MARKER (char) 0200 /* non-escaped CTRL-D stored as MARKER */ #define SCODE1 71 /* scan code for Home on numeric pad */ #define SCODE2 81 /* scan code for PgDn on numeric pad */ #define DEL_CODE (char) 83 /* DEL for use in CTRL-ALT-DEL reboot */ *************** *** 389,396 **** /* A character has just been typed in. Process, save, and echo it. */ register struct tty_struct *tp; ! int mode, sig, scode; ! char make_break(); scode = ch; /* save the scan code */ tp = &tty_struct[line]; /* set 'tp' to point to proper struct */ --- 397,404 ---- /* A character has just been typed in. Process, save, and echo it. */ register struct tty_struct *tp; ! int mode, sig, scode, c; ! int make_break(); scode = ch; /* save the scan code */ tp = &tty_struct[line]; /* set 'tp' to point to proper struct */ *************** *** 403,410 **** if (tp->tty_incount >= TTY_IN_BYTES) return; /* no room, discard char */ mode = tp->tty_mode & (RAW | CBREAK); if (tp->tty_makebreak == TWO_INTS) { ! ch = make_break(ch); /* console give 2 ints/ch */ ! if (ch == 0) return; } else if (mode != RAW) ch &= 0177; /* 7-bit chars except in raw mode */ --- 411,419 ---- if (tp->tty_incount >= TTY_IN_BYTES) return; /* no room, discard char */ mode = tp->tty_mode & (RAW | CBREAK); if (tp->tty_makebreak == TWO_INTS) { ! c = make_break(ch); /* console give 2 ints/ch */ ! if (c == -1) return; ! ch = c; } else if (mode != RAW) ch &= 0177; /* 7-bit chars except in raw mode */ *************** *** 445,451 **** * line feed in terms of knowing whether a full line * has been typed already. */ ! if (ch == tp->tty_eof) ch = MARKER; } else { /* Previous character was backslash. */ tp->tty_escaped = NOT_ESCAPED; /* turn escaping off */ --- 454,463 ---- * line feed in terms of knowing whether a full line * has been typed already. */ ! if (ch == tp->tty_eof) { ! ch = MARKER; ! tp->tty_lfct++; /* counts as LF */ ! } } else { /* Previous character was backslash. */ tp->tty_escaped = NOT_ESCAPED; /* turn escaping off */ *************** *** 485,491 **** } /* All 3 modes come here. */ ! if (ch == '\n' || ch == MARKER) tp->tty_lfct++; /* count line feeds */ /* The numeric pad generates ASCII escape sequences: ESC [ letter */ if (line == 0 && scode >= SCODE1 && scode <= SCODE2 && --- 497,503 ---- } /* All 3 modes come here. */ ! if (ch == '\n') tp->tty_lfct++; /* count line feeds */ /* The numeric pad generates ASCII escape sequences: ESC [ letter */ if (line == 0 && scode >= SCODE1 && scode <= SCODE2 && *************** *** 516,522 **** /*===========================================================================* * make_break * *===========================================================================*/ ! PRIVATE char make_break(ch) char ch; /* scan code of key just struck or released */ { /* This routine can handle keyboards that interrupt only on key depression, --- 528,534 ---- /*===========================================================================* * make_break * *===========================================================================*/ ! PRIVATE int make_break(ch) char ch; /* scan code of key just struck or released */ { /* This routine can handle keyboards that interrupt only on key depression, *************** *** 559,566 **** code -= 'a' - 'A'; if (alt) code |= 0200; /* alt key ORs 0200 into code */ if (control) code &= 037; ! if (code == 0) code = AT_SIGN; /* @ is 0100, so CTRL-@ = 0 */ ! if (make == 0) code = 0; /* key release */ return(code); } --- 571,578 ---- code -= 'a' - 'A'; if (alt) code |= 0200; /* alt key ORs 0200 into code */ if (control) code &= 037; ! /* if (code == 0) code = AT_SIGN; /* @ is 0100, so CTRL-@ = 0 */ ! if (make == 0) return(-1); /* key release */ return(code); } *************** *** 583,589 **** num_off = 1 - make; break; /* num lock */ } ! return(0); } #endif --- 595,601 ---- num_off = 1 - make; break; /* num lock */ } ! return(-1); } #endif *************** *** 598,604 **** /* Echo a character on the terminal. */ if ( (tp->tty_mode & ECHO) == 0) return; /* if no echoing, don't echo */ ! if (c != MARKER) { if (tp - tty_struct < NR_CONS) out_char(tp, c); /* echo to console */ else --- 610,617 ---- /* Echo a character on the terminal. */ if ( (tp->tty_mode & ECHO) == 0) return; /* if no echoing, don't echo */ ! /* MARKER is meaningful only in cooked mode */ ! if (c != MARKER || tp->tty_mode & (CBREAK | RAW)) { if (tp - tty_struct < NR_CONS) out_char(tp, c); /* echo to console */ else *************** *** 706,714 **** tp->tty_intail = tp->tty_inqueue; *tty_ptr++ = ch; ct++; ! if (ch == '\n' || ch == MARKER) { ! tp->tty_lfct--; ! if (cooked && ch == MARKER) eot_seen++; enough++; /* exit loop */ if (cooked) break; /* only provide 1 line */ } --- 719,727 ---- tp->tty_intail = tp->tty_inqueue; *tty_ptr++ = ch; ct++; ! if (ch == '\n' || ch == MARKER && cooked) { ! tp->tty_lfct--; ! if (ch == MARKER) eot_seen++; enough++; /* exit loop */ if (cooked) break; /* only provide 1 line */ } *************** *** 1159,1164 **** --- 1172,1181 ---- } switch(c) { + /* null is typically used for padding, so it better do nothing + * It displays as space, so we don't lose anything */ + case 000: + return; case 007: /* ring the bell */ flush(tp); /* print any chars queued for output */ beep(BEEP_FREQ);/* BEEP_FREQ gives bell tone */ *************** *** 1210,1219 **** return; default: /* printable chars are stored in ramqueue */ ! if (tp->tty_column >= LINE_WIDTH) return; /* long line */ if (tp->tty_rwords == TTY_RAM_WORDS) flush(tp); tp->tty_ramqueue[tp->tty_rwords++]=tp->tty_attribute|(c & BYTE); tp->tty_column++; /* next column */ return; } } --- 1227,1247 ---- return; default: /* printable chars are stored in ramqueue */ if (tp->tty_rwords == TTY_RAM_WORDS) flush(tp); tp->tty_ramqueue[tp->tty_rwords++]=tp->tty_attribute|(c & BYTE); tp->tty_column++; /* next column */ + if (tp->tty_column >= LINE_WIDTH) { + flush(tp); + if (tp->tty_row == SCR_LINES-1) + scroll_screen(tp, GO_FORWARD); + else + tp->tty_row++; + move_to(tp, 0, tp->tty_row); + } return; } } *************** *** 1668,1673 **** --- 1696,1754 ---- long_vid_copy(NIL_PTR, vid_base, dst - limit, count); } break; + case 'P': /* delete chars */ + {int src, dst, count; + + n = tp->tty_esc_parmv[0]; + if (n < 1) + n = 1; + if (n > (LINE_WIDTH - tp->tty_column)) + n = LINE_WIDTH - tp->tty_column; + src = (tp->tty_row * LINE_WIDTH + tp->tty_column + n) * 2; + dst = (tp->tty_row * LINE_WIDTH + tp->tty_column) * 2; + count = LINE_WIDTH - tp->tty_column - n; + src += tp->tty_org; + dst += tp->tty_org; + if ((! softscroll) && ega) { + if (src > SCR_BYTES) + src -= SCR_BYTES; + if (dst > SCR_BYTES) + dst -= SCR_BYTES; + } + scr_up(vid_base, src, dst, count); + vid_copy(NIL_PTR, vid_base, dst + count * 2, n); + } + break; + case '@': /* insert chars (actually blanks) */ + {int src, dst, count; + + n = tp->tty_esc_parmv[0]; + if (n < 1) + n = 1; + if (n > (LINE_WIDTH - tp->tty_column)) + n = LINE_WIDTH - tp->tty_column; + src = (tp->tty_row * LINE_WIDTH + LINE_WIDTH - n - 1) * 2; + dst = (tp->tty_row * LINE_WIDTH + LINE_WIDTH - 1) * 2; + count = LINE_WIDTH - tp->tty_column - n; + src += tp->tty_org; + dst += tp->tty_org; + if ((! softscroll) && ega) { + if (src > SCR_BYTES) + src -= SCR_BYTES; + if (dst > SCR_BYTES) + dst -= SCR_BYTES; + } + scr_down(vid_base, src, dst, count); + dst = (tp->tty_row * LINE_WIDTH + tp->tty_column) * 2; + dst += tp->tty_org; + if ((! softscroll) && ega) { + if (dst > SCR_BYTES) + dst -= SCR_BYTES; + } + vid_copy(NIL_PTR, vid_base, dst, n); + } + break; + case 'm': /* Set graphic rendition */ switch (tp->tty_esc_parmv[0]) { case 1: /* BOLD */