[9] | 1 | /* curses.c */
|
---|
| 2 |
|
---|
| 3 | /* Author:
|
---|
| 4 | * Steve Kirkendall
|
---|
| 5 | * 14407 SW Teal Blvd. #C
|
---|
| 6 | * Beaverton, OR 97005
|
---|
| 7 | * kirkenda@cs.pdx.edu
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 |
|
---|
| 11 | /* This file contains the functions & variables needed for a tiny subset of
|
---|
| 12 | * curses. The principle advantage of this version of curses is its
|
---|
| 13 | * extreme speed. Disadvantages are potentially larger code, few supported
|
---|
| 14 | * functions, limited compatibility with full curses, and only stdscr.
|
---|
| 15 | */
|
---|
| 16 |
|
---|
| 17 | #include "config.h"
|
---|
| 18 | #include "vi.h"
|
---|
| 19 |
|
---|
| 20 | #if ANY_UNIX
|
---|
| 21 | /* The termios/termio/sgtty #ifdefs were a mess, so I removed all but termios.
|
---|
| 22 | * (KJB)
|
---|
| 23 | */
|
---|
| 24 | # include <termios.h>
|
---|
| 25 | # if MINIX
|
---|
| 26 | # include <sys/ioctl.h>
|
---|
| 27 | # endif
|
---|
| 28 | #endif
|
---|
| 29 |
|
---|
| 30 | #if TOS
|
---|
| 31 | # include <osbind.h>
|
---|
| 32 | #endif
|
---|
| 33 |
|
---|
| 34 | #if OSK
|
---|
| 35 | # include <sgstat.h>
|
---|
| 36 | #endif
|
---|
| 37 |
|
---|
| 38 | #if VMS
|
---|
| 39 | extern int VMS_read_raw; /* Set in initscr() */
|
---|
| 40 | #endif
|
---|
| 41 |
|
---|
| 42 |
|
---|
| 43 | extern char *getenv();
|
---|
| 44 | static void starttcap();
|
---|
| 45 |
|
---|
| 46 | /* variables, publicly available & used in the macros */
|
---|
| 47 | char *termtype; /* name of terminal entry */
|
---|
| 48 | short ospeed; /* speed of the tty, eg B2400 */
|
---|
| 49 | #if OSK
|
---|
| 50 | char PC_; /* Pad char */
|
---|
| 51 | char *BC; /* backspace character string */
|
---|
| 52 | #else
|
---|
| 53 | char PC; /* Pad char */
|
---|
| 54 | #endif
|
---|
| 55 | WINDOW *stdscr; /* pointer into kbuf[] */
|
---|
| 56 | WINDOW kbuf[KBSIZ]; /* a very large output buffer */
|
---|
| 57 | int LINES; /* :li#: number of rows */
|
---|
| 58 | int COLS; /* :co#: number of columns */
|
---|
| 59 | int AM; /* :am: boolean: auto margins? */
|
---|
| 60 | int PT; /* :pt: boolean: physical tabs? */
|
---|
| 61 | char *VB; /* :vb=: visible bell */
|
---|
| 62 | char *UP; /* :up=: move cursor up */
|
---|
| 63 | char *SO = ""; /* :so=: standout start */
|
---|
| 64 | char *SE = ""; /* :se=: standout end */
|
---|
| 65 | char *US = ""; /* :us=: underline start */
|
---|
| 66 | char *UE = ""; /* :ue=: underline end */
|
---|
| 67 | char *MD = ""; /* :md=: bold start */
|
---|
| 68 | char *ME = ""; /* :me=: bold end */
|
---|
| 69 | char *AS = ""; /* :as=: alternate (italic) start */
|
---|
| 70 | char *AE = ""; /* :ae=: alternate (italic) end */
|
---|
| 71 | #ifndef NO_VISIBLE
|
---|
| 72 | char *MV; /* :mv=: "visible" selection start */
|
---|
| 73 | #endif
|
---|
| 74 | char *CM; /* :cm=: cursor movement */
|
---|
| 75 | char *CE; /* :ce=: clear to end of line */
|
---|
| 76 | char *CD; /* :cd=: clear to end of screen */
|
---|
| 77 | char *AL; /* :al=: add a line */
|
---|
| 78 | char *DL; /* :dl=: delete a line */
|
---|
| 79 | #if OSK
|
---|
| 80 | char *SR_; /* :sr=: scroll reverse */
|
---|
| 81 | #else
|
---|
| 82 | char *SR; /* :sr=: scroll reverse */
|
---|
| 83 | #endif
|
---|
| 84 | char *KS = ""; /* :ks=: init string for cursor */
|
---|
| 85 | char *KE = ""; /* :ke=: restore string for cursor */
|
---|
| 86 | char *KU; /* :ku=: key sequence sent by up arrow */
|
---|
| 87 | char *KD; /* :kd=: key sequence sent by down arrow */
|
---|
| 88 | char *KL; /* :kl=: key sequence sent by left arrow */
|
---|
| 89 | char *KR; /* :kr=: key sequence sent by right arrow */
|
---|
| 90 | char *HM; /* :HM=: key sequence sent by the <Home> key */
|
---|
| 91 | char *EN; /* :EN=: key sequence sent by the <End> key */
|
---|
| 92 | char *PU; /* :PU=: key sequence sent by the <PgUp> key */
|
---|
| 93 | char *PD; /* :PD=: key sequence sent by the <PgDn> key */
|
---|
| 94 | char *KI; /* :kI=: key sequence sent by the <Insert> key */
|
---|
| 95 | #ifndef NO_FKEY
|
---|
| 96 | char *FKEY[NFKEYS]; /* :k0=: ... :k9=: sequences sent by function keys */
|
---|
| 97 | #endif
|
---|
| 98 | char *IM = ""; /* :im=: insert mode start */
|
---|
| 99 | char *IC = ""; /* :ic=: insert the following character */
|
---|
| 100 | char *EI = ""; /* :ei=: insert mode end */
|
---|
| 101 | char *DC; /* :dc=: delete a character */
|
---|
| 102 | char *TI = ""; /* :ti=: terminal init */ /* GB */
|
---|
| 103 | char *TE = ""; /* :te=: terminal exit */ /* GB */
|
---|
| 104 | #ifndef NO_CURSORSHAPE
|
---|
| 105 | #if 1
|
---|
| 106 | char *CQ = (char *)0;/* :cQ=: normal cursor */
|
---|
| 107 | char *CX = (char *)1;/* :cX=: cursor used for EX command/entry */
|
---|
| 108 | char *CV = (char *)2;/* :cV=: cursor used for VI command mode */
|
---|
| 109 | char *CI = (char *)3;/* :cI=: cursor used for VI input mode */
|
---|
| 110 | char *CR = (char *)4;/* :cR=: cursor used for VI replace mode */
|
---|
| 111 | #else
|
---|
| 112 | char *CQ = ""; /* :cQ=: normal cursor */
|
---|
| 113 | char *CX = ""; /* :cX=: cursor used for EX command/entry */
|
---|
| 114 | char *CV = ""; /* :cV=: cursor used for VI command mode */
|
---|
| 115 | char *CI = ""; /* :cI=: cursor used for VI input mode */
|
---|
| 116 | char *CR = ""; /* :cR=: cursor used for VI replace mode */
|
---|
| 117 | #endif
|
---|
| 118 | #endif
|
---|
| 119 | char *aend = ""; /* end an attribute -- either UE or ME */
|
---|
| 120 | char ERASEKEY; /* backspace key taken from ioctl structure */
|
---|
| 121 | #ifndef NO_COLOR
|
---|
| 122 | char normalcolor[16];
|
---|
| 123 | char SOcolor[16];
|
---|
| 124 | char SEcolor[16];
|
---|
| 125 | char UScolor[16];
|
---|
| 126 | char UEcolor[16];
|
---|
| 127 | char MDcolor[16];
|
---|
| 128 | char MEcolor[16];
|
---|
| 129 | char AScolor[16];
|
---|
| 130 | char AEcolor[16];
|
---|
| 131 | # ifndef NO_POPUP
|
---|
| 132 | char POPUPcolor[16];
|
---|
| 133 | # endif
|
---|
| 134 | # ifndef NO_VISIBLE
|
---|
| 135 | char VISIBLEcolor[16];
|
---|
| 136 | # endif
|
---|
| 137 | #endif
|
---|
| 138 |
|
---|
| 139 | #if ANY_UNIX
|
---|
| 140 | static struct termios oldtermio; /* original tty mode */
|
---|
| 141 | static struct termios newtermio; /* cbreak/noecho tty mode */
|
---|
| 142 | #endif
|
---|
| 143 |
|
---|
| 144 | #if OSK
|
---|
| 145 | static struct sgbuf oldsgttyb; /* orginal tty mode */
|
---|
| 146 | static struct sgbuf newsgttyb; /* noecho tty mode */
|
---|
| 147 | #endif
|
---|
| 148 |
|
---|
| 149 | static char *capbuf; /* capability string buffer */
|
---|
| 150 |
|
---|
| 151 |
|
---|
| 152 | /* Initialize the Curses package. */
|
---|
| 153 | void initscr()
|
---|
| 154 | {
|
---|
| 155 | /* make sure TERM variable is set */
|
---|
| 156 | termtype = getenv("TERM");
|
---|
| 157 |
|
---|
| 158 | #if VMS
|
---|
| 159 | /* VMS getenv() handles TERM as a environment setting. Foreign
|
---|
| 160 | * terminal support can be implemented by setting the ELVIS_TERM
|
---|
| 161 | * logical or symbol to match a tinytcap entry.
|
---|
| 162 | */
|
---|
| 163 | if (!strcmp(termtype,"unknown"))
|
---|
| 164 | termtype = getenv("ELVIS_TERM");
|
---|
| 165 | #endif
|
---|
| 166 | #if MSDOS
|
---|
| 167 | /* For MS-DOS, if TERM is unset we can default to "pcbios", or
|
---|
| 168 | * maybe "rainbow".
|
---|
| 169 | */
|
---|
| 170 | if (!termtype)
|
---|
| 171 | {
|
---|
| 172 | #ifdef RAINBOW
|
---|
| 173 | if (*(unsigned char far*)(0xffff000eL) == 6 /* Rainbow 100a */
|
---|
| 174 | || *(unsigned char far*)(0xffff000eL) == 148)/* Rainbow 100b */
|
---|
| 175 | {
|
---|
| 176 | termtype = "rainbow";
|
---|
| 177 | }
|
---|
| 178 | else
|
---|
| 179 | #endif
|
---|
| 180 | termtype = "pcbios";
|
---|
| 181 | }
|
---|
| 182 | if (!strcmp(termtype, "pcbios"))
|
---|
| 183 | #else
|
---|
| 184 | if (!termtype)
|
---|
| 185 | #endif
|
---|
| 186 | {
|
---|
| 187 | #if ANY_UNIX
|
---|
| 188 | write(2, "Environment variable TERM must be set\n", (unsigned)38);
|
---|
| 189 | exit(1);
|
---|
| 190 | #endif
|
---|
| 191 | #if OSK
|
---|
| 192 | writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
|
---|
| 193 | exit(1);
|
---|
| 194 | #endif
|
---|
| 195 | #if AMIGA
|
---|
| 196 | termtype = TERMTYPE;
|
---|
| 197 | starttcap(termtype);
|
---|
| 198 | #endif
|
---|
| 199 | #if MSDOS
|
---|
| 200 | starttcap("pcbios");
|
---|
| 201 | #endif
|
---|
| 202 | #if TOS
|
---|
| 203 | termtype = "vt52";
|
---|
| 204 | starttcap(termtype);
|
---|
| 205 | #endif
|
---|
| 206 | #if VMS
|
---|
| 207 | write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
|
---|
| 208 | exit(1);
|
---|
| 209 | #endif
|
---|
| 210 | }
|
---|
| 211 | else
|
---|
| 212 | {
|
---|
| 213 | #if MSDOS
|
---|
| 214 | *o_pcbios = 0;
|
---|
| 215 | #endif
|
---|
| 216 | /* start termcap stuff */
|
---|
| 217 | starttcap(termtype);
|
---|
| 218 | }
|
---|
| 219 |
|
---|
| 220 | /* create stdscr and curscr */
|
---|
| 221 | stdscr = kbuf;
|
---|
| 222 |
|
---|
| 223 | /* change the terminal mode to cbreak/noecho */
|
---|
| 224 | #if ANY_UNIX
|
---|
| 225 | tcgetattr(2, &oldtermio);
|
---|
| 226 | #endif
|
---|
| 227 |
|
---|
| 228 | #if OSK
|
---|
| 229 | _gs_opt(0, &oldsgttyb);
|
---|
| 230 | #endif
|
---|
| 231 |
|
---|
| 232 | #if VMS
|
---|
| 233 | VMS_read_raw = 1; /* cbreak/noecho */
|
---|
| 234 | vms_open_tty();
|
---|
| 235 | #endif
|
---|
| 236 | resume_curses(TRUE);
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | /* Shut down the Curses package. */
|
---|
| 240 | void endwin()
|
---|
| 241 | {
|
---|
| 242 | /* change the terminal mode back the way it was */
|
---|
| 243 | suspend_curses();
|
---|
| 244 | #if AMIGA
|
---|
| 245 | amiclosewin();
|
---|
| 246 | #endif
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 |
|
---|
| 250 | static int curses_active = FALSE;
|
---|
| 251 |
|
---|
| 252 | /* Send any required termination strings. Turn off "raw" mode. */
|
---|
| 253 | void suspend_curses()
|
---|
| 254 | {
|
---|
| 255 | #ifndef NO_CURSORSHAPE
|
---|
| 256 | if (has_CQ)
|
---|
| 257 | {
|
---|
| 258 | do_CQ();
|
---|
| 259 | }
|
---|
| 260 | #endif
|
---|
| 261 | if (has_TE) /* GB */
|
---|
| 262 | {
|
---|
| 263 | do_TE();
|
---|
| 264 | }
|
---|
| 265 | if (has_KE)
|
---|
| 266 | {
|
---|
| 267 | do_KE();
|
---|
| 268 | }
|
---|
| 269 | #ifndef NO_COLOR
|
---|
| 270 | quitcolor();
|
---|
| 271 | #endif
|
---|
| 272 | refresh();
|
---|
| 273 |
|
---|
| 274 | /* change the terminal mode back the way it was */
|
---|
| 275 | #if ANY_UNIX
|
---|
| 276 | tcsetattr(2, TCSADRAIN, &oldtermio);
|
---|
| 277 | #endif
|
---|
| 278 | #if OSK
|
---|
| 279 | _ss_opt(0, &oldsgttyb);
|
---|
| 280 | #endif
|
---|
| 281 | #if AMIGA
|
---|
| 282 | ttyshutdown();
|
---|
| 283 | #endif
|
---|
| 284 | #if MSDOS
|
---|
| 285 | raw_set_stdio(FALSE);
|
---|
| 286 | #endif
|
---|
| 287 |
|
---|
| 288 | #if VMS
|
---|
| 289 | VMS_read_raw = 0;
|
---|
| 290 | #endif
|
---|
| 291 | curses_active = FALSE;
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 |
|
---|
| 295 | /* put the terminal in RAW mode. If "quietly" is FALSE, then ask the user
|
---|
| 296 | * to hit a key, and wait for keystroke before returning.
|
---|
| 297 | */
|
---|
| 298 | void resume_curses(quietly)
|
---|
| 299 | int quietly;
|
---|
| 300 | {
|
---|
| 301 | if (!curses_active)
|
---|
| 302 | {
|
---|
| 303 | /* change the terminal mode to cbreak/noecho */
|
---|
| 304 | #if ANY_UNIX
|
---|
| 305 | ospeed = cfgetospeed(&oldtermio);
|
---|
| 306 | ERASEKEY = oldtermio.c_cc[VERASE];
|
---|
| 307 | newtermio = oldtermio;
|
---|
| 308 | newtermio.c_iflag &= (IXON|IXOFF|IXANY|ISTRIP|IGNBRK);
|
---|
| 309 | newtermio.c_oflag &= ~OPOST;
|
---|
| 310 | newtermio.c_lflag &= ISIG;
|
---|
| 311 | newtermio.c_cc[VINTR] = ctrl('C'); /* always use ^C for interrupts */
|
---|
| 312 | newtermio.c_cc[VMIN] = 1;
|
---|
| 313 | newtermio.c_cc[VTIME] = 0;
|
---|
| 314 | newtermio.c_cc[VSUSP] = 0;
|
---|
| 315 | tcsetattr(2, TCSADRAIN, &newtermio);
|
---|
| 316 | #endif
|
---|
| 317 | #if OSK
|
---|
| 318 | newsgttyb = oldsgttyb;
|
---|
| 319 | newsgttyb.sg_echo = 0;
|
---|
| 320 | newsgttyb.sg_eofch = 0;
|
---|
| 321 | newsgttyb.sg_kbach = 0;
|
---|
| 322 | newsgttyb.sg_kbich = ctrl('C');
|
---|
| 323 | _ss_opt(0, &newsgttyb);
|
---|
| 324 | ospeed = oldsgttyb.sg_baud;
|
---|
| 325 | ERASEKEY = oldsgttyb.sg_bspch;
|
---|
| 326 | #endif
|
---|
| 327 | #if AMIGA
|
---|
| 328 | /* turn on window resize and RAW */
|
---|
| 329 | ttysetup();
|
---|
| 330 | #endif
|
---|
| 331 | #if MSDOS
|
---|
| 332 | raw_set_stdio(TRUE);
|
---|
| 333 | #endif
|
---|
| 334 |
|
---|
| 335 | #if VMS
|
---|
| 336 | VMS_read_raw = 1;
|
---|
| 337 | { int c;
|
---|
| 338 | read(0,&c,0); /* Flush the tty buffer. */
|
---|
| 339 | }
|
---|
| 340 | ERASEKEY = '\177'; /* Accept <DEL> as <^H> for VMS */
|
---|
| 341 | #endif
|
---|
| 342 |
|
---|
| 343 | if (has_TI) /* GB */
|
---|
| 344 | {
|
---|
| 345 | do_TI();
|
---|
| 346 | }
|
---|
| 347 | if (has_KS)
|
---|
| 348 | {
|
---|
| 349 | do_KS();
|
---|
| 350 | }
|
---|
| 351 |
|
---|
| 352 | curses_active = TRUE;
|
---|
| 353 | }
|
---|
| 354 |
|
---|
| 355 | /* If we're supposed to quit quietly, then we're done */
|
---|
| 356 | if (quietly)
|
---|
| 357 | {
|
---|
| 358 | return;
|
---|
| 359 | }
|
---|
| 360 |
|
---|
| 361 | signal(SIGINT, SIG_IGN);
|
---|
| 362 |
|
---|
| 363 | move(LINES - 1, 0);
|
---|
| 364 | do_SO();
|
---|
| 365 | #if VMS
|
---|
| 366 | qaddstr("\n[Press <RETURN> to continue]");
|
---|
| 367 | #else
|
---|
| 368 | qaddstr("[Press <RETURN> to continue]");
|
---|
| 369 | #endif
|
---|
| 370 | do_SE();
|
---|
| 371 | refresh();
|
---|
| 372 | ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
|
---|
| 373 | if (kbuf[0] == ':')
|
---|
| 374 | {
|
---|
| 375 | mode = MODE_COLON;
|
---|
| 376 | addch('\n');
|
---|
| 377 | refresh();
|
---|
| 378 | }
|
---|
| 379 | else
|
---|
| 380 | {
|
---|
| 381 | mode = MODE_VI;
|
---|
| 382 | redraw(MARK_UNSET, FALSE);
|
---|
| 383 | }
|
---|
| 384 | exwrote = FALSE;
|
---|
| 385 |
|
---|
| 386 | #if TURBOC || __GNUC__ || _ANSI
|
---|
| 387 | signal(SIGINT, (void(*)()) trapint);
|
---|
| 388 | #else
|
---|
| 389 | signal(SIGINT, trapint);
|
---|
| 390 | #endif
|
---|
| 391 | }
|
---|
| 392 |
|
---|
| 393 | /* This function fetches an optional string from termcap */
|
---|
| 394 | static void mayhave(T, s)
|
---|
| 395 | char **T; /* where to store the returned pointer */
|
---|
| 396 | char *s; /* name of the capability */
|
---|
| 397 | {
|
---|
| 398 | char *val;
|
---|
| 399 |
|
---|
| 400 | val = tgetstr(s, &capbuf);
|
---|
| 401 | if (val)
|
---|
| 402 | {
|
---|
| 403 | *T = val;
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 |
|
---|
| 408 | /* This function fetches a required string from termcap */
|
---|
| 409 | static void musthave(T, s)
|
---|
| 410 | char **T; /* where to store the returned pointer */
|
---|
| 411 | char *s; /* name of the capability */
|
---|
| 412 | {
|
---|
| 413 | mayhave(T, s);
|
---|
| 414 | if (!*T)
|
---|
| 415 | {
|
---|
| 416 | write(2, "This termcap entry lacks the :", (unsigned)30);
|
---|
| 417 | write(2, s, (unsigned)2);
|
---|
| 418 | write(2, "=: capability\n", (unsigned)14);
|
---|
| 419 | #if OSK
|
---|
| 420 | write(2, "\l", 1);
|
---|
| 421 | #endif
|
---|
| 422 | exit(1);
|
---|
| 423 | }
|
---|
| 424 | }
|
---|
| 425 |
|
---|
| 426 |
|
---|
| 427 | /* This function fetches a pair of strings from termcap. If one of them is
|
---|
| 428 | * missing, then the other one is ignored.
|
---|
| 429 | */
|
---|
| 430 | static void pair(T, U, sT, sU)
|
---|
| 431 | char **T; /* where to store the first pointer */
|
---|
| 432 | char **U; /* where to store the second pointer */
|
---|
| 433 | char *sT; /* name of the first capability */
|
---|
| 434 | char *sU; /* name of the second capability */
|
---|
| 435 | {
|
---|
| 436 | mayhave(T, sT);
|
---|
| 437 | mayhave(U, sU);
|
---|
| 438 | if (!**T || !**U)
|
---|
| 439 | {
|
---|
| 440 | *T = *U = "";
|
---|
| 441 | }
|
---|
| 442 | }
|
---|
| 443 |
|
---|
| 444 |
|
---|
| 445 |
|
---|
| 446 | /* Read everything from termcap */
|
---|
| 447 | static void starttcap(term)
|
---|
| 448 | char *term;
|
---|
| 449 | {
|
---|
| 450 | static char cbmem[800];
|
---|
| 451 |
|
---|
| 452 | /* allocate memory for capbuf */
|
---|
| 453 | capbuf = cbmem;
|
---|
| 454 |
|
---|
| 455 | /* get the termcap entry */
|
---|
| 456 | switch (tgetent(kbuf, term))
|
---|
| 457 | {
|
---|
| 458 | case -1:
|
---|
| 459 | write(2, "Can't read /etc/termcap\n", (unsigned)24);
|
---|
| 460 | #if OSK
|
---|
| 461 | write(2, "\l", 1);
|
---|
| 462 | #endif
|
---|
| 463 | exit(2);
|
---|
| 464 |
|
---|
| 465 | case 0:
|
---|
| 466 | write(2, "Unrecognized TERM type\n", (unsigned)23);
|
---|
| 467 | #if OSK
|
---|
| 468 | write(2, "\l", 1);
|
---|
| 469 | #endif
|
---|
| 470 | exit(3);
|
---|
| 471 | }
|
---|
| 472 |
|
---|
| 473 | /* get strings */
|
---|
| 474 | musthave(&UP, "up");
|
---|
| 475 | mayhave(&VB, "vb");
|
---|
| 476 | musthave(&CM, "cm");
|
---|
| 477 | pair(&SO, &SE, "so", "se");
|
---|
| 478 | mayhave(&TI, "ti");
|
---|
| 479 | mayhave(&TE, "te");
|
---|
| 480 | if (tgetnum("ug") <= 0)
|
---|
| 481 | {
|
---|
| 482 | pair(&US, &UE, "us", "ue");
|
---|
| 483 | pair(&MD, &ME, "md", "me");
|
---|
| 484 |
|
---|
| 485 | /* get italics, or have it default to underline */
|
---|
| 486 | pair(&AS, &AE, "as", "ae");
|
---|
| 487 | if (!*AS)
|
---|
| 488 | {
|
---|
| 489 | AS = US;
|
---|
| 490 | AE = UE;
|
---|
| 491 | }
|
---|
| 492 | }
|
---|
| 493 | #ifndef NO_VISIBLE
|
---|
| 494 | MV = SO; /* by default */
|
---|
| 495 | mayhave(&MV, "mv");
|
---|
| 496 | #endif
|
---|
| 497 | mayhave(&AL, "al");
|
---|
| 498 | mayhave(&DL, "dl");
|
---|
| 499 | musthave(&CE, "ce");
|
---|
| 500 | mayhave(&CD, "cd");
|
---|
| 501 | #if OSK
|
---|
| 502 | mayhave(&SR_, "sr");
|
---|
| 503 | #else
|
---|
| 504 | mayhave(&SR, "sr");
|
---|
| 505 | #endif
|
---|
| 506 | pair(&IM, &EI, "im", "ei");
|
---|
| 507 | mayhave(&IC, "ic");
|
---|
| 508 | mayhave(&DC, "dc");
|
---|
| 509 |
|
---|
| 510 | /* other termcap stuff */
|
---|
| 511 | AM = (tgetflag("am") && !tgetflag("xn"));
|
---|
| 512 | PT = tgetflag("pt");
|
---|
| 513 | #if AMIGA
|
---|
| 514 | amiopenwin(termtype); /* Must run this before ttysetup(); */
|
---|
| 515 | ttysetup(); /* Must run this before getsize(0); */
|
---|
| 516 | #endif
|
---|
| 517 | getsize(0);
|
---|
| 518 |
|
---|
| 519 | /* Key sequences */
|
---|
| 520 | pair(&KS, &KE, "ks", "ke");
|
---|
| 521 | mayhave(&KU, "ku"); /* up */
|
---|
| 522 | mayhave(&KD, "kd"); /* down */
|
---|
| 523 | mayhave(&KL, "kl"); /* left */
|
---|
| 524 | mayhave(&KR, "kr"); /* right */
|
---|
| 525 | mayhave(&PU, "kP"); /* PgUp */
|
---|
| 526 | mayhave(&PD, "kN"); /* PgDn */
|
---|
| 527 | mayhave(&HM, "kh"); /* Home */
|
---|
| 528 | mayhave(&EN, "kH"); /* End */
|
---|
| 529 | mayhave(&KI, "kI"); /* Insert */
|
---|
| 530 | #ifndef CRUNCH
|
---|
| 531 | if (!PU) mayhave(&PU, "K2"); /* "3x3 pad" names for PgUp, etc. */
|
---|
| 532 | if (!PD) mayhave(&PD, "K5");
|
---|
| 533 | if (!HM) mayhave(&HM, "K1");
|
---|
| 534 | if (!EN) mayhave(&EN, "K4");
|
---|
| 535 |
|
---|
| 536 | mayhave(&PU, "PU"); /* old XENIX names for PgUp, etc. */
|
---|
| 537 | mayhave(&PD, "PD"); /* (overrides others, if used.) */
|
---|
| 538 | mayhave(&HM, "HM");
|
---|
| 539 | mayhave(&EN, "EN");
|
---|
| 540 | #endif
|
---|
| 541 | #ifndef NO_FKEY
|
---|
| 542 | mayhave(&FKEY[0], "k0"); /* function key codes */
|
---|
| 543 | mayhave(&FKEY[1], "k1");
|
---|
| 544 | mayhave(&FKEY[2], "k2");
|
---|
| 545 | mayhave(&FKEY[3], "k3");
|
---|
| 546 | mayhave(&FKEY[4], "k4");
|
---|
| 547 | mayhave(&FKEY[5], "k5");
|
---|
| 548 | mayhave(&FKEY[6], "k6");
|
---|
| 549 | mayhave(&FKEY[7], "k7");
|
---|
| 550 | mayhave(&FKEY[8], "k8");
|
---|
| 551 | mayhave(&FKEY[9], "k9");
|
---|
| 552 | # ifndef NO_SHIFT_FKEY
|
---|
| 553 | mayhave(&FKEY[10], "s0"); /* shift function key codes */
|
---|
| 554 | mayhave(&FKEY[11], "s1");
|
---|
| 555 | mayhave(&FKEY[12], "s2");
|
---|
| 556 | mayhave(&FKEY[13], "s3");
|
---|
| 557 | mayhave(&FKEY[14], "s4");
|
---|
| 558 | mayhave(&FKEY[15], "s5");
|
---|
| 559 | mayhave(&FKEY[16], "s6");
|
---|
| 560 | mayhave(&FKEY[17], "s7");
|
---|
| 561 | mayhave(&FKEY[18], "s8");
|
---|
| 562 | mayhave(&FKEY[19], "s9");
|
---|
| 563 | # ifndef NO_CTRL_FKEY
|
---|
| 564 | mayhave(&FKEY[20], "c0"); /* control function key codes */
|
---|
| 565 | mayhave(&FKEY[21], "c1");
|
---|
| 566 | mayhave(&FKEY[22], "c2");
|
---|
| 567 | mayhave(&FKEY[23], "c3");
|
---|
| 568 | mayhave(&FKEY[24], "c4");
|
---|
| 569 | mayhave(&FKEY[25], "c5");
|
---|
| 570 | mayhave(&FKEY[26], "c6");
|
---|
| 571 | mayhave(&FKEY[27], "c7");
|
---|
| 572 | mayhave(&FKEY[28], "c8");
|
---|
| 573 | mayhave(&FKEY[29], "c9");
|
---|
| 574 | # ifndef NO_ALT_FKEY
|
---|
| 575 | mayhave(&FKEY[30], "a0"); /* alt function key codes */
|
---|
| 576 | mayhave(&FKEY[31], "a1");
|
---|
| 577 | mayhave(&FKEY[32], "a2");
|
---|
| 578 | mayhave(&FKEY[33], "a3");
|
---|
| 579 | mayhave(&FKEY[34], "a4");
|
---|
| 580 | mayhave(&FKEY[35], "a5");
|
---|
| 581 | mayhave(&FKEY[36], "a6");
|
---|
| 582 | mayhave(&FKEY[37], "a7");
|
---|
| 583 | mayhave(&FKEY[38], "a8");
|
---|
| 584 | mayhave(&FKEY[39], "a9");
|
---|
| 585 | # endif
|
---|
| 586 | # endif
|
---|
| 587 | # endif
|
---|
| 588 | #endif
|
---|
| 589 |
|
---|
| 590 | #ifndef NO_CURSORSHAPE
|
---|
| 591 | /* cursor shapes */
|
---|
| 592 | CQ = tgetstr("cQ", &capbuf);
|
---|
| 593 | if (has_CQ)
|
---|
| 594 | {
|
---|
| 595 | CX = tgetstr("cX", &capbuf);
|
---|
| 596 | if (!CX) CX = CQ;
|
---|
| 597 | CV = tgetstr("cV", &capbuf);
|
---|
| 598 | if (!CV) CV = CQ;
|
---|
| 599 | CI = tgetstr("cI", &capbuf);
|
---|
| 600 | if (!CI) CI = CQ;
|
---|
| 601 | CR = tgetstr("cR", &capbuf);
|
---|
| 602 | if (!CR) CR = CQ;
|
---|
| 603 | }
|
---|
| 604 | # ifndef CRUNCH
|
---|
| 605 | else
|
---|
| 606 | {
|
---|
| 607 | CQ = CV = "";
|
---|
| 608 | pair(&CQ, &CV, "ve", "vs");
|
---|
| 609 | CX = CI = CR = CQ;
|
---|
| 610 | }
|
---|
| 611 | # endif /* !CRUNCH */
|
---|
| 612 | #endif /* !NO_CURSORSHAPE */
|
---|
| 613 |
|
---|
| 614 | #ifndef NO_COLOR
|
---|
| 615 | strcpy(SOcolor, SO);
|
---|
| 616 | strcpy(SEcolor, SE);
|
---|
| 617 | strcpy(AScolor, AS);
|
---|
| 618 | strcpy(AEcolor, AE);
|
---|
| 619 | strcpy(MDcolor, MD);
|
---|
| 620 | strcpy(MEcolor, ME);
|
---|
| 621 | strcpy(UScolor, US);
|
---|
| 622 | strcpy(UEcolor, UE);
|
---|
| 623 | # ifndef NO_POPUP
|
---|
| 624 | strcpy(POPUPcolor, SO);
|
---|
| 625 | # endif
|
---|
| 626 | # ifndef NO_VISIBLE
|
---|
| 627 | strcpy(VISIBLEcolor, MV);
|
---|
| 628 | # endif
|
---|
| 629 | #endif
|
---|
| 630 |
|
---|
| 631 | }
|
---|
| 632 |
|
---|
| 633 |
|
---|
| 634 | /* This function gets the window size. It uses the TIOCGWINSZ ioctl call if
|
---|
| 635 | * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
|
---|
| 636 | * This function is called once during initialization, and thereafter it is
|
---|
| 637 | * called whenever the SIGWINCH signal is sent to this process.
|
---|
| 638 | */
|
---|
| 639 | int getsize(signo)
|
---|
| 640 | int signo;
|
---|
| 641 | {
|
---|
| 642 | int lines;
|
---|
| 643 | int cols;
|
---|
| 644 | #ifdef TIOCGWINSZ
|
---|
| 645 | struct winsize size;
|
---|
| 646 | #endif
|
---|
| 647 |
|
---|
| 648 | #ifdef SIGWINCH
|
---|
| 649 | /* reset the signal vector */
|
---|
| 650 | signal(SIGWINCH, getsize);
|
---|
| 651 | #endif
|
---|
| 652 |
|
---|
| 653 | /* get the window size, one way or another. */
|
---|
| 654 | lines = cols = 0;
|
---|
| 655 | #ifdef TIOCGWINSZ
|
---|
| 656 | if (ioctl(2, TIOCGWINSZ, &size) >= 0)
|
---|
| 657 | {
|
---|
| 658 | lines = size.ws_row;
|
---|
| 659 | cols = size.ws_col;
|
---|
| 660 | }
|
---|
| 661 | #endif
|
---|
| 662 | #if AMIGA
|
---|
| 663 | /* Amiga gets window size by asking the console.device */
|
---|
| 664 | if (!strcmp(TERMTYPE, termtype))
|
---|
| 665 | {
|
---|
| 666 | auto long len;
|
---|
| 667 | auto char buf[30];
|
---|
| 668 |
|
---|
| 669 | Write(Output(), "\2330 q", 4); /* Ask the console.device */
|
---|
| 670 | len = Read(Input(), buf, 29);
|
---|
| 671 | buf[len] = '\000';
|
---|
| 672 | sscanf(&buf[5], "%d;%d", &lines, &cols);
|
---|
| 673 | }
|
---|
| 674 | #endif
|
---|
| 675 | if ((lines == 0 || cols == 0) && signo == 0)
|
---|
| 676 | {
|
---|
| 677 | LINES = tgetnum("li");
|
---|
| 678 | COLS = tgetnum("co");
|
---|
| 679 | }
|
---|
| 680 | #if MSDOS
|
---|
| 681 | # ifdef RAINBOW
|
---|
| 682 | if (!strcmp(termtype, "rainbow"))
|
---|
| 683 | {
|
---|
| 684 | /* Determine whether Rainbow is in 80-column or 132-column mode */
|
---|
| 685 | cols = *(unsigned char far *)0xee000f57L;
|
---|
| 686 | }
|
---|
| 687 | else
|
---|
| 688 | # endif
|
---|
| 689 | {
|
---|
| 690 | lines = v_rows();
|
---|
| 691 | cols = v_cols();
|
---|
| 692 | }
|
---|
| 693 | #endif
|
---|
| 694 | if (lines >= 2)
|
---|
| 695 | {
|
---|
| 696 | LINES = lines;
|
---|
| 697 | }
|
---|
| 698 |
|
---|
| 699 | if (cols >= 30)
|
---|
| 700 | {
|
---|
| 701 | COLS = cols;
|
---|
| 702 | }
|
---|
| 703 |
|
---|
| 704 | /* Make sure we got values that we can live with */
|
---|
| 705 | if (LINES < 2 || COLS < 30)
|
---|
| 706 | {
|
---|
| 707 | write(2, "Screen too small\n", (unsigned)17);
|
---|
| 708 | #if OSK
|
---|
| 709 | write(2, "\l", 1);
|
---|
| 710 | #endif
|
---|
| 711 | endwin();
|
---|
| 712 | exit(2);
|
---|
| 713 | }
|
---|
| 714 |
|
---|
| 715 | #if AMIGA
|
---|
| 716 | if (*o_lines != LINES || *o_columns != COLS)
|
---|
| 717 | {
|
---|
| 718 | *o_lines = LINES;
|
---|
| 719 | *o_columns = COLS;
|
---|
| 720 | }
|
---|
| 721 | #endif
|
---|
| 722 |
|
---|
| 723 | return 0;
|
---|
| 724 | }
|
---|
| 725 |
|
---|
| 726 |
|
---|
| 727 | /* This is a function version of addch() -- it is used by tputs() */
|
---|
| 728 | int faddch(ch)
|
---|
| 729 | int ch;
|
---|
| 730 | {
|
---|
| 731 | addch(ch);
|
---|
| 732 |
|
---|
| 733 | return 0;
|
---|
| 734 | }
|
---|
| 735 |
|
---|
| 736 | /* This function quickly adds a string to the output queue. It does *NOT*
|
---|
| 737 | * convert \n into <CR><LF>.
|
---|
| 738 | */
|
---|
| 739 | void qaddstr(str)
|
---|
| 740 | char *str;
|
---|
| 741 | {
|
---|
| 742 | REG char *s_, *d_;
|
---|
| 743 |
|
---|
| 744 | #if MSDOS
|
---|
| 745 | if (o_pcbios[0])
|
---|
| 746 | {
|
---|
| 747 | while (*str)
|
---|
| 748 | qaddch(*str++);
|
---|
| 749 | return;
|
---|
| 750 | }
|
---|
| 751 | #endif
|
---|
| 752 | for (s_=(str), d_=stdscr; *d_++ = *s_++; )
|
---|
| 753 | {
|
---|
| 754 | }
|
---|
| 755 | stdscr = d_ - 1;
|
---|
| 756 | }
|
---|
| 757 |
|
---|
| 758 | /* Output the ESC sequence needed to go into any video mode, if supported */
|
---|
| 759 | void attrset(a)
|
---|
| 760 | int a;
|
---|
| 761 | {
|
---|
| 762 | do_aend();
|
---|
| 763 | if (a == A_BOLD)
|
---|
| 764 | {
|
---|
| 765 | do_MD();
|
---|
| 766 | aend = ME;
|
---|
| 767 | }
|
---|
| 768 | else if (a == A_UNDERLINE)
|
---|
| 769 | {
|
---|
| 770 | do_US();
|
---|
| 771 | aend = UE;
|
---|
| 772 | }
|
---|
| 773 | else if (a == A_ALTCHARSET)
|
---|
| 774 | {
|
---|
| 775 | do_AS();
|
---|
| 776 | aend = AE;
|
---|
| 777 | }
|
---|
| 778 | else
|
---|
| 779 | {
|
---|
| 780 | aend = "";
|
---|
| 781 | }
|
---|
| 782 | }
|
---|
| 783 |
|
---|
| 784 |
|
---|
| 785 | /* Insert a single character into the display */
|
---|
| 786 | void insch(ch)
|
---|
| 787 | int ch;
|
---|
| 788 | {
|
---|
| 789 | if (has_IM)
|
---|
| 790 | do_IM();
|
---|
| 791 | do_IC();
|
---|
| 792 | qaddch(ch);
|
---|
| 793 | if (has_EI)
|
---|
| 794 | do_EI();
|
---|
| 795 | }
|
---|
| 796 |
|
---|
| 797 | void wrefresh()
|
---|
| 798 | {
|
---|
| 799 | if (stdscr != kbuf)
|
---|
| 800 | {
|
---|
| 801 | VOIDBIOS(;,ttywrite(kbuf, (unsigned)(stdscr - kbuf)));
|
---|
| 802 | stdscr = kbuf;
|
---|
| 803 | }
|
---|
| 804 | }
|
---|
| 805 |
|
---|
| 806 | void wqrefresh()
|
---|
| 807 | {
|
---|
| 808 | if (stdscr - kbuf > 2000)
|
---|
| 809 | {
|
---|
| 810 | VOIDBIOS(stdscr = kbuf,
|
---|
| 811 | {
|
---|
| 812 | ttywrite(kbuf, (unsigned)(stdscr - kbuf));
|
---|
| 813 | stdscr = kbuf;
|
---|
| 814 | });
|
---|
| 815 | }
|
---|
| 816 | }
|
---|
| 817 |
|
---|
| 818 | #ifndef NO_COLOR
|
---|
| 819 | /* This function is called during termination. It resets color modes */
|
---|
| 820 | int ansiquit()
|
---|
| 821 | {
|
---|
| 822 | /* if ANSI color terminal, then reset the colors */
|
---|
| 823 | if (!strcmp(UP, "\033[A"))
|
---|
| 824 | {
|
---|
| 825 | tputs("\033[37;40m\033[m", 1, faddch);
|
---|
| 826 | clrtoeol();
|
---|
| 827 | return 1;
|
---|
| 828 | }
|
---|
| 829 | return 0;
|
---|
| 830 | }
|
---|
| 831 |
|
---|
| 832 | /* This sets the color strings that work for ANSI terminals. If the TERMCAP
|
---|
| 833 | * doesn't look like an ANSI terminal, then it returns FALSE. If the colors
|
---|
| 834 | * aren't understood, it also returns FALSE. If all goes well, it returns TRUE
|
---|
| 835 | */
|
---|
| 836 | int ansicolor(cmode, attrbyte)
|
---|
| 837 | int cmode; /* mode to set, e.g. A_NORMAL */
|
---|
| 838 | int attrbyte; /* IBM PC attribute byte */
|
---|
| 839 | {
|
---|
| 840 | char temp[16]; /* hold the new mode string */
|
---|
| 841 |
|
---|
| 842 | /* if not ANSI-ish, then fail */
|
---|
| 843 | if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
|
---|
| 844 | {
|
---|
| 845 | msg("Don't know how to set colors for this terminal");
|
---|
| 846 | return 0;
|
---|
| 847 | }
|
---|
| 848 |
|
---|
| 849 | /* construct the color string */
|
---|
| 850 | sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
|
---|
| 851 | "04261537"[attrbyte & 0x07],
|
---|
| 852 | "04261537"[(attrbyte >> 4) & 0x07],
|
---|
| 853 | (attrbyte & 0x08) ? ";1" : "",
|
---|
| 854 | (attrbyte & 0x80) ? ";5" : "");
|
---|
| 855 |
|
---|
| 856 | /* stick it in the right place */
|
---|
| 857 | switch (cmode)
|
---|
| 858 | {
|
---|
| 859 | case A_NORMAL:
|
---|
| 860 | if (!strcmp(MEcolor, normalcolor))
|
---|
| 861 | strcpy(MEcolor, temp);
|
---|
| 862 | if (!strcmp(UEcolor, normalcolor))
|
---|
| 863 | strcpy(UEcolor, temp);
|
---|
| 864 | if (!strcmp(AEcolor, normalcolor))
|
---|
| 865 | strcpy(AEcolor, temp);
|
---|
| 866 | if (!strcmp(SEcolor, normalcolor))
|
---|
| 867 | strcpy(SEcolor, temp);
|
---|
| 868 |
|
---|
| 869 | strcpy(normalcolor, temp);
|
---|
| 870 | tputs(normalcolor, 1, faddch);
|
---|
| 871 | break;
|
---|
| 872 |
|
---|
| 873 | case A_BOLD:
|
---|
| 874 | strcpy(MDcolor, temp);
|
---|
| 875 | strcpy(MEcolor, normalcolor);
|
---|
| 876 | break;
|
---|
| 877 |
|
---|
| 878 | case A_UNDERLINE:
|
---|
| 879 | strcpy(UScolor, temp);
|
---|
| 880 | strcpy(UEcolor, normalcolor);
|
---|
| 881 | break;
|
---|
| 882 |
|
---|
| 883 | case A_ALTCHARSET:
|
---|
| 884 | strcpy(AScolor, temp);
|
---|
| 885 | strcpy(AEcolor, normalcolor);
|
---|
| 886 | break;
|
---|
| 887 |
|
---|
| 888 | case A_STANDOUT:
|
---|
| 889 | strcpy(SOcolor, temp);
|
---|
| 890 | strcpy(SEcolor, normalcolor);
|
---|
| 891 | break;
|
---|
| 892 |
|
---|
| 893 | #ifndef NO_POPUP
|
---|
| 894 | case A_POPUP:
|
---|
| 895 | strcpy(POPUPcolor, temp);
|
---|
| 896 | break;
|
---|
| 897 | #endif
|
---|
| 898 |
|
---|
| 899 | #ifndef NO_VISIBLE
|
---|
| 900 | case A_VISIBLE:
|
---|
| 901 | strcpy(VISIBLEcolor, temp);
|
---|
| 902 | break;
|
---|
| 903 | #endif
|
---|
| 904 | }
|
---|
| 905 |
|
---|
| 906 | return 1;
|
---|
| 907 | }
|
---|
| 908 |
|
---|
| 909 |
|
---|
| 910 | /* This function outputs the ESC sequence needed to switch the screen back
|
---|
| 911 | * to "normal" mode. On color terminals which haven't had their color set
|
---|
| 912 | * yet, this is one of the termcap strings; for color terminals that really
|
---|
| 913 | * have had colors defined, we just the "normal color" escape sequence.
|
---|
| 914 | */
|
---|
| 915 | endcolor()
|
---|
| 916 | {
|
---|
| 917 | if (aend == ME)
|
---|
| 918 | tputs(MEcolor, 1, faddch);
|
---|
| 919 | else if (aend == UE)
|
---|
| 920 | tputs(UEcolor, 1, faddch);
|
---|
| 921 | else if (aend == AE)
|
---|
| 922 | tputs(AEcolor, 1, faddch);
|
---|
| 923 | else if (aend == SE)
|
---|
| 924 | tputs(SEcolor, 1, faddch);
|
---|
| 925 | aend = "";
|
---|
| 926 | return 0;
|
---|
| 927 | }
|
---|
| 928 |
|
---|
| 929 |
|
---|
| 930 | #endif /* !NO_COLOR */
|
---|