/* * Put a character with possible tracing. */ int vputch(int c) { #ifdef TRACE if (trace) tracec(c); #endif return vputc(c); }
/* * Get a keystroke, including a ^@. * If an key was returned with ungetkey, that * comes back first. Next comes unread input (e.g. * from repeating commands with .), and finally new * keystrokes. * * The hard work here is in mapping of \ escaped * characters on upper case only terminals. */ static int getbr(void) { char ch; register int c, d; register char *colp; #define BEEHIVE #ifdef BEEHIVE static char Peek2key; #endif extern short slevel, ttyindes; getATTN: if (Peekkey) { c = Peekkey; Peekkey = 0; return (c); } #ifdef BEEHIVE if (Peek2key) { c = Peek2key; Peek2key = 0; return (c); } #endif if (vglobp) { if (*vglobp) return (lastvgk = *vglobp++); lastvgk = 0; return (ESCAPE); } if (vmacp) { if (*vmacp) return(*vmacp++); /* End of a macro or set of nested macros */ vmacp = 0; if (inopen == -1) /* don't screw up undo for esc esc */ vundkind = VMANY; inopen = 1; /* restore old setting now that macro done */ vch_mac = VC_NOTINMAC; } flusho(); again: if (read(slevel == 0 ? 0 : ttyindes, &ch, 1) != 1) { if (errno == EINTR) goto getATTN; error("Input read error"); } c = ch & TRIM; #ifdef BEEHIVE if (XB && slevel==0 && c == ESCAPE) { if (read(0, &Peek2key, 1) != 1) goto getATTN; Peek2key &= TRIM; switch (Peek2key) { case 'C': /* SPOW mode sometimes sends \EC for space */ c = ' '; Peek2key = 0; break; case 'q': /* f2 -> ^C */ c = CTRL('c'); Peek2key = 0; break; case 'p': /* f1 -> esc */ Peek2key = 0; break; } } #endif #ifdef UCVISUAL /* * The algorithm here is that of the UNIX kernel. * See the description in the programmers manual. */ if (UPPERCASE) { if (isupper(c)) c = tolower(c); if (c == '\\') { if (precbksl < 2) precbksl++; if (precbksl == 1) goto again; } else if (precbksl) { d = 0; if (islower(c)) d = toupper(c); else { colp = "({)}!|^~'~"; while ((d = *colp++)) if (d == c) { d = *colp++; break; } else colp++; } if (precbksl == 2) { if (!d) { Peekkey = c; precbksl = 0; c = '\\'; } } else if (d) c = d; else { Peekkey = c; precbksl = 0; c = '\\'; } } if (c != '\\') precbksl = 0; } #endif #ifdef TRACE if (trace) { if (!techoin) { tfixnl(); techoin = 1; fprintf(trace, "*** Input: "); } tracec(c); } #endif lastvgk = 0; return (c); }
/* * Put the character c on the screen at the current cursor position. * This routine handles wraparound and scrolling and understands not * to roll when splitw is set, i.e. we are working in the echo area. * There is a bunch of hacking here dealing with the difference between * QUOTE, QUOTE|' ', and ' ' for CONCEPT-100 like terminals, and also * code to deal with terminals which overstrike, including CRT's where * you can erase overstrikes with some work. CRT's which do underlining * implicitly which has to be erased (like CONCEPTS) are also handled. */ int vputchar(register int c) { register cell *tp; register int d, m, n; #ifndef BIT8 c &= (QUOTE|TRIM); #endif #ifdef TRACE if (trace) tracec(c); #endif /* Fix problem of >79 chars on echo line. */ if (destcol >= WCOLS-1 && splitw && destline == WECHO) pofix(); #ifdef MB if (mb_cur_max > 1) { if (c == MULTICOL) return c; /* * If a multicolumn character extends beyond the screen * width, it must be put on the next line. A tilde is * printed as an indicator but must disappear when the * text is moved at a later time. */ if (c == ('~'|INVBIT|QUOTE)) c = '~'|INVBIT; else if (c == ('~'|INVBIT)) return c; else if (destcol < WCOLS && destcol + colsc(c==QUOTE ? ' ' : c&TRIM&~MULTICOL) - 1 >= WCOLS) vputchar('~'|INVBIT|QUOTE); } #endif /* MB */ if (destcol >= WCOLS) { destline += destcol / WCOLS; destcol %= WCOLS; } if (destline > WBOT && (!splitw || destline > WECHO)) vrollup(destline); tp = vtube[destline] + destcol; if (c == QUOTE) { if (insmode) { /* * When in insert mode, tabs have to expand * to real, printed blanks. */ c = ' ' | QUOTE; goto def; } if (*tp == 0) { /* * A ``space''. */ if ((hold & HOLDPUPD) == 0) *tp = QUOTE; destcol++; return c; } /* * A ``space'' ontop of a part of a tab. */ if (*tp & QUOTE) { destcol++; return c; } c = ' ' | QUOTE; goto def; } #ifdef notdef #ifdef BIT8 if (c == ' ' | QUOTE) { c = ' '; goto def; } #endif #endif switch (c) { case '\t': vgotab(); return c; case ' ': /* * We can get away without printing a space in a number * of cases, but not always. We get away with doing nothing * if we are not in insert mode, and not on a CONCEPT-100 * like terminal, and either not in hardcopy open or in hardcopy * open on a terminal with no overstriking, provided, * in all cases, that nothing has ever been displayed * at this position. Ugh. */ if (!insmode && !IN && (state != HARDOPEN || OS) && (*tp"E)) { *tp = ' '; destcol++; return c; } goto def; def: default: d = *tp & TRIM; /* * Now get away with doing nothing if the characters * are the same, provided we are not in insert mode * and if we are in hardopen, that the terminal has overstrike. */ if ((d & ~MULTICOL) == (c & TRIM & ~MULTICOL) && !insmode && (state != HARDOPEN || OS) && c != MULTICOL) { n = colsc(d); for (m = 1; m < n; m++) if ((tp[m] & (MULTICOL|TRIM)) != MULTICOL) break; if (m == n) { if ((hold & HOLDPUPD) == 0) *tp = c | (n > 1 ? MULTICOL : 0); destcol += n; return c; } } /* * Backwards looking optimization. * The low level cursor motion routines will use * a cursor motion right sequence to step 1 character * right. On, e.g., a DM3025A this is 2 characters * and printing is noticeably slower at 300 baud. * Since the low level routines are not allowed to use * spaces for positioning, we discover the common * case of a single space here and force a space * to be printed. */ if (destcol == outcol + 1 && tp[-1] == ' ' && outline == destline) { vputc(' '); outcol++; } /* * This is an inline expansion a call to vcsync() dictated * by high frequency in a profile. */ if (outcol != destcol || outline != destline) vgoto(destline, destcol); /* * Deal with terminals which have overstrike. * We handle erasing general overstrikes, erasing * underlines on terminals (such as CONCEPTS) which * do underlining correctly automatically (e.g. on nroff * output), and remembering, in hardcopy mode, * that we have overstruct something. */ if (!insmode && d && d != ' ' && d != (c & TRIM)) { if (EO && (OS || UL && (c == '_' || d == '_'))) { vputc(' '); outcol++, destcol++; back1(); } else rubble = 1; } /* * Unless we are just bashing characters around for * inner working of insert mode, update the display. */ if ((hold & HOLDPUPD) == 0) *tp = c; /* * In insert mode, put out the IC sequence, padded * based on the depth of the current line. * A terminal which had no real insert mode, rather * opening a character position at a time could do this. * Actually should use depth to end of current line * but this rarely matters. */ #ifdef notdef if (insmode) #else /* * It seems today's termcap writers consider this * an either-or situation; if both im and ic * are used vi puts out additional spaces. * * SVR4 ex does not include this change. If it hits * your terminal, change back to the old way and * mail me a description. * * GR July 2000 */ if (insmode && (!IM || !*IM)) #endif /* !notdef */ { n = colsc(c&TRIM); for (m = 0; m < n; m++) vputp(IC, DEPTH(vcline)); } vputc(c & TRIM); /* * In insert mode, IP is a post insert pad. */ if (insmode) vputp(IP, DEPTH(vcline)); destcol++, outcol++; /* * CONCEPT braindamage in early models: after a wraparound * the next newline is eaten. It's hungry so we just * feed it now rather than worrying about it. * Fixed to use return linefeed to work right * on vt100/tab132 as well as concept. */ if (XN && outcol % WCOLS == 0) { vputc('\r'); vputc('\n'); } } #ifdef MB if (mb_cur_max > 1 && (d = colsc(c&TRIM&~MULTICOL)) > 1) { if ((hold & HOLDPUPD) == 0) *tp |= MULTICOL; while (--d) { if ((hold & HOLDPUPD) == 0) *++tp = MULTICOL; destcol++; outcol++; } } #endif /* MB */ return c; }