home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume2 / window / part2 / curses.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  10.8 KB  |  504 lines

  1. /*
  2.  *************
  3.  * DISTRIBUTION NOTICE  July 30 1985
  4.  * A Revised Edition of WM, by Matt Lennon and Tom Truscott,
  5.  *        Research Triangle Institute, (919) 541-7005.
  6.  * Based on the original by Robert Jacob (decvax!nrl-css!jacob),
  7.  *        Naval Research Laboratory, (202) 767-3365.
  8.  * No claims or warranties of any sort are made for this distribution.
  9.  * General permission is granted to copy, but not for profit,
  10.  * any of this distribution, provided that this notice
  11.  * is always included in the copies.
  12.  *************
  13.  */
  14. /*
  15.  * curses.c  R. Jacob
  16.  */
  17.  
  18. #include "wm.h"
  19.  
  20. static WINDOW *mw=NULL;        /* message window */
  21. static WINDOW *cmw=NULL;    /* blank message window */
  22. time_t msgbirth = 0;
  23.  
  24.  
  25. /*
  26.  * Set up win structure and associated junk for new window w.
  27.  * Returns 0 if sucessful, else -1.
  28.  */
  29. NewWindow(w, lines, cols, begline, begcol)
  30.  
  31. register int w;
  32. int lines, cols, begline, begcol;
  33. {
  34.     register WINDOW *wp, *owp;
  35.  
  36.  
  37.     if ((wp=newwin(lines,cols,begline,begcol)) == NULL) {
  38.     showmsg("\007Cannot %sconstruct window #%d!.",
  39.         ((win[w].flags&INUSE)? "re": ""), w);
  40.     FreeWindow(w);
  41.     return(-1);
  42.     }
  43.     leaveok(wp, TRUE);
  44.  
  45.     /* If the window is already in use, copy old window to new one
  46.      * anchored at bottom left of the windows.
  47.      * We move the bottom left of both windows to the bottom left
  48.      * of the screen, overwrite, then move the windows back.
  49.      * (Actually, we do not bother to move the old window back.)
  50.      */
  51.     if (win[w].flags&INUSE) {
  52.     owp = win[w].wptr;
  53.     mvwin(owp, LINES-wlines(owp), 0);
  54.     mvwin(wp, LINES-wlines(wp), 0);
  55.     overwrite(owp, wp);
  56.     mvwin(wp, begline, begcol);
  57.     wmove(wp, wcury(owp) + (wlines(wp)-wlines(owp)), wcurx(owp));
  58.     FreeWindow(w);
  59.     }
  60.  
  61.     win[w].wptr = wp;
  62.  
  63.     if (MakeBorders(w) != 0)
  64.     {
  65.     showmsg("\007Cannot construct borders for window #%d!.", w);
  66.     FreeWindow(w);
  67.     return(-1);
  68.     }
  69.  
  70.     win[w].flags |= INUSE;
  71.     if (has_scroll_window
  72.      || (cols == COLS
  73.       && (has_scroll_region || has_insdel_line || lines == LINES-1)))
  74.     win[w].flags |= FAST;
  75.  
  76.     return(0);
  77. }
  78.  
  79. /*
  80.  * Deallocate win structure and associated junk.
  81.  */
  82. FreeWindow(w)
  83.  
  84. register int w;
  85. {
  86.     win[w].flags = 0;
  87.  
  88.     if (win[w].wptr)     {delwin(win[w].wptr);     win[w].wptr = 0;}
  89.     if (win[w].boxbot)     {delwin(win[w].boxbot);   win[w].boxbot = 0;}
  90.     if (win[w].boxtop)     {delwin(win[w].boxtop);   win[w].boxtop = 0;}
  91.     if (win[w].boxright) {delwin(win[w].boxright); win[w].boxright = 0;}
  92.     if (win[w].boxleft)     {delwin(win[w].boxleft);  win[w].boxleft = 0;}
  93. }
  94.  
  95. #ifdef notdef
  96. /*
  97.  * Redraw window w.
  98.  */
  99. RedrawWindow(w)
  100.  
  101. register int w;
  102. {
  103.     register WINDOW *wp;
  104.  
  105.     if (!iswindow(w))
  106.     return;
  107.     if (wp=win[w].wptr)     { touchwin(wp); wrefresh(wp); }
  108.     if (wp=win[w].boxbot)   { touchwin(wp); wrefresh(wp); }
  109.     if (wp=win[w].boxtop)   { touchwin(wp); wrefresh(wp); }
  110.     if (wp=win[w].boxright) { touchwin(wp); wrefresh(wp); }
  111.     if (wp=win[w].boxleft)  { touchwin(wp); wrefresh(wp); }
  112. }
  113. #endif
  114.  
  115. /*
  116.  * Redraw the entire screen.
  117.  * Uses Curses' standard screen, stdscr.
  118.  */
  119. RedrawScreen()
  120. {
  121.     register int w, base;
  122.     register WINDOW *wp;
  123.  
  124.     /* speed hack: start with the topmost full-screen window.
  125.      * (Smarter hacks come to mind, but this one is easy.)
  126.      */
  127.     base = botw;
  128.     for (w=base; w>=0; w=win[w].next)
  129.     if ((wp = win[w].wptr) && wcols(wp) == COLS && wlines(wp) >= LINES-1)
  130.         base = w;
  131.  
  132.     werase(stdscr);
  133.  
  134.      /* Write contents of all windows into stdscr, then refresh.
  135.       */
  136.     for (w=base; w>=0; w=win[w].next)
  137.     {
  138.     if (wp=win[w].wptr)     overwrite(wp, stdscr);
  139.     if (wp=win[w].boxtop)   overwrite(wp, stdscr);
  140.     if (wp=win[w].boxbot)   overwrite(wp, stdscr);
  141.     if (wp=win[w].boxright) overwrite(wp, stdscr);
  142.     if (wp=win[w].boxleft)  overwrite(wp, stdscr);
  143.     }
  144.  
  145.     if (msgbirth)
  146.     overwrite(mw, stdscr);
  147.     touchwin(stdscr);
  148.     wrefresh(stdscr);
  149.     RestoreCursor();
  150. }
  151.  
  152. /*
  153.  * Identify windows.
  154.  * Draw each window in turn, from bottom to top.
  155.  * Uses Curses' standard screen, stdscr.
  156.  */
  157. IdentWindows()
  158. {
  159.     register int w;    /* window index */
  160.     register WINDOW *wp;
  161.     register int canceled=FALSE; /* TRUE if user cancels this command */
  162.     register int c;
  163.  
  164.  
  165.      /* Erase the screen (and stdscr).
  166.       */
  167.     ClearScreen();
  168.  
  169.      /* Write contents of each window into stdscr, then refresh.
  170.       */
  171.     for (w=botw; w>=0; w=win[w].next)
  172.     {
  173.     if (wp=win[w].wptr)     overwrite(wp, stdscr);
  174.     if (wp=win[w].boxtop)   overwrite(wp, stdscr);
  175.     if (wp=win[w].boxbot)   overwrite(wp, stdscr);
  176.     if (wp=win[w].boxright) overwrite(wp, stdscr);
  177.     if (wp=win[w].boxleft)  overwrite(wp, stdscr);
  178.  
  179.     if (canceled)
  180.         continue;
  181.  
  182. #ifdef BUGGYTERMINFO
  183.     /* buggyterminfo seems to require this */
  184.     touchwin(stdscr);
  185. #endif
  186.     wrefresh(stdscr);
  187.  
  188.     if (w != topw)
  189.     {
  190.         showmsg("Window #%d.  Hit any key to see next window.", w);
  191.         c = tty_getch();
  192.         if (c == CANCEL1  ||  c == CANCEL2)
  193.         {
  194.         showmsg("Canceled.");
  195.         canceled = TRUE;
  196.         }
  197.     }
  198.  
  199.     else
  200.     {
  201.         showmsg("Window #%d (top window).  Hit any key to continue.", w);
  202.         (void) tty_getch();
  203.     }
  204.     }
  205.  
  206.     if (canceled)
  207.     wrefresh(stdscr);
  208.     RestoreMsg();
  209.     RestoreCursor();
  210. }
  211.  
  212. /*
  213.  * Show message s on bottom of screen.
  214.  */
  215. /*VARARGS1*/
  216. showmsg(s, arg1, arg2)
  217.  
  218. register char *s;
  219. {
  220.     char buf[256];
  221.  
  222.      /* Initialize message window first time 'round.
  223.       */
  224.     if (mw == NULL) {
  225.     mw=newwin(1, 0, LINES-1, 0);
  226.     cmw=newwin(1, 0, LINES-1, 0);
  227.     if (!mw || !cmw) {
  228.         fprintf(stderr, "Cannot create message window!\n\r");
  229.         Shutdown(1);
  230.     }
  231.     leaveok(cmw, TRUE);
  232.     werase(cmw);
  233.     /* (leaveok for mw & cursor positioning for prompts needs thought) */
  234.     wstandout(mw);
  235.     }
  236.  
  237. #ifdef notdef
  238.     /* pause to let user ponder a previous message */
  239.     if (msgbirth && *s && (t = 2-abs(msgbirth - time((time_t *)0))) > 0)
  240.     sleep((unsigned int)t);
  241. #endif
  242.  
  243.     /* Format the message */
  244.     (void) sprintf(buf, s, arg1, arg2);
  245.     s = buf;
  246.     s[wcols(mw)-1] = '\0';        /* make sure it fits */
  247.  
  248.     /* hack to honk but once */
  249.     if (*s == '\007') {
  250.     flash();
  251.     s++;
  252.     }
  253.     werase(mw);
  254.     waddstr(mw, s);
  255.     touchwin(mw);
  256.     wrefresh(mw);
  257.  
  258.     msgbirth = s[0]? time((time_t *)0): 0;
  259. }
  260.  
  261. ZapMsgLine()
  262. {
  263.     if (msgbirth) {
  264.     touchwin(cmw);
  265.     wrefresh(cmw);
  266.     }
  267. }
  268.  
  269. RestoreMsg()
  270. {
  271.     if (msgbirth) {
  272.     touchwin(mw);
  273.     wrefresh(mw);
  274.     }
  275. }
  276.  
  277. /*
  278.  * Restore cursor in top window.
  279.  */
  280. RestoreCursor()
  281. {
  282.     register WINDOW *wp;    /* pointer to top window */
  283.  
  284.     wp = win[topw].wptr;
  285.     if (movecursor(wbegy(wp)+wcury(wp), wbegx(wp)+wcurx(wp)))
  286.     (void) fflush(stdout);
  287. }
  288.  
  289. /*
  290.  * Clear the whole screen
  291.  */
  292. ClearScreen()
  293. {
  294.     wclear(stdscr);
  295.     wrefresh(stdscr);
  296. }
  297.  
  298. /*
  299.  * Creates windows containing
  300.  * a border to surround window w
  301.  * and puts pointer to the new windows
  302.  * into proper places in global win[].
  303.  * Borders appear in standout mode if
  304.  * terminal has that capability.
  305.  * Returns 0 if sucessful, else -1.
  306.  */
  307. MakeBorders(w)
  308.  
  309. register int w;        /* make borders for this window */
  310. {
  311.     int left, right, top, bottom;    /* border flags */
  312.     int begx, begy, cols, lines;    /* window dimensions */
  313.     register WINDOW *wp;        /* window pointer */
  314.     register int i;            /* index */
  315.  
  316.  
  317.      /* Get window dimensions.
  318.       */
  319.     wp = win[w].wptr;
  320.     begx =  wbegx(wp);
  321.     begy =  wbegy(wp);
  322.     cols =  wcols(wp);
  323.     lines = wlines(wp);
  324.  
  325.  
  326.      /* Determine which sides of the window need borders.
  327.       */
  328.     left   = (begx > 0);
  329.     right  = (begx+cols < COLS);
  330.     top    = (begy > 0);
  331.     bottom = (begy+lines < LINES-1); /* bottom line for msgs */
  332.  
  333.     if (top)
  334.     --begy, ++lines;
  335.     if (bottom)
  336.     lines++;
  337.     
  338.  
  339.      /* Make left border using '>'.
  340.       */
  341.     if (left)
  342.     {
  343.     if ((win[w].boxleft = wp = newwin(lines,1,begy,begx-1))  == NULL)
  344.         return(-1);
  345.     leaveok(wp, TRUE);
  346.     wstandout(wp);
  347.     for (i=0; i<lines; i++)
  348.         waddch(wp, '>');
  349.     }
  350.     
  351.  
  352.      /* Make right border using '<'.
  353.       */
  354.     if (right)
  355.     {
  356.     if ((win[w].boxright = wp = newwin(lines,1,begy,begx+cols))  == NULL)
  357.         return(-1);
  358.     leaveok(wp, TRUE);
  359.     wstandout(wp);
  360.     for (i=0; i<lines; i++)
  361.         waddch(wp, '<');
  362.     }
  363.  
  364.  
  365.      /* Make top border using window number.
  366.       */
  367.     if (top)
  368.     {
  369.     if ((win[w].boxtop = wp = newwin(1,cols,begy,begx))  == NULL)
  370.         return(-1);
  371.     leaveok(wp, TRUE);
  372.     wstandout(wp);
  373.     for (i=0; i<cols; i++)
  374.         waddch(wp, itoc(w));
  375.     }
  376.  
  377.  
  378.      /* Make bottom border using window number.
  379.       */
  380.     if (bottom)
  381.     {
  382.     if ((win[w].boxbot = wp = newwin(1,cols,begy+lines-1,begx))  == NULL)
  383.         return(-1);
  384.     leaveok(wp, TRUE);
  385.     wstandout(wp);
  386.     for (i=0; i<cols; i++)
  387.         waddch(wp, itoc(w));
  388.     }
  389.  
  390.     return(0);
  391. }
  392.  
  393. /*
  394.  * Dump.
  395.  * Dump the contents of the current window to file 'wmdump'
  396.  * in the current directory.
  397.  * Returns 0 on sucessful completion, -1 otherwise.
  398.  */
  399. DumpWindow(w, dumpfile)
  400.  
  401. int w;        /* number of window we're to dump */
  402. char *dumpfile;    /* file we're dumping to */
  403. {
  404.     register WINDOW *wp;    /* top window */
  405.     register FILE *dfp;        /* dump file pointer */
  406.     register int line, col;    /* current line, column of window */
  407.     register int lastcol;    /* column of rightmost non-blank */
  408.     int oldy, oldx;        /* saved cursor position */
  409.  
  410.     if ((dfp = fopen(dumpfile, "w"))  == NULL)
  411.     return(-1);
  412.  
  413.     wp = win[w].wptr;
  414.     getyx(wp, oldy, oldx);
  415.     for (line = 0; line < wlines(wp); line++)
  416.     {
  417.     lastcol = wcols(wp);
  418.     while (--lastcol >= 0)
  419.         if (toascii(mvwinch(wp, line, lastcol)) != ' ')
  420.         break;
  421.     for (col = 0; col <= lastcol; col++)
  422.         putc(toascii(mvwinch(wp, line, col)),  dfp);
  423.     putc('\n', dfp);
  424.     }
  425.     (void) fclose(dfp);
  426.     wmove(wp, oldy, oldx);
  427.     return(0);
  428. }
  429.  
  430. #define BUFLEN        80
  431.  
  432. /* Prompt user for a string.
  433.  */
  434. char *
  435. WPrompt(prompt, dflt)
  436.  
  437. char *prompt;    /* prompt */
  438. char *dflt;    /* default response */
  439. {
  440.     register int c;        /* character in string */
  441.     static char buf[BUFLEN+1];    /* string buffer */
  442.     register int i=0;        /* buffer index */
  443.     int maxlen, x;        /* how long can string be? */
  444.  
  445.      /* Print prompt and default response
  446.       * on bottom line of screen.
  447.       */
  448.     showmsg("%s? [%s] ", prompt, dflt);
  449.  
  450.      /* Determine length of longest string
  451.       * that will fit in window.
  452.       */
  453.     x = wcurx(mw);
  454.     maxlen = (BUFLEN < wcols(mw)-2-x  ?  BUFLEN  :  wcols(mw)-2-x);
  455.  
  456.  
  457.      /* Read string. Process line kill & backspace chars.
  458.       */
  459.     while ((c = tty_getch()) != EOF && c != '\n' && c != '\r')
  460.     {
  461.     if (c==CANCEL1 || c==CANCEL2)    /* cancel */
  462.     {
  463.         showmsg("Canceled.");
  464.         return(NULL);
  465.     }
  466.     if (c==erasechar() || c == KEY_BACKSPACE || c == KEY_LEFT)
  467.     {
  468.         if (i > 0)
  469.         {
  470.         i--;
  471.         waddstr(mw, "\b \b");
  472.         }
  473.     }
  474.     else if (c == killchar())
  475.     {
  476.         i = 0;
  477.         wmove(mw, 0, x);
  478.         wclrtoeol(mw);
  479.     }
  480.     else if (i > maxlen)        /* is string too long? */
  481.         flash();
  482.     else if (isspace(c) || !isprint(c)) /* is character inappropriate? */
  483.         flash();
  484.     else                /* regular char: add to string */
  485.     {
  486.         waddch(mw, c);
  487.         buf[i++] = c;
  488.     }
  489.  
  490.     wrefresh(mw);
  491.     }
  492.  
  493.  
  494.      /* If user didn't respond, just return default response.
  495.       */
  496.     if (i == 0)
  497.     strcpy(buf, dflt);
  498.     else
  499.     buf[i] = '\0';
  500.  
  501.  
  502.     return(buf);
  503. }
  504.