termcap.c (6177B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* termcap.c - version 1.0.3 */ 3 4 #include <stdio.h> 5 #include "config.h" /* for ROWNO and COLNO */ 6 #include "flag.h" /* for flags.nonull */ 7 extern char *tgetstr(), *tgoto(), *getenv(); 8 extern long *alloc(); 9 10 #ifndef lint 11 extern /* it is defined in libtermlib (libtermcap) */ 12 #endif /* lint /**/ 13 short ospeed; /* terminal baudrate; used by tputs */ 14 static char tbuf[512]; 15 static char *HO, *CL, *CE, *UP, *CM, *ND, *XD, *BC, *SO, *SE, *TI, *TE; 16 static char *VS, *VE; 17 char *US, *UE; 18 static int SG; 19 static char PC = '\0'; 20 char *CD; /* tested in pri.c: docorner() */ 21 int CO, LI; /* used in pri.c and whatis.c */ 22 23 startup() 24 { 25 register char *term; 26 register char *tptr; 27 char *tbufptr, *pc; 28 29 tptr = (char *) alloc(1024); 30 31 tbufptr = tbuf; 32 33 if(!(term = getenv("TERM"))) 34 # ifdef MSDOS 35 term = "ibmpc-mono"; 36 # else 37 error("Can't get TERM."); 38 # endif 39 if(!strncmp(term, "5620", 4)) 40 flags.nonull = 1; /* this should be a termcap flag */ 41 if(tgetent(tptr, term) < 1) 42 error("Unknown terminal type: %s.", term); 43 TI = tgetstr("ti", &tbufptr); 44 TE = tgetstr("te", &tbufptr); 45 VS = VE = ""; 46 47 if(pc = tgetstr("pc", &tbufptr)) 48 PC = *pc; 49 if(!(BC = tgetstr("bc", &tbufptr))) { 50 if(!tgetflag("bs")) 51 error("Terminal must backspace."); 52 BC = tbufptr; 53 tbufptr += 2; 54 *BC = '\b'; 55 } 56 HO = tgetstr("ho", &tbufptr); 57 CO = tgetnum("co"); 58 LI = tgetnum("li"); 59 if(CO < COLNO || LI < ROWNO+2) 60 setclipped(); 61 if(!(CL = tgetstr("cl", &tbufptr))) 62 error("Hack needs CL."); 63 ND = tgetstr("nd", &tbufptr); 64 if(tgetflag("os")) 65 error("Hack can't have OS."); 66 CE = tgetstr("ce", &tbufptr); 67 UP = tgetstr("up", &tbufptr); 68 /* It seems that xd is no longer supported, and we should use 69 a linefeed instead; unfortunately this requires resetting 70 CRMOD, and many output routines will have to be modified 71 slightly. Let's leave that till the next release. */ 72 XD = tgetstr("xd", &tbufptr); 73 /* not: XD = tgetstr("do", &tbufptr); */ 74 if(!(CM = tgetstr("cm", &tbufptr))) { 75 if(!UP && !HO) 76 error("Hack needs CM or UP or HO."); 77 printf("Playing hack on terminals without cm is suspect...\n"); 78 getret(); 79 } 80 US = SO = tgetstr("so", &tbufptr); 81 UE = SE = tgetstr("se", &tbufptr); 82 US = tgetstr("us", &tbufptr); 83 UE = tgetstr("ue", &tbufptr); 84 SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */ 85 if(!SO || !SE || (SG > 0)) SO = SE = 0; 86 CD = tgetstr("cd", &tbufptr); 87 set_whole_screen(); /* uses LI and CD */ 88 if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n"); 89 free(tptr); 90 } 91 92 start_screen() 93 { 94 xputs(TI); 95 xputs(VS); 96 97 /* Select normal ASCII and line drawing character sets. 98 */ 99 if (flags.DECRainbow) 100 xputs("\033(B\033)0"); 101 } 102 103 end_screen() 104 { 105 clear_screen(); 106 xputs(VE); 107 xputs(TE); 108 } 109 110 /* Cursor movements */ 111 extern xchar curx, cury; 112 113 curs(x, y) 114 register int x, y; /* not xchar: perhaps xchar is unsigned and 115 curx-x would be unsigned as well */ 116 { 117 118 if (y == cury && x == curx) 119 return; 120 if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */ 121 cmov(x, y); /* bunker!wtm */ 122 return; 123 } 124 if(abs(cury-y) <= 3 && abs(curx-x) <= 3) 125 nocmov(x, y); 126 else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) { 127 (void) putchar('\r'); 128 curx = 1; 129 nocmov(x, y); 130 } else if(!CM) { 131 nocmov(x, y); 132 } else 133 cmov(x, y); 134 } 135 136 nocmov(x, y) 137 { 138 if (cury > y) { 139 if(UP) { 140 while (cury > y) { /* Go up. */ 141 xputs(UP); 142 cury--; 143 } 144 } else if(CM) { 145 cmov(x, y); 146 } else if(HO) { 147 home(); 148 curs(x, y); 149 } /* else impossible("..."); */ 150 } else if (cury < y) { 151 if(XD) { 152 while(cury < y) { 153 xputs(XD); 154 cury++; 155 } 156 } else if(CM) { 157 cmov(x, y); 158 } else { 159 while(cury < y) { 160 xputc('\n'); 161 curx = 1; 162 cury++; 163 } 164 } 165 } 166 if (curx < x) { /* Go to the right. */ 167 if(!ND) cmov(x, y); else /* bah */ 168 /* should instead print what is there already */ 169 while (curx < x) { 170 xputs(ND); 171 curx++; 172 } 173 } else if (curx > x) { 174 while (curx > x) { /* Go to the left. */ 175 xputs(BC); 176 curx--; 177 } 178 } 179 } 180 181 cmov(x, y) 182 register x, y; 183 { 184 xputs(tgoto(CM, x-1, y-1)); 185 cury = y; 186 curx = x; 187 } 188 189 xputc(c) char c; { 190 (void) fputc(c, stdout); 191 } 192 193 xputs(s) char *s; { 194 #ifdef MSDOS 195 fputs(s, stdout); 196 #else 197 tputs(s, 1, xputc); 198 #endif 199 } 200 201 cl_end() { 202 if(CE) 203 xputs(CE); 204 else { /* no-CE fix - free after Harold Rynes */ 205 /* this looks terrible, especially on a slow terminal 206 but is better than nothing */ 207 register cx = curx, cy = cury; 208 209 while(curx < COLNO) { 210 xputc(' '); 211 curx++; 212 } 213 curs(cx, cy); 214 } 215 } 216 217 clear_screen() { 218 xputs(CL); 219 home(); 220 } 221 222 home() 223 { 224 if(HO) 225 xputs(HO); 226 else if(CM) 227 xputs(tgoto(CM, 0, 0)); 228 else 229 curs(1, 1); /* using UP ... */ 230 curx = cury = 1; 231 } 232 233 standoutbeg() 234 { 235 if(SO) xputs(SO); 236 } 237 238 standoutend() 239 { 240 if(SE) xputs(SE); 241 } 242 243 backsp() 244 { 245 xputs(BC); 246 curx--; 247 } 248 249 bell() 250 { 251 #ifdef DGK 252 if (flags.silent) return; 253 #endif /* DGK /**/ 254 (void) putchar('\007'); /* curx does not change */ 255 (void) fflush(stdout); 256 } 257 258 static short tmspc10[] = { /* from termcap */ 259 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5 260 }; 261 262 delay_output() { 263 /* delay 50 ms - could also use a 'nap'-system call */ 264 /* BUG: if the padding character is visible, as it is on the 5620 265 then this looks terrible. */ 266 #ifdef MSDOS 267 /* simulate the delay with "cursor here" */ 268 register i; 269 for (i = 0; i < 3; i++) { 270 cmov(curx, cury); 271 (void) fflush(stdout); 272 } 273 #else 274 if(!flags.nonull) 275 tputs("50", 1, xputc); 276 277 /* cbosgd!cbcephus!pds for SYS V R2 */ 278 /* is this terminfo, or what? */ 279 /* tputs("$<50>", 1, xputc); */ 280 281 else if(ospeed > 0 || ospeed < SIZE(tmspc10)) if(CM) { 282 /* delay by sending cm(here) an appropriate number of times */ 283 register int cmlen = strlen(tgoto(CM, curx-1, cury-1)); 284 register int i = 500 + tmspc10[ospeed]/2; 285 286 while(i > 0) { 287 cmov(curx, cury); 288 i -= cmlen*tmspc10[ospeed]; 289 } 290 } 291 #endif /* MSDOS /**/ 292 } 293 294 cl_eos() /* free after Robert Viduya */ 295 { /* must only be called with curx = 1 */ 296 297 if(CD) 298 xputs(CD); 299 else { 300 register int cx = curx, cy = cury; 301 while(cury <= LI-2) { 302 cl_end(); 303 xputc('\n'); 304 curx = 1; 305 cury++; 306 } 307 cl_end(); 308 curs(cx, cy); 309 } 310 }