home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / CURSES.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  11KB  |  524 lines

  1. #ifdef linux
  2. #include <ncurses.h>
  3. #else
  4. #include <curses.h>
  5. #endif
  6. #include <term.h>
  7. #undef FALSE
  8. #undef TRUE
  9.   
  10. #define SCREEN_INTERNAL
  11. #include "hardware.h"
  12.   
  13. #include "proc.h"
  14. #include "socket.h"
  15. #undef tputs
  16.   
  17. #include "tty.h"
  18.   
  19. extern int Numrows, Numcols;
  20.   
  21. static WINDOW *curwin, *curss;
  22. static int in_ss;
  23.   
  24. struct keytrie
  25. {
  26.     enum {KT_DEF, KT_TRIE, KT_VAL} kt_type;
  27.     union
  28.     {
  29.         struct keytrie *ktu_trie;
  30. #define kt_trie kt_u.ktu_trie
  31.         int ktu_val;
  32. #define kt_val kt_u.ktu_val
  33.     } kt_u;
  34. };
  35.   
  36. static struct keytrie *keys;
  37.   
  38. static void
  39. key_init()
  40. {
  41.     int i;
  42.   
  43.     keys = mallocw(256 * sizeof *keys);
  44.     for (i = 256; i--; )
  45.     {
  46.         keys[i].kt_type = KT_DEF;
  47.         keys[i].kt_val = i;
  48.     }
  49. }
  50.   
  51. static void
  52. key_add(str, val)
  53. const char *str;
  54. int val;
  55. {
  56.     const char *old;
  57.     struct keytrie *t;
  58.     int c, i;
  59.   
  60.     /*
  61.      * Follow the trie until we get to the right subtrie for the string, then
  62.      * add the value.  If we hit a KT_DEF, expand the trie.  If we hit a KT_VAL
  63.      * we have a conflict; drop the key on the floor.  (We can't use timeouts.)
  64.      * (Well, actually, we could, but I'll be darned if *I* want to write it!)
  65.      */
  66.     if (!str || !*str)
  67.         return;         /* no key to define */
  68.     old = str;
  69.     t = keys;
  70.     while (str[1])
  71.     {
  72.         c = uchar(*str++);
  73.         if (t[c].kt_type == KT_DEF)
  74.         {
  75.             t[c].kt_type = KT_TRIE;
  76.             t[c].kt_trie = mallocw(256 * sizeof (struct keytrie));
  77.             for (i = 256; i--; )
  78.             {
  79.                 t[c].kt_trie[i].kt_type = KT_DEF;
  80.                 t[c].kt_trie[i].kt_val = i;
  81.             }
  82.         }
  83.         else if (t[c].kt_type != KT_TRIE)
  84.             return;
  85.         t = t[c].kt_trie;
  86.     }
  87.     c = uchar(*str);
  88.     if (t[c].kt_type == KT_TRIE)
  89.         return;
  90.     t[c].kt_type = KT_VAL;
  91.     t[c].kt_val = val;
  92. }
  93.   
  94. void
  95. ioinit()
  96. {
  97.     initscr();
  98.     nonl();
  99.     raw();
  100.     noecho();
  101.     Numrows = LINES;
  102.     Numcols = COLS;
  103.     init_sys();
  104.     /* build a trie of function keys */
  105.     key_init();
  106.     key_add(key_down, DNARROW);
  107.     key_add(key_f0, -3);
  108.     key_add(key_f1, -4);
  109.     key_add(key_f2, -5);
  110.     key_add(key_f3, -6);
  111.     key_add(key_f4, -7);
  112.     key_add(key_f5, -8);
  113.     key_add(key_f6, -9);
  114.     key_add(key_f7, -10);
  115.     key_add(key_f8, -11);
  116.     key_add(key_f9, -2);    /* F10 traditionally is NOS escape */
  117.     key_add(key_left, LTARROW);
  118.     key_add(key_right, RTARROW);
  119.     key_add(key_up, UPARROW);
  120.     key_add("\177", '\b');  /* so DEL behaves as BS */
  121. }
  122.   
  123. void
  124. iostop()
  125. {
  126.     deinit_sys();
  127.     endwin();
  128. }
  129.   
  130. void
  131. swapscreen(old, new)
  132. struct session *old, *new;
  133. {
  134.     if (old == new)
  135.         return;
  136.     if (old != NULLSESSION && old->screen != NULLSCREEN)
  137.         old->screen->in_ss = in_ss;
  138.     if (new != NULLSESSION && new->screen != NULLSCREEN)
  139.     {
  140.         curwin = new->screen->win;
  141.         clearok(curwin, TRUE);
  142.         touchwin(curwin);
  143.         wnoutrefresh(curwin);
  144.         if (!new->split || !new->screen->sswin)
  145.             curss = 0;
  146.         else
  147.         {
  148.             curss = new->screen->sswin;
  149.             touchwin(curss);
  150.             wnoutrefresh(curss);
  151.         }
  152.         in_ss = new->screen->in_ss;
  153.     }
  154. }
  155.   
  156. static int
  157. in_split(s)
  158. struct session *s;
  159. {
  160.     return s->screen->in_ss;
  161. }
  162.   
  163. void
  164. putch(c)
  165. int c;
  166. {
  167.     WINDOW *w;
  168.     int x, y;
  169.   
  170.     if (in_ss && curss)
  171.         w = curss;
  172.     else
  173.         w = curwin;
  174.     if (c == 7)
  175.         write(1, "\7", 1);
  176.     else if (c == '\r' || c == '\t' || c == '\b')
  177.         waddch(w, c);
  178.     else if (c == '\n')
  179.     {
  180.     /* waddch() does clrtoeol() implicitly.  This breaks us. */
  181.         getyx(w, y, x);
  182.         if (++y > w->_regbottom)
  183.         {
  184.             y--;
  185.             scroll(w);
  186.         }
  187.         wmove(w, y, 0);
  188.     }
  189.     else if (c < 32)
  190.         return;
  191.     else if (c > 126)
  192.         return;
  193.     else
  194.         waddch(w, c);
  195. }
  196.   
  197. void
  198. sputch(s, c)
  199. struct session *s;
  200. int c;
  201. {
  202.     WINDOW *w;
  203.     int x, y;
  204.   
  205.     if (in_split(s) && s->screen->sswin)
  206.         w = s->screen->sswin;
  207.     else
  208.         w = s->screen->win;
  209.     if (c == 7)
  210.         write(1, "\7", 1);
  211.     else if (c == '\r' || c == '\t' || c == '\b')
  212.         waddch(w, c);
  213.     else if (c == '\n')
  214.     {
  215.     /* waddch() does clrtoeol() implicitly.  This breaks us. */
  216.         getyx(w, y, x);
  217.         if (++y > w->_regbottom)
  218.         {
  219.             y--;
  220.             scroll(w);
  221.         }
  222.         wmove(w, y, 0);
  223.     }
  224.     else if (c < 32)
  225.         return;
  226.     else if (c > 126)
  227.         return;
  228.     else
  229.         waddch(w, c);
  230. }
  231.   
  232. void
  233. cputs(s)
  234. char *s;
  235. {
  236.     if (in_ss && curss)
  237.         waddstr(curss, s);
  238.     else
  239.         waddstr(curwin, s);
  240. }
  241.   
  242. void
  243. scputs(ses, s)
  244. struct session *ses;
  245. char *s;
  246. {
  247.     if (in_split(ses) && ses->screen->sswin)
  248.         waddstr(ses->screen->sswin, s);
  249.     else
  250.         waddstr(ses->screen->win, s);
  251. }
  252.   
  253. void
  254. clreol()
  255. {
  256.     if (in_ss && curss)
  257.         wclrtoeol(curss);
  258.     else
  259.         wclrtoeol(curwin);
  260. }
  261.   
  262. void
  263. sclreol(s)
  264. struct session *s;
  265. {
  266.     if (in_split(s) && s->screen->sswin)
  267.         wclrtoeol(s->screen->sswin);
  268.     else
  269.         wclrtoeol(s->screen->win);
  270. }
  271.   
  272. /*
  273.  * The display process.  Under *ix, all output goes to curses windows; since
  274.  * I/O is buffered until a wrefresh(), we don't need to limit ourselves to the
  275.  * current window and block other windows' I/O.  (A window sleeping on a More?
  276.  * is the exception; but it's blocking on the keyboard, not the display.)
  277.  * This does mean that you might lose information if you don't have "more"
  278.  * enabled on a window; I don't think this matters much.
  279.  *
  280.  * Note that the real work is done by rflush().  The Display process no longer
  281.  * exists.
  282.  */
  283.   
  284. void
  285. rflush()
  286. {
  287.     struct session *sp;
  288.     int i, c, cnt;
  289.   
  290.     for (sp = Sessions, i = 0; i < Nsessions; sp++, i++)
  291.     {
  292.         if (sp->type == FREE)
  293.             continue;
  294.         if (!sp->screen || !sp->screen->win) /* "shouldn't happen" */
  295.             continue;
  296.         if (sp->morewait == 1) /* More prompt, no key yet */
  297.             continue;
  298.         if (sp->morewait == 2)
  299.         {
  300.             sp->morewait = 0;
  301.             sputch(sp, '\r');
  302.             sclreol(sp);
  303.         }
  304.         cnt = 0;
  305.         while (socklen(sp->output, 0) > 0)
  306.         {
  307.             if ((c = rrecvchar(sp->output)) == -1)
  308.                 continue;
  309.             cnt++;
  310.             if (!sp->split || c != 0x0a)
  311.                 sputch(sp, c);
  312.             else
  313.             {
  314.                 scputs(sp, Eol);
  315.                 sclreol(sp);
  316.             }
  317.             if (sp->record != NULLFILE)
  318.             {
  319.                 if (c == '\r' || c == '\n')
  320.                     fflush(sp->record);
  321.                 if (c != '\r' || sockmode(sp->output, -1) != SOCK_ASCII)
  322.                     putc(c, sp->record);
  323.             }
  324.             if (sp->flowmode && c == '\n' && --sp->row <= 0)
  325.             {
  326.                 scputs(sp, "--More--");
  327.                 sp->morewait = 1;
  328.                 break;
  329.             }
  330.         }
  331.     }
  332.     if (curwin)
  333.         wnoutrefresh(curwin);
  334.     if (curss)
  335.         wnoutrefresh(curss);
  336.     doupdate();
  337. }
  338.   
  339. void
  340. j_newscreen(sp)
  341. struct session *sp;
  342. {
  343.     if (sp == NULLSESSION)
  344.         return;
  345.     sp->screen = mallocw(sizeof *sp->screen);
  346.     curwin = sp->screen->win = newwin(LINES - (sp->split? 2: 0), COLS, 0, 0);
  347.     scrollok(curwin, TRUE);
  348.     in_ss = 0;
  349.     sp->screen->in_ss = 0;
  350.     if (sp->split)
  351.     {
  352.         sp->screen->sswin = newwin(2, COLS, LINES - 2, 0);
  353.         curss = sp->screen->sswin;
  354.         scrollok(curss, TRUE);
  355.     }
  356.     else
  357.     {
  358.         sp->screen->sswin = 0;
  359.         curss = 0;
  360.     }
  361. }
  362.   
  363. void
  364. freescreen(sp)
  365. struct session *sp;
  366. {
  367.     if (sp == NULLSESSION || sp->screen == NULLSCREEN)
  368.         return;
  369.     delwin(sp->screen->win);
  370.     if (sp->screen->sswin)
  371.         delwin(sp->screen->sswin);
  372.     j_free(sp->screen);
  373. }
  374.   
  375. /* Now we come to the emulation of the PC console as seen by Turbo C (bleah) */
  376.   
  377. void
  378. clrscr()
  379. {
  380.     wclear(curwin);
  381.     if (curss)
  382.         werase(curss);
  383. }
  384.   
  385. int
  386. wherex()
  387. {
  388.     int x, y;
  389.   
  390.     if (in_ss && curss)
  391.         getyx(curss, y, x);
  392.     else
  393.         getyx(curwin, y, x);
  394.     return x + 1;
  395. }
  396.   
  397. int
  398. wherey()
  399. {
  400.     int x, y;
  401.   
  402.     if (in_ss && curss)
  403.     {
  404.         getyx(curss, y, x);
  405.         y += LINES - 2;
  406.     }
  407.     else
  408.         getyx(curwin, y, x);
  409.     return y + 1;
  410. }
  411.   
  412. void
  413. window(x, y, w, h)
  414. int x, y, w, h;
  415. {
  416.     in_ss = (y == LINES - 1);
  417. }
  418.   
  419. void
  420. gotoxy(x, y)
  421. int x, y;
  422. {
  423.     if (in_ss && curss)
  424.         wmove(curss, y - LINES + 1, x - 1);
  425.     else
  426.         wmove(curwin, y - 1, x - 1);
  427. }
  428.   
  429. void
  430. highvideo()
  431. {
  432.     if (in_ss && curss)
  433.         wstandout(curss);
  434.     else
  435.         wstandout(curwin);
  436. }
  437.   
  438. void
  439. normvideo()
  440. {
  441.     if (in_ss && curss)
  442.         wstandend(curss);
  443.     else
  444.         wstandend(curwin);
  445. }
  446.   
  447. void
  448. _setcursortype(t)
  449. int t;
  450. {
  451.     curs_set(t);
  452. }
  453.   
  454. /*
  455.  * Read from the keyboard, "blocking" via the NOS scheduler.
  456.  * We handle function keys ourselves:  curses wants to use alarms to do it,
  457.  * which is somewhat dangerous in this case because it leaves us waiting on
  458.  * a tick from a nonexistent timer (curses doesn't bother checking to see if
  459.  * someone's got an alarm pending).
  460.  */
  461.   
  462. static int
  463. kbchar()
  464. {
  465.     extern int Keyboard;
  466.     unsigned char ch;
  467.     int i;
  468.   
  469.     do
  470.     {
  471.         pwait(&Keyboard);
  472.     }
  473.     while ((i = read(0, &ch, 1)) == 0 || (i == -1 && errno == EWOULDBLOCK));
  474.     if (i < 0)
  475.     {
  476.         tprintf("NOS PANIC: Lost keyboard\n");
  477.         where_outta_here(1);
  478.     }
  479.     return ch;
  480. }
  481.   
  482. int
  483. kbread()
  484. {
  485.     static int ungets[10];
  486.     struct keytrie *t;
  487.     static int unget;
  488.     int ungetc[10];
  489.     int c, i, u;
  490.   
  491.     i = 0;
  492.     u = 0;
  493.     if (unget > i)
  494.         c = ungets[i++];
  495.     else
  496.         c = kbchar();
  497.     ungetc[u++] = c;
  498.     t = keys;
  499.     while (t[c].kt_type == KT_TRIE)
  500.     {
  501.         t = t[c].kt_trie;
  502.         if (unget > i)
  503.             c = ungets[i++];
  504.         else
  505.             c = kbchar();
  506.         ungetc[u++] = c;
  507.     }
  508.     if (t[c].kt_type == KT_VAL)
  509.     {
  510.         u = 0;
  511.         c = t[c].kt_val;
  512.     }
  513.     while (i < unget)
  514.         ungetc[u++] = ungets[i++];
  515.     if (u)
  516.     {
  517.         c = ungetc[0];
  518.         for (i = u; i; i--)
  519.             ungets[i - 1] = ungetc[i];
  520.         unget = u - 1;
  521.     }
  522.     return c;
  523. }
  524.