home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / pcomm-2.0.2 / part04 / curses.c next >
Encoding:
C/C++ Source or Header  |  1993-04-13  |  8.8 KB  |  504 lines

  1. /*
  2.  * Miscellaneous curses(3) routines.
  3.  */
  4.  
  5. #define STR_WIDTH    256
  6. #define NUM_WIDTH    16
  7.  
  8. #include <stdio.h>
  9. #include <curses.h>
  10. #include <signal.h>
  11. #include "config.h"
  12. #include "misc.h"
  13. #include "status.h"
  14.  
  15. #ifdef BSD
  16. #include <setjmp.h>
  17. jmp_buf wk_buf;
  18. #endif /* BSD */
  19.  
  20. #ifndef OLDCURSES
  21. #include <term.h>
  22. #else /* OLDCURSES */
  23. #ifdef UNIXPC
  24. #include <sgtty.h>
  25. #endif /* UNIXPC */
  26. #endif /* OLDCURSES */
  27.  
  28. /*
  29.  * Get a string from a window.  Similar to wgetstr(), except we limit
  30.  * the length, return a NULL (not pointer to NULL) on <ESC> key, beep
  31.  * at any character in "disallow" string, and beep at any character not
  32.  * in "allow". (It doesn't make sense to use both "allow" and "disallow"
  33.  * at the same time).  Returns a pointer to a static area.
  34.  */
  35.  
  36. char *
  37. get_str(win, num, allow, disallow)
  38. WINDOW *win;
  39. int num;
  40. char *allow, *disallow;
  41. {
  42.     int count, x, y;
  43.     char ans, *strchr();
  44.     static char buf[STR_WIDTH];
  45.  
  46.     count = 0;
  47.     while ((ans = wgetch(win)) != '\r') {
  48.                     /* do our own backspace */
  49.         if (ans == BS || ans == DEL) {
  50.             if (!count) {
  51.                 beep();
  52.                 continue;
  53.             }
  54.             count--;
  55.             buf[count] = '\0';
  56.             getyx(win, y, x);
  57.             x--;
  58.             wmove(win, y, x);
  59.             waddch(win, (chtype) ' ');
  60.             wmove(win, y, x);
  61.             wrefresh(win);
  62.             continue;
  63.         }
  64.                     /* an <ESC> anywhere in the string */
  65.         if (ans == ESC)
  66.             return(NULL);
  67.  
  68.                     /* illegal character? */
  69.         if (*disallow != '\0' && strchr(disallow, ans)) {
  70.             beep();
  71.             continue;
  72.         }
  73.         if (*allow != '\0' && !strchr(allow, ans)) {
  74.             beep();
  75.             continue;
  76.         }
  77.                     /* exceeded the max? */
  78.         if (count >= num || count >= STR_WIDTH) {
  79.             beep();
  80.             continue;
  81.         }
  82.  
  83.         buf[count] = ans;
  84.         waddch(win, (chtype) ans);
  85.         wrefresh(win);
  86.         count++;
  87.     }
  88.     buf[count] = '\0';
  89.     return(buf);
  90. }
  91.  
  92. /*
  93.  * Get a number from a window.  We limit the length and return a -1
  94.  * on <ESC> key.
  95.  */
  96.  
  97. int
  98. get_num(win, num)
  99. WINDOW *win;
  100. int num;
  101. {
  102.     int count, x, y, number;
  103.     char ans, buf[NUM_WIDTH];
  104.  
  105.     count = 0;
  106.     while ((ans = wgetch(win)) != '\r') {
  107.                     /* do our own backspace */
  108.         if (ans == BS || ans == DEL) {
  109.             if (!count) {
  110.                 beep();
  111.                 continue;
  112.             }
  113.             count--;
  114.             buf[count] = '\0';
  115.             getyx(win, y, x);
  116.             x--;
  117.             wmove(win, y, x);
  118.             waddch(win, (chtype) ' ');
  119.             wmove(win, y, x);
  120.             wrefresh(win);
  121.             continue;
  122.         }
  123.                     /* an <ESC> anywhere in the string */
  124.         if (ans == ESC)
  125.             return(-1);
  126.                     /* only digits are allowed */
  127.         if (ans < '0' || ans > '9') {
  128.             beep();
  129.             continue;
  130.         }
  131.                     /* exceeded the max? */
  132.         if (count >= num || count >= NUM_WIDTH) {
  133.             beep();
  134.             continue;
  135.         }
  136.  
  137.         buf[count] = ans;
  138.         waddch(win, (chtype) ans);
  139.         wrefresh(win);
  140.         count++;
  141.     }
  142.     buf[count] = '\0';
  143.     number = atoi(buf);
  144.     return(number);
  145. }
  146.  
  147. /*
  148.  * Change video attributes while printing a string.  The use of the
  149.  * pre-processor definition NOPROMOTE (located in config.h) means that
  150.  * strings will be printed without any special video attribute if the
  151.  * requested capability doesn't exist.
  152.  */
  153.  
  154. wattrstr(win, attr, str)
  155. WINDOW *win;
  156. chtype attr;
  157. char *str;
  158. {
  159.     int do_it;
  160.                     /* if nothing, do nothing */
  161.     if (str == NULL || *str == '\0')
  162.         return(0);
  163.  
  164. #ifdef OLDCURSES
  165.     if (attr)
  166.         wstandout(win);
  167.     waddstr(win, str);
  168.     if (attr)
  169.         wstandend(win);
  170. #else /* OLDCURSES */
  171.  
  172. #ifdef NOPROMOTE
  173.                     /* does the capability exist? */
  174.     do_it = 0;
  175.     if ((attr & A_STANDOUT) && enter_standout_mode)
  176.         do_it++;
  177.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  178.         do_it++;
  179.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  180.         do_it++;
  181.     if ((attr & A_BLINK) && enter_blink_mode)
  182.         do_it++;
  183.     if ((attr & A_BOLD) && enter_bold_mode)
  184.         do_it++;
  185.     if ((attr & A_DIM) && enter_dim_mode)
  186.         do_it++;
  187. #else /* NOPROMOTE */
  188.     do_it = 1;
  189. #endif /* NOPROMOTE */
  190.  
  191.     if (do_it)
  192.         wattron(win, attr);
  193.                     /* print the string */
  194.     waddstr(win, str);
  195.     if (do_it)
  196.         wattroff(win, attr);
  197. #endif /* OLDCURSES */
  198.     return(0);
  199. }
  200.  
  201. /*
  202.  * Change video attributes while printing a character.
  203.  */
  204.  
  205. wattrch(win, attr, c)
  206. WINDOW *win;
  207. chtype attr;
  208. char c;
  209. {
  210.     int do_it;
  211.  
  212.     if (c == '\0')
  213.         return(0);
  214. #ifdef OLDCURSES
  215.     if (attr)
  216.         wstandout(win);
  217.     waddch(win, (chtype) c);
  218.     if (attr)
  219.         wstandend(win);
  220. #else /* OLDCURSES */
  221.  
  222. #ifdef NOPROMOTE
  223.                     /* does the capability exist? */
  224.     do_it = 0;
  225.     if ((attr & A_STANDOUT) && enter_standout_mode)
  226.         do_it++;
  227.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  228.         do_it++;
  229.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  230.         do_it++;
  231.     if ((attr & A_BLINK) && enter_blink_mode)
  232.         do_it++;
  233.     if ((attr & A_BOLD) && enter_bold_mode)
  234.         do_it++;
  235.     if ((attr & A_DIM) && enter_dim_mode)
  236.         do_it++;
  237. #else /* NOPROMOTE */
  238.     do_it = 1;
  239. #endif /* NOPROMOTE */
  240.  
  241.     if (do_it)
  242.         wattron(win, attr);
  243.                     /* print the character */
  244.     waddch(win, (chtype) c);
  245.     if (do_it)
  246.         wattroff(win, attr);
  247. #endif /* OLDCURSES */
  248.     return(0);
  249. }
  250.  
  251.  
  252. /*
  253.  * Change video attributes while printing a number.
  254.  */
  255.  
  256. wattrnum(win, attr, num)
  257. WINDOW *win;
  258. chtype attr;
  259. int num;
  260. {
  261.     int do_it;
  262.     char buf[40];
  263.  
  264.     sprintf(buf, "%d", num);
  265.  
  266. #ifdef OLDCURSES
  267.     if (attr)
  268.         wstandout(win);
  269.     waddstr(win, buf);
  270.     if (attr)
  271.         wstandend(win);
  272. #else /* OLDCURSES */
  273.  
  274. #ifdef NOPROMOTE
  275.                     /* does the capability exist? */
  276.     do_it = 0;
  277.     if ((attr & A_STANDOUT) && enter_standout_mode)
  278.         do_it++;
  279.     if ((attr & A_UNDERLINE) && enter_underline_mode)
  280.         do_it++;
  281.     if ((attr & A_REVERSE) && (enter_reverse_mode || enter_standout_mode))
  282.         do_it++;
  283.     if ((attr & A_BLINK) && enter_blink_mode)
  284.         do_it++;
  285.     if ((attr & A_BOLD) && enter_bold_mode)
  286.         do_it++;
  287.     if ((attr & A_DIM) && enter_dim_mode)
  288.         do_it++;
  289. #else /* NOPROMOTE */
  290.     do_it = 1;
  291. #endif /* NOPROMOTE */
  292.  
  293.     if (do_it)
  294.         wattron(win, attr);
  295.                     /* print the character */
  296.     waddstr(win, buf);
  297.     if (do_it)
  298.         wattroff(win, attr);
  299. #endif /* OLDCURSES */
  300.     return(0);
  301. }
  302.  
  303. /*
  304.  * Prompt for a Yes or No answer.  Echo the single key input as words.
  305.  * Handle the funny cursor movement problems with magic cookie terminals.
  306.  * Returns a 1 on yes.
  307.  */
  308.  
  309. int
  310. yes_prompt(win, y, x, attr, str)
  311. WINDOW *win;
  312. int y, x;
  313. chtype attr;
  314. char *str;
  315. {
  316.     int ret_code, ans;
  317.     char new_str[80], *strcpy(), *strcat();
  318.                     /* sanity checking */
  319.     if (strlen(str) > 71)
  320.         *(str+71) = '\0';
  321.                     /* build and display the prompt */
  322.     strcpy(new_str, str);
  323.     strcat(new_str, "? (y/n):");
  324.     mvwattrstr(win, y, x, attr, new_str);
  325.     wmove(win, y, strlen(new_str)+x+2);
  326.     wrefresh(win);
  327.         
  328.     ret_code = -1;
  329.     while (ret_code == -1) {
  330.                     /* if inside a script */
  331.         if (status->dup_fd != -1)
  332.             ans = wait_key(win, 5);
  333.         else
  334.             ans = wgetch(win);
  335.  
  336.         switch (ans) {
  337.             case -1:
  338.             case 'y':
  339.             case 'Y':
  340.                 waddstr(win, "Yes");
  341.                 ret_code = 1;
  342.                 break;
  343.             case 'n':
  344.             case 'N':
  345.             case ESC:
  346.                 waddstr(win, "No");
  347.                 ret_code = 0;
  348.                 break;
  349.             default:
  350.                 beep();
  351.  
  352.         }
  353.     }
  354.     wrefresh(win);
  355.     return(ret_code);
  356. }
  357.  
  358. /*
  359.  * Handy routine for clear-to-end-of-line.  Fixes up the box if requested.
  360.  */
  361.  
  362. int
  363. clear_line(win, y, x, re_box)
  364. WINDOW *win;
  365. int y, x, re_box;
  366. {
  367.     if (wmove(win, y, x) == ERR)
  368.         return(ERR);
  369.  
  370.     wclrtoeol(win);
  371.  
  372.     if (re_box) {
  373.         mvwaddch(win, y, win->_maxx-1, (chtype) ACS_VLINE);
  374.         wmove(win, y, x);
  375.     }
  376.     return(0);
  377. }
  378.  
  379. /*
  380.  * Routine to make a horizontal line.  Does NOT do a wrefresh().
  381.  */
  382.  
  383. int
  384. horizontal(win, x, y, len)
  385. WINDOW *win;
  386. int x, y, len;
  387. {
  388.     wmove(win, x, y);
  389.  
  390.     while (len--)
  391.         waddch(win, ACS_HLINE);
  392.  
  393.     return(0);
  394. }
  395.  
  396. /*
  397.  * Wait for a key or time out.  Returns a -1 on timeout.  This is similar
  398.  * to the half-delay mode in the newer versions of curses(3).
  399.  */
  400.  
  401. static int wk_flag;
  402. static int wk_force();
  403.  
  404. /* ARGSUSED */
  405. int
  406. wait_key(win, sec)
  407. WINDOW *win;
  408. unsigned int sec;
  409. {
  410.     int key;
  411.     unsigned int alarm();
  412. #ifdef WGETCH_BROKE
  413.     char c;
  414. #endif /* WGETCH_BROKE */
  415.  
  416.     signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
  417.     wk_flag = 0;
  418.  
  419.     alarm(sec);
  420.  
  421. #ifdef BSD
  422.     if (setjmp(wk_buf))
  423.         return(-1);
  424. #endif /* BSD */
  425.  
  426. #ifdef WGETCH_BROKE
  427.     read(0, &c, 1);
  428.     key = c & 0x7f;
  429. #else /* WGETCH_BROKE */
  430.     key = wgetch(win);
  431. #endif /* WGETCH_BROKE */
  432.  
  433.     if (wk_flag)
  434.         return(-1);
  435.     alarm(0);
  436.     return(key);
  437. }
  438.  
  439. /* ARGSUSED */
  440. static int
  441. wk_force(dummy)
  442. int dummy;
  443. {
  444. #ifdef BSD
  445.     longjmp(wk_buf, 1);
  446. #else /* BSD */
  447.     signal(SIGALRM, (SIG_TYPE(*) ()) wk_force);
  448.     wk_flag = 1;
  449.     return(0);
  450. #endif /* BSD */
  451. }
  452.  
  453. /*
  454.  * Here are some routines that are probably missing from the older
  455.  * flavors of curses(3).
  456.  */
  457.  
  458. #ifdef OLDCURSES
  459. /*
  460.  * Make the terminal bell go off
  461.  */
  462.  
  463. int
  464. beep()
  465. {
  466.     fputc(BEL, stderr);
  467.     return(0);
  468. }
  469.  
  470. /*
  471.  * Take the terminal out of the "curses mode".  The t_mode structure was 
  472.  * captured before we initialized the curses mode.
  473.  */
  474.  
  475. int
  476. resetterm()
  477. {
  478.     extern char _putchar();
  479.     extern struct sgttyb t_mode;
  480.  
  481.     ioctl(0, TIOCSETP, &t_mode);
  482.     tputs(TE, 1, _putchar);
  483.     tputs(VE, 1, _putchar);
  484.     return(0);
  485. }
  486.  
  487. /*
  488.  * Put the terminal back into the "curses mode".  The c_mode structure was
  489.  * captured after we initialized the curses mode.
  490.  */
  491.  
  492. int
  493. fixterm()
  494. {
  495.     extern char _putchar();
  496.     extern struct sgttyb c_mode;
  497.  
  498.     ioctl(0, TIOCSETP, &c_mode);
  499.     tputs(TI, 1, _putchar);
  500.     tputs(VS, 1, _putchar);
  501.     return(0);
  502. }
  503. #endif /* OLDCURSES */
  504.