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