| 1 | /* Copyright (c) 1980 Regents of the University of California */ |
| 2 | static char *sccsid = "@(#)ex_tty.c 6.2 10/30/80"; |
| 3 | #include "ex.h" |
| 4 | #include "ex_tty.h" |
| 5 | |
| 6 | /* |
| 7 | * Terminal type initialization routines, |
| 8 | * and calculation of flags at entry or after |
| 9 | * a shell escape which may change them. |
| 10 | */ |
| 11 | short ospeed = -1; |
| 12 | |
| 13 | gettmode() |
| 14 | { |
| 15 | |
| 16 | #ifndef USG3TTY |
| 17 | if (gtty(1, &tty) < 0) |
| 18 | return; |
| 19 | if (ospeed != tty.sg_ospeed) |
| 20 | value(SLOWOPEN) = tty.sg_ospeed < B1200; |
| 21 | ospeed = tty.sg_ospeed; |
| 22 | normf = tty.sg_flags; |
| 23 | UPPERCASE = (tty.sg_flags & LCASE) != 0; |
| 24 | GT = (tty.sg_flags & XTABS) != XTABS && !XT; |
| 25 | NONL = (tty.sg_flags & CRMOD) == 0; |
| 26 | #else |
| 27 | if (ioctl(1, TCGETA, &tty) < 0) |
| 28 | return; |
| 29 | if (ospeed != tty.c_cflag & CBAUD) |
| 30 | value(SLOWOPEN) = (tty.c_cflag & CBAUD) < B1200; |
| 31 | ospeed = tty.c_cflag & CBAUD; |
| 32 | normf = tty; |
| 33 | UPPERCASE = (tty.c_iflag & IUCLC) != 0; |
| 34 | GT = (tty.c_oflag & TABDLY) != TAB3 && !XT; |
| 35 | NONL = (tty.c_oflag & OCRNL) == 0; |
| 36 | #endif |
| 37 | } |
| 38 | |
| 39 | char *xPC; |
| 40 | char **sstrs[] = { |
| 41 | &AL, &BC, &BT, &CD, &CE, &CL, &CM, &xCR, &DC, &DL, &DM, &DO, &ED, &EI, |
| 42 | &F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9, |
| 43 | &HO, &IC, &IM, &IP, &KD, &KE, &KH, &KL, &KR, &KS, &KU, &LL, |
| 44 | &ND, &xNL, &xPC, &SE, &SF, &SO, &SR, &TA, &TE, &TI, &UP, &VB, &VS, &VE |
| 45 | }; |
| 46 | bool *sflags[] = { |
| 47 | &AM, &BS, &DA, &DB, &EO, &HC, &HZ, &IN, &MI, &NC, &NS, &OS, &UL, |
| 48 | &XB, &XN, &XT, &XX |
| 49 | }; |
| 50 | char **fkeys[10] = { |
| 51 | &F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9 |
| 52 | }; |
| 53 | setterm(type) |
| 54 | char *type; |
| 55 | { |
| 56 | char *tgoto(); |
| 57 | register int unknown, i; |
| 58 | register int l; |
| 59 | char ltcbuf[TCBUFSIZE]; |
| 60 | |
| 61 | if (type[0] == 0) |
| 62 | type = "xx"; |
| 63 | unknown = 0; |
| 64 | putpad(TE); |
| 65 | if (tgetent(ltcbuf, type) != 1) { |
| 66 | unknown++; |
| 67 | CP(ltcbuf, "xx|dumb:"); |
| 68 | } |
| 69 | i = LINES = tgetnum("li"); |
| 70 | if (LINES <= 5) |
| 71 | LINES = 24; |
| 72 | if (LINES > TUBELINES) |
| 73 | LINES = TUBELINES; |
| 74 | l = LINES; |
| 75 | if (ospeed < B1200) |
| 76 | l = 9; /* including the message line at the bottom */ |
| 77 | else if (ospeed < B2400) |
| 78 | l = 17; |
| 79 | if (l > LINES) |
| 80 | l = LINES; |
| 81 | aoftspace = tspace; |
| 82 | zap(); |
| 83 | /* |
| 84 | * Initialize keypad arrow keys. |
| 85 | */ |
| 86 | arrows[0].cap = KU; arrows[0].mapto = "k"; arrows[0].descr = "up"; |
| 87 | arrows[1].cap = KD; arrows[1].mapto = "j"; arrows[1].descr = "down"; |
| 88 | arrows[2].cap = KL; arrows[2].mapto = "h"; arrows[2].descr = "left"; |
| 89 | arrows[3].cap = KR; arrows[3].mapto = "l"; arrows[3].descr = "right"; |
| 90 | arrows[4].cap = KH; arrows[4].mapto = "H"; arrows[4].descr = "home"; |
| 91 | |
| 92 | #ifdef TIOCLGET |
| 93 | /* |
| 94 | * Now map users susp char to ^Z, being careful that the susp |
| 95 | * overrides any arrow key, but only for hackers (=new tty driver). |
| 96 | */ |
| 97 | { |
| 98 | static char sc[2]; |
| 99 | int i, fnd; |
| 100 | |
| 101 | ioctl(0, TIOCGETD, &ldisc); |
| 102 | if (ldisc == NTTYDISC) { |
| 103 | sc[0] = olttyc.t_suspc; |
| 104 | sc[1] = 0; |
| 105 | if (olttyc.t_suspc == CTRL(z)) { |
| 106 | for (i=0; i<=4; i++) |
| 107 | if (arrows[i].cap[0] == CTRL(z)) |
| 108 | addmac(sc, NULL, NULL, arrows); |
| 109 | } else |
| 110 | addmac(sc, "\32", "susp", arrows); |
| 111 | } |
| 112 | } |
| 113 | #endif |
| 114 | |
| 115 | options[WINDOW].ovalue = options[WINDOW].odefault = l - 1; |
| 116 | if (defwind) options[WINDOW].ovalue = defwind; |
| 117 | options[SCROLL].ovalue = options[SCROLL].odefault = HC ? 11 : ((l-1) / 2); |
| 118 | COLUMNS = tgetnum("co"); |
| 119 | if (COLUMNS <= 4) |
| 120 | COLUMNS = 1000; |
| 121 | if (tgoto(CM, 2, 2)[0] == 'O') /* OOPS */ |
| 122 | CA = 0, CM = 0; |
| 123 | else |
| 124 | CA = 1, costCM = cost(tgoto(CM, 8, 10)); |
| 125 | costSR = cost(SR); |
| 126 | costAL = cost(AL); |
| 127 | PC = xPC ? xPC[0] : 0; |
| 128 | aoftspace = tspace; |
| 129 | CP(ttytype, longname(ltcbuf, type)); |
| 130 | if (i <= 0) |
| 131 | LINES = 2; |
| 132 | /* proper strings to change tty type */ |
| 133 | termreset(); |
| 134 | gettmode(); |
| 135 | value(REDRAW) = AL && DL; |
| 136 | value(OPTIMIZE) = !CA && !GT; |
| 137 | if (ospeed == B1200 && !value(REDRAW)) |
| 138 | value(SLOWOPEN) = 1; /* see also gettmode above */ |
| 139 | if (unknown) |
| 140 | serror("%s: Unknown terminal type", type); |
| 141 | } |
| 142 | |
| 143 | zap() |
| 144 | { |
| 145 | register char *namp; |
| 146 | register bool **fp; |
| 147 | register char ***sp; |
| 148 | |
| 149 | namp = "ambsdadbeohchzinmincnsosulxbxnxtxx"; |
| 150 | fp = sflags; |
| 151 | do { |
| 152 | *(*fp++) = tgetflag(namp); |
| 153 | namp += 2; |
| 154 | } while (*namp); |
| 155 | namp = "albcbtcdceclcmcrdcdldmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullndnlpcsesfsosrtatetiupvbvsve"; |
| 156 | sp = sstrs; |
| 157 | do { |
| 158 | *(*sp++) = tgetstr(namp, &aoftspace); |
| 159 | namp += 2; |
| 160 | } while (*namp); |
| 161 | } |
| 162 | |
| 163 | char * |
| 164 | longname(bp, def) |
| 165 | register char *bp; |
| 166 | char *def; |
| 167 | { |
| 168 | register char *cp; |
| 169 | |
| 170 | while (*bp && *bp != ':' && *bp != '|') |
| 171 | bp++; |
| 172 | if (*bp == '|') { |
| 173 | bp++; |
| 174 | cp = bp; |
| 175 | while (*cp && *cp != ':' && *cp != '|') |
| 176 | cp++; |
| 177 | *cp = 0; |
| 178 | return (bp); |
| 179 | } |
| 180 | return (def); |
| 181 | } |
| 182 | |
| 183 | char * |
| 184 | fkey(i) |
| 185 | int i; |
| 186 | { |
| 187 | if (0 <= i && i <= 9) |
| 188 | return(*fkeys[i]); |
| 189 | else |
| 190 | return(NOSTR); |
| 191 | } |
| 192 | |
| 193 | /* |
| 194 | * cost figures out how much (in characters) it costs to send the string |
| 195 | * str to the terminal. It takes into account padding information, as |
| 196 | * much as it can, for a typical case. (Right now the typical case assumes |
| 197 | * the number of lines affected is the size of the screen, since this is |
| 198 | * mainly used to decide if AL or SR is better, and this always happens |
| 199 | * at the top of the screen. We assume cursor motion (CM) has little |
| 200 | * padding, if any, required, so that case, which is really more important |
| 201 | * than AL vs SR, won't be really affected.) |
| 202 | */ |
| 203 | static int costnum; |
| 204 | cost(str) |
| 205 | char *str; |
| 206 | { |
| 207 | int countnum(); |
| 208 | |
| 209 | if (str == NULL) |
| 210 | return 10000; /* infinity */ |
| 211 | costnum = 0; |
| 212 | tputs(str, LINES, countnum); |
| 213 | return costnum; |
| 214 | } |
| 215 | |
| 216 | /* ARGSUSED */ |
| 217 | countnum(ch) |
| 218 | char ch; |
| 219 | { |
| 220 | costnum++; |
| 221 | } |