home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / e / elv17src.zip / CURSES.C < prev    next >
C/C++ Source or Header  |  1992-12-30  |  24KB  |  1,047 lines

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