home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncurses-1.9.9e-src.tgz / tar.out / fsf / ncurses / test / ncurses.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  50KB  |  2,225 lines

  1. /****************************************************************************
  2.  
  3. NAME
  4.    ncurses.c --- ncurses library exerciser
  5.  
  6. SYNOPSIS
  7.    ncurses
  8.  
  9. DESCRIPTION
  10.    An interactive test module for the ncurses library.
  11.  
  12. AUTHOR
  13.    This software is Copyright (C) 1993 by Eric S. Raymond, all rights reserved.
  14. It is issued with ncurses under the same terms and conditions as the ncurses
  15. library source.
  16.  
  17. ***************************************************************************/
  18. /*LINTLIBRARY */
  19.  
  20. #if HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include <unistd.h>
  28. #include <string.h>
  29. #include <assert.h>
  30.  
  31. #if HAVE_GETTIMEOFDAY
  32. #if HAVE_SYS_TIME_H && ! SYSTEM_LOOKS_LIKE_SCO
  33. #include <sys/time.h>
  34. #endif
  35. #if HAVE_SYS_SELECT_H
  36. #include <sys/select.h>
  37. #endif
  38. #endif
  39.  
  40. #include <curses.h>
  41.  
  42. #if HAVE_PANEL_H
  43. #include <panel.h>
  44. #endif
  45.  
  46. #if HAVE_MENU_H
  47. #include <menu.h>
  48. #endif
  49.  
  50. #if HAVE_FORM_H
  51. #include <form.h>
  52. #endif
  53.  
  54. #ifndef NCURSES_VERSION
  55. #define mmask_t chtype        /* not specified in XSI */
  56. #define attr_t chtype        /* not specified in XSI */
  57. #define ACS_S3          (acs_map['p'])  /* scan line 3 */
  58. #define ACS_S7          (acs_map['r'])  /* scan line 7 */
  59. #define ACS_LEQUAL      (acs_map['y'])  /* less/equal */
  60. #define ACS_GEQUAL      (acs_map['z'])  /* greater/equal */
  61. #define ACS_PI          (acs_map['{'])  /* Pi */
  62. #define ACS_NEQUAL      (acs_map['|'])  /* not equal */
  63. #define ACS_STERLING    (acs_map['}'])  /* UK pound sign */
  64. #endif
  65.  
  66. #define P(string)    printw("%s\n", string)
  67. #ifndef CTRL
  68. #define CTRL(x)        ((x) & 0x1f)
  69. #endif
  70.  
  71. static void Pause(void)
  72. {
  73.     move(LINES - 1, 0);
  74.     addstr("Press any key to continue... ");
  75.     (void) getch();
  76. }
  77.  
  78. static void Cannot(char *what)
  79. {
  80.     printw("\nThis %s terminal %s\n\n", getenv("TERM"), what);
  81.     Pause();
  82. }
  83.  
  84. /****************************************************************************
  85.  *
  86.  * Character input test
  87.  *
  88.  ****************************************************************************/
  89.  
  90. static void getch_test(void)
  91. /* test the keypad feature */
  92. {
  93. char buf[BUFSIZ];
  94. int c;
  95. int incount = 0, firsttime = 0;
  96. bool blocking = TRUE;
  97. int y, x;
  98.  
  99.      refresh();
  100.  
  101. #ifdef NCURSES_VERSION
  102.      mousemask(ALL_MOUSE_EVENTS, (mmask_t *)NULL);
  103. #endif
  104.   
  105.      (void) printw("Delay in 10ths of a second (<CR> for blocking input)? ");
  106.      echo();
  107.      getstr(buf);
  108.      noecho();
  109.  
  110.      if (isdigit(buf[0]))
  111.      {
  112.      timeout(atoi(buf) * 100);
  113.      blocking = FALSE;
  114.      }
  115.  
  116.      c = '?';
  117.      for (;;)
  118.      {
  119.     if (firsttime++)
  120.     {
  121.         printw("Key pressed: %04o ", c);
  122. #ifdef NCURSES_VERSION
  123.         if (c == KEY_MOUSE)
  124.         {
  125.         MEVENT    event;
  126.  
  127.         getmouse(&event);
  128.         printw("KEY_MOUSE, %s\n", _tracemouse(&event));
  129.         }
  130.         else
  131. #endif    /* NCURSES_VERSION */
  132.          if (c >= KEY_MIN)
  133.         {
  134.         (void) addstr(keyname(c));
  135.         addch('\n');
  136.         }
  137.         else if (c > 0x80)
  138.         {
  139.         int c2 = (c & 0x7f);
  140.         if (isprint(c2))
  141.             (void) printw("M-%c", c2);
  142.         else
  143.             (void) printw("M-%s", unctrl(c2));
  144.         addstr(" (high-half character)\n");
  145.         }
  146.         else
  147.         {
  148.         if (isprint(c))
  149.             (void) printw("%c (ASCII printable character)\n", c);
  150.         else
  151.             (void) printw("%s (ASCII control character)\n", unctrl(c));
  152.         }
  153.         getyx(stdscr, y, x);
  154.         if (y >= LINES-1)
  155.             move(0,0);
  156.         clrtoeol();    
  157.     }
  158.  
  159.     if (c == 'g')
  160.     {
  161.         addstr("getstr test: ");
  162.         echo(); getstr(buf); noecho();
  163.         printw("I saw `%s'.\n", buf);
  164.     }
  165.     if (c == 's')
  166.     {
  167.         addstr("Shelling out...");
  168.         def_prog_mode();
  169.         endwin();
  170.         system("sh");
  171.         addstr("returned from shellout.\n");
  172.         refresh();
  173.     }
  174.     if (c == 'x' || c == 'q')
  175.         break;
  176.     if (c == '?')
  177.     {
  178.         addstr("Type any key to see its keypad value.  Also:\n");
  179.         addstr("g -- triggers a getstr test\n");
  180.         addstr("s -- shell out\n");
  181.         addstr("q -- quit\n");
  182.         addstr("? -- repeats this help message\n");
  183.     }
  184.  
  185.     while ((c = getch()) == ERR)
  186.         if (!blocking)
  187.         (void) printw("%05d: input timed out\n", incount++);
  188.     }
  189.  
  190. #ifdef NCURSES_VERSION
  191.     mousemask(0, (mmask_t *)NULL);  
  192. #endif
  193.     timeout(-1);
  194.     erase();
  195.     endwin();
  196. }
  197.  
  198. static void attr_test(void)
  199. /* test text attributes */
  200. {
  201.     refresh();
  202.  
  203.     mvaddstr(0, 20, "Character attribute test display");
  204.  
  205.     mvaddstr(2,8,"This is STANDOUT mode: ");
  206.     attron(A_STANDOUT);
  207.     addstr("abcde fghij klmno pqrst uvwxy z");
  208.     attroff(A_STANDOUT);
  209.  
  210.     mvaddstr(4,8,"This is REVERSE mode: ");
  211.     attron(A_REVERSE);
  212.     addstr("abcde fghij klmno pqrst uvwxy z");
  213.     attroff(A_REVERSE);
  214.  
  215.     mvaddstr(6,8,"This is BOLD mode: ");
  216.     attron(A_BOLD);
  217.     addstr("abcde fghij klmno pqrst uvwxy z");
  218.     attroff(A_BOLD);
  219.  
  220.     mvaddstr(8,8,"This is UNDERLINE mode: ");
  221.     attron(A_UNDERLINE);
  222.     addstr("abcde fghij klmno pqrst uvwxy z");
  223.     attroff(A_UNDERLINE);
  224.  
  225.     mvaddstr(10,8,"This is DIM mode: ");
  226.     attron(A_DIM);
  227.     addstr("abcde fghij klmno pqrst uvwxy z");
  228.     attroff(A_DIM);
  229.  
  230.     mvaddstr(12,8,"This is BLINK mode: ");
  231.     attron(A_BLINK);
  232.     addstr("abcde fghij klmno pqrst uvwxy z");
  233.     attroff(A_BLINK);
  234.  
  235.     mvaddstr(14,8,"This is PROTECT mode: ");
  236.     attron(A_PROTECT);
  237.     addstr("abcde fghij klmno pqrst uvwxy z");
  238.     attroff(A_PROTECT);
  239.  
  240.     attrset(A_INVIS);
  241.     mvaddstr(16,8,"This is INVISIBLE mode: ");
  242.     addstr("abcde fghij klmno pqrst uvwxy z");
  243.  
  244.     attrset(A_NORMAL);
  245.     mvaddstr(18,8,"This is NORMAL mode: ");
  246.     addstr("abcde fghij klmno pqrst uvwxy z");
  247.  
  248.     refresh();
  249.  
  250.     Pause();
  251.  
  252.     erase();
  253.     endwin();
  254. }
  255.  
  256. /****************************************************************************
  257.  *
  258.  * Color support tests
  259.  *
  260.  ****************************************************************************/
  261.  
  262. static char    *colors[] =
  263. {
  264.     "black", 
  265.     "red",
  266.     "green",
  267.     "yellow",
  268.     "blue",
  269.     "magenta",
  270.     "cyan",
  271.     "white"
  272. };
  273.  
  274. static void color_test(void)
  275. /* generate a color test pattern */
  276. {
  277.     int i;
  278.  
  279.     refresh();
  280.     (void) printw("There are %d color pairs\n", COLOR_PAIRS);
  281.  
  282.     (void) mvprintw(1, 0,
  283.      "%dx%d matrix of foreground/background colors, bright *off*\n",
  284.      COLORS, COLORS);
  285.     for (i = 0; i < COLORS; i++)
  286.     mvaddstr(2, (i+1) * 8, colors[i]);
  287.     for (i = 0; i < COLORS; i++)
  288.     mvaddstr(3 + i, 0, colors[i]);
  289.     for (i = 1; i < COLOR_PAIRS; i++)
  290.     {
  291.     init_pair(i, i % COLORS, i / COLORS);
  292.     attron((attr_t)COLOR_PAIR(i));
  293.     mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
  294.     attrset(A_NORMAL);
  295.     }
  296.  
  297.     (void) mvprintw(COLORS + 4, 0,
  298.        "%dx%d matrix of foreground/background colors, bright *on*\n",
  299.            COLORS, COLORS);
  300.     for (i = 0; i < COLORS; i++)
  301.     mvaddstr(5 + COLORS, (i+1) * 8, colors[i]);
  302.     for (i = 0; i < COLORS; i++)
  303.     mvaddstr(6 + COLORS + i, 0, colors[i]);
  304.     for (i = 1; i < COLOR_PAIRS; i++)
  305.     {
  306.     init_pair(i, i % COLORS, i / COLORS);
  307.     attron((attr_t)(COLOR_PAIR(i) | A_BOLD));
  308.     mvaddstr(6 + COLORS + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
  309.     attrset(A_NORMAL);
  310.     }
  311.  
  312.     Pause();
  313.  
  314.     erase();
  315.     endwin();
  316. }
  317.  
  318. static void color_edit(void)
  319. /* display the color test pattern, without trying to edit colors */
  320. {
  321.     int    i, c, value = 0, current = 0, field = 0, usebase = 0;
  322.  
  323.     refresh();
  324.  
  325.     for (i = 0; i < COLORS; i++)
  326.     init_pair(i, COLOR_WHITE, i);
  327.  
  328.     do {
  329.     short    red, green, blue;
  330.  
  331.     attron(A_BOLD);
  332.     mvaddstr(0, 20, "Color RGB Value Editing");
  333.     attroff(A_BOLD);
  334.  
  335.     for (i = 0; i < COLORS; i++)
  336.         {
  337.         mvprintw(2 + i, 0, "%c %-8s:",
  338.              (i == current ? '>' : ' '), 
  339.              (i < sizeof(colors)/sizeof(colors[0]) ? colors[i] : ""));
  340.         attrset(COLOR_PAIR(i));
  341.         addstr("        ");
  342.         attrset(A_NORMAL);
  343.  
  344.         /*
  345.          * Note: this refresh should *not* be necessary!  It works around
  346.          * a bug in attribute handling that apparently causes the A_NORMAL
  347.          * attribute sets to interfere with the actual emission of the
  348.          * color setting somehow.  This needs to be fixed.
  349.          */
  350.         refresh();
  351.  
  352.         color_content(i, &red, &green, &blue);
  353.         addstr("   R = ");
  354.         if (current == i && field == 0) attron(A_STANDOUT);
  355.         printw("%04d", red);
  356.         if (current == i && field == 0) attrset(A_NORMAL);
  357.         addstr(", G = ");
  358.         if (current == i && field == 1) attron(A_STANDOUT);
  359.         printw("%04d", green);
  360.         if (current == i && field == 1) attrset(A_NORMAL);
  361.         addstr(", B = ");
  362.         if (current == i && field == 2) attron(A_STANDOUT);
  363.         printw("%04d", blue);
  364.         if (current == i && field == 2) attrset(A_NORMAL);
  365.         attrset(A_NORMAL);
  366.         addstr(")");
  367.     }
  368.  
  369.     mvaddstr(COLORS + 3, 0,
  370.         "Use up/down to select a color, left/right to change fields.");
  371.     mvaddstr(COLORS + 4, 0,
  372.         "Modify field by typing nnn=, nnn-, or nnn+.  ? for help.");
  373.  
  374.     move(2 + current, 0);
  375.  
  376.     switch (c = getch())
  377.     {
  378.     case KEY_UP:
  379.         current = (current == 0 ? (COLORS - 1) : current - 1);
  380.         value = 0;
  381.         break;
  382.  
  383.     case KEY_DOWN:
  384.         current = (current == (COLORS - 1) ? 0 : current + 1);
  385.         value = 0;
  386.         break;
  387.  
  388.     case KEY_RIGHT:
  389.         field = (field == 2 ? 0 : field + 1);
  390.         value = 0;
  391.         break;
  392.  
  393.     case KEY_LEFT:
  394.         field = (field == 0 ? 2 : field - 1);
  395.         value = 0;
  396.         break;
  397.  
  398.     case '0': case '1': case '2': case '3': case '4':
  399.     case '5': case '6': case '7': case '8': case '9':
  400.         do {
  401.         value = value * 10 + (c - '0');
  402.         c = getch();
  403.         } while
  404.         (isdigit(c));
  405.         if (c != '+' && c != '-' && c != '=')
  406.         beep();
  407.         else
  408.         ungetch(c);
  409.         break;
  410.  
  411.     case '+':
  412.         usebase = 1;
  413.         goto changeit;
  414.  
  415.     case '-':
  416.         value = -value;
  417.         usebase = 1;
  418.         goto changeit;
  419.  
  420.     case '=':
  421.         usebase = 0; 
  422.     changeit:
  423.         color_content(current, &red, &green, &blue);
  424.         if (field == 0)
  425.         red = red * usebase + value;
  426.         else if (field == 1)
  427.         green = green * usebase + value;
  428.         else if (field == 2)
  429.         blue = blue * usebase + value;
  430.         init_color(current, red, green, blue);
  431.         break;
  432.  
  433.     case '?':
  434.         erase();
  435.     P("                      RGB Value Editing Help");
  436.     P("");
  437.     P("You are in the RGB value editor.  Use the arrow keys to select one of");
  438.     P("the fields in one of the RGB triples of the current colors; the one");
  439.     P("currently selected will be reverse-video highlighted.");    
  440.     P("");
  441.     P("To change a field, enter the digits of the new value; they won't be");
  442.     P("echoed.  Finish by typing `='; the change will take effect instantly.");
  443.     P("To increment or decrement a value, use the same procedure, but finish");
  444.     P("with a `+' or `-'.");
  445.     P("");
  446.     P("To quit, do `x' or 'q'");
  447.  
  448.         Pause();
  449.         erase();
  450.         break;
  451.  
  452.     case 'x':
  453.     case 'q':
  454.         break;
  455.  
  456.     default:
  457.         beep();
  458.         break;
  459.     }
  460.     } while
  461.     (c != 'x' && c != 'q');
  462.  
  463.     erase();
  464.     endwin();
  465. }
  466.  
  467. /****************************************************************************
  468.  *
  469.  * Soft-key label test
  470.  *
  471.  ****************************************************************************/
  472.  
  473. static void slk_test(void)
  474. /* exercise the soft keys */
  475. {
  476.     int    c, fmt = 1;
  477.     char buf[9];
  478.  
  479.     c = CTRL('l');
  480.     do {
  481.     switch(c)
  482.     {
  483.     case CTRL('l'):
  484.         erase();
  485.         attron(A_BOLD);
  486.         mvaddstr(0, 20, "Soft Key Exerciser");
  487.         attroff(A_BOLD);
  488.  
  489.         move(2, 0);
  490.         P("Available commands are:");
  491.         P("");
  492.         P("^L         -- refresh screen");
  493.         P("a          -- activate or restore soft keys");
  494.         P("d          -- disable soft keys");
  495.         P("c          -- set centered format for labels");
  496.         P("l          -- set left-justified format for labels");
  497.         P("r          -- set right-justified format for labels");
  498.         P("[12345678] -- set label; labels are numbered 1 through 8");
  499.         P("e          -- erase stdscr (should not erase labels)");
  500.         P("s          -- test scrolling of shortened screen");
  501.         P("x, q       -- return to main menu");
  502.         P("");
  503.         P("Note: if activating the soft keys causes your terminal to");
  504.         P("scroll up one line, your terminal auto-scrolls when anything");
  505.         P("is written to the last screen position.  The ncurses code");
  506.         P("does not yet handle this gracefully.");
  507.         refresh();
  508.         /* fall through */
  509.  
  510.     case 'a':
  511.         slk_restore();
  512.         break;
  513.  
  514.     case 'e':
  515.         wclear(stdscr);
  516.         break;
  517.  
  518.     case 's':
  519.         move(20, 0);
  520.         while ((c = getch()) != 'Q' && (c != ERR))
  521.         addch((chtype)c);
  522.         break;
  523.  
  524.     case 'd':
  525.         slk_clear();
  526.         break;
  527.  
  528.     case 'l':
  529.         fmt = 0;
  530.         break;
  531.  
  532.     case 'c':
  533.         fmt = 1;
  534.         break;
  535.  
  536.     case 'r':
  537.         fmt = 2;
  538.         break;
  539.  
  540.     case '1': case '2': case '3': case '4':
  541.     case '5': case '6': case '7': case '8':
  542.         (void) mvaddstr(20, 0, "Please enter the label value: ");
  543.         echo();
  544.         wgetnstr(stdscr, buf, 8);
  545.         noecho();
  546.         slk_set((c - '0'), buf, fmt);
  547.         slk_refresh();
  548.         break;
  549.  
  550.     case 'x':
  551.     case 'q':
  552.         goto done;
  553.  
  554.     default:
  555.         beep();
  556.     }
  557.     } while
  558.     ((c = getch()) != EOF);
  559.  
  560.  done:
  561.     erase();
  562.     endwin();
  563. }
  564.  
  565. /****************************************************************************
  566.  *
  567.  * Alternate character-set stuff
  568.  *
  569.  ****************************************************************************/
  570.  
  571. static void acs_display(void)
  572. /* display the ACS character set */
  573. {
  574.     int    i, j;
  575.  
  576.     erase();
  577.     attron(A_BOLD);
  578.     mvaddstr(0, 20, "Display of the ACS Character Set");
  579.     attroff(A_BOLD);
  580.     refresh();
  581.  
  582. #define ACSY    1
  583.     mvaddstr(ACSY + 0, 0, "ACS_ULCORNER: "); addch(ACS_ULCORNER);
  584.     mvaddstr(ACSY + 1, 0, "ACS_LLCORNER: "); addch(ACS_LLCORNER);
  585.     mvaddstr(ACSY + 2, 0, "ACS_URCORNER: "); addch(ACS_URCORNER);
  586.     mvaddstr(ACSY + 3, 0, "ACS_LRCORNER: "); addch(ACS_LRCORNER);
  587.     mvaddstr(ACSY + 4, 0, "ACS_RTEE: "); addch(ACS_RTEE);
  588.     mvaddstr(ACSY + 5, 0, "ACS_LTEE: "); addch(ACS_LTEE);
  589.     mvaddstr(ACSY + 6, 0, "ACS_BTEE: "); addch(ACS_BTEE);
  590.     mvaddstr(ACSY + 7, 0, "ACS_TTEE: "); addch(ACS_TTEE);
  591.     mvaddstr(ACSY + 8, 0, "ACS_HLINE: "); addch(ACS_HLINE);
  592.     mvaddstr(ACSY + 9, 0, "ACS_VLINE: "); addch(ACS_VLINE);
  593.     mvaddstr(ACSY + 10,0, "ACS_PLUS: "); addch(ACS_PLUS);
  594.     mvaddstr(ACSY + 11,0, "ACS_S1: "); addch(ACS_S1);
  595.     mvaddstr(ACSY + 12,0, "ACS_S9: "); addch(ACS_S9);
  596.     mvaddstr(ACSY + 13,0, "ACS_DIAMOND: "); addch(ACS_DIAMOND);
  597.     mvaddstr(ACSY + 14,0, "ACS_CKBOARD: "); addch(ACS_CKBOARD);
  598.     mvaddstr(ACSY + 15,0, "ACS_DEGREE: "); addch(ACS_DEGREE);
  599.  
  600.     mvaddstr(ACSY + 0, 40, "ACS_PLMINUS: "); addch(ACS_PLMINUS);
  601.     mvaddstr(ACSY + 1, 40, "ACS_BULLET: "); addch(ACS_BULLET);
  602.     mvaddstr(ACSY + 2, 40, "ACS_LARROW: "); addch(ACS_LARROW);
  603.     mvaddstr(ACSY + 3, 40, "ACS_RARROW: "); addch(ACS_RARROW);
  604.     mvaddstr(ACSY + 4, 40, "ACS_DARROW: "); addch(ACS_DARROW);
  605.     mvaddstr(ACSY + 5, 40, "ACS_UARROW: "); addch(ACS_UARROW);
  606.     mvaddstr(ACSY + 6, 40, "ACS_BOARD: "); addch(ACS_BOARD);
  607.     mvaddstr(ACSY + 7, 40, "ACS_LANTERN: "); addch(ACS_LANTERN);
  608.     mvaddstr(ACSY + 8, 40, "ACS_BLOCK: "); addch(ACS_BLOCK);
  609.     mvaddstr(ACSY + 9,40,  "ACS_S3: "); addch(ACS_S3);
  610.     mvaddstr(ACSY + 10,40, "ACS_S7: "); addch(ACS_S7);
  611.     mvaddstr(ACSY + 11,40, "ACS_LEQUAL: "); addch(ACS_LEQUAL);
  612.     mvaddstr(ACSY + 12,40, "ACS_GEQUAL: "); addch(ACS_GEQUAL);
  613.     mvaddstr(ACSY + 13,40, "ACS_PI: "); addch(ACS_PI);
  614.     mvaddstr(ACSY + 14,40, "ACS_NEQUAL: "); addch(ACS_NEQUAL);
  615.     mvaddstr(ACSY + 15,40, "ACS_STERLING: "); addch(ACS_STERLING);
  616.  
  617. #define HYBASE     (ACSY + 17)    
  618.     mvprintw(HYBASE, 0, "High-half characters via echochar:\n");
  619.     for (i = 0; i < 4; i++)
  620.     {
  621.     move(HYBASE + 1 + i, 24);
  622.     for (j = 0; j < 32; j++)
  623.         echochar((chtype)(128 + 32 * i + j));
  624.     }
  625.  
  626.     Pause();
  627.  
  628.     erase();
  629.     endwin();
  630. }
  631.  
  632. /****************************************************************************
  633.  *
  634.  * Windows and scrolling tester.
  635.  *
  636.  ****************************************************************************/
  637.  
  638. #define BOTLINES    4    /* number of line stolen from screen bottom */
  639.  
  640. typedef struct
  641. {
  642.     int y, x;
  643. }
  644. pair;
  645.  
  646. static void report(void)
  647. /* report on the cursor's current position, then restore it */
  648. {
  649.     int y, x;
  650.  
  651.     getyx(stdscr, y, x);
  652.     move(LINES - 1, COLS - 17);
  653.     printw("Y = %2d X = %2d", y, x);
  654.     move(y, x);
  655. }
  656.  
  657. static pair *selectcell(int uli, int ulj, int lri, int lrj)
  658. /* arrows keys move cursor, return location at current on non-arrow key */
  659. {
  660.     static pair    res;            /* result cell */
  661.     int        si = lri - uli + 1;    /* depth of the select area */
  662.     int        sj = lrj - ulj + 1;    /* width of the select area */
  663.     int        i = 0, j = 0;        /* offsets into the select area */
  664.  
  665.     res.y = uli;
  666.     res.x = ulj;
  667.     for (;;)
  668.     {
  669.     move(LINES - 1, COLS - 17);
  670.     clrtoeol();
  671.     printw("Y = %2d X = %2d", uli + i, ulj + j);
  672.     move(uli + i, ulj + j);
  673.  
  674.     switch(getch())
  675.     {
  676.     case KEY_UP:    i += si - 1; break;
  677.     case KEY_DOWN:    i++; break;
  678.     case KEY_LEFT:    j += sj - 1; break;
  679.     case KEY_RIGHT:    j++; break;
  680.     case '\004':    return((pair *)NULL);
  681.     default:    res.y = uli + i; res.x = ulj + j; return(&res);
  682.     }
  683.     i %= si;
  684.     j %= sj;
  685.     }
  686. }
  687.  
  688. static void outerbox(pair ul, pair lr, bool onoff)
  689. /* draw or erase a box *outside* the given pair of corners */
  690. {
  691.     mvaddch(ul.y-1, lr.x-1, onoff ? ACS_ULCORNER : ' ');
  692.     mvaddch(ul.y-1, lr.x+1, onoff ? ACS_URCORNER : ' ');
  693.     mvaddch(lr.y+1, lr.x+1, onoff ? ACS_LRCORNER : ' ');
  694.     mvaddch(lr.y+1, ul.x-1, onoff ? ACS_LLCORNER : ' ');
  695.     move(ul.y-1, ul.x);   hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1);
  696.     move(ul.y,   ul.x-1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1);
  697.     move(lr.y+1, ul.x);   hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1);
  698.     move(ul.y,   lr.x+1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1);
  699. }
  700.  
  701. static WINDOW *getwindow(void)
  702. /* Ask user for a window definition */
  703. {
  704.     WINDOW    *rwindow;
  705.     pair    ul, lr, *tmp;
  706.  
  707.     move(0, 0); clrtoeol();
  708.     addstr("Use arrows to move cursor, anything else to mark corner 1");
  709.     refresh();
  710.     if ((tmp = selectcell(2, 1, LINES-BOTLINES-2, COLS-2)) == (pair *)NULL)
  711.     return((WINDOW *)NULL);
  712.     memcpy(&ul, tmp, sizeof(pair));
  713.     mvaddch(ul.y-1, ul.x-1, ACS_ULCORNER);
  714.     move(0, 0); clrtoeol();
  715.     addstr("Use arrows to move cursor, anything else to mark corner 2");
  716.     refresh();
  717.     if ((tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2)) == (pair *)NULL)
  718.     return((WINDOW *)NULL);
  719.     memcpy(&lr, tmp, sizeof(pair));
  720.  
  721.     rwindow = subwin(stdscr, lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x);
  722.  
  723.     outerbox(ul, lr, TRUE);
  724.     refresh();
  725.  
  726.     scrollok(rwindow, TRUE);
  727. /*    immedok(rwindow);    */
  728.     wrefresh(rwindow);
  729.  
  730.     return(rwindow);
  731. }
  732.  
  733. static void transient(char *msg)
  734. {
  735.     if (msg)
  736.     {
  737.     mvaddstr(LINES - 1, 0, msg);
  738.     refresh();
  739.     sleep(1);
  740.     }
  741.  
  742.     mvaddstr(LINES - 1, 0,
  743.          "All other characters are echoed, windows should scroll.");
  744.     refresh();
  745. }
  746.  
  747. static void acs_and_scroll(void)
  748. /* Demonstrate windows */
  749. {
  750.     int    c, i;
  751.     FILE *fp;
  752.     struct frame
  753.     {
  754.         struct frame    *next, *last;
  755.         WINDOW        *wind;
  756.     }
  757.     *current = (struct frame *)NULL, *neww;
  758.  
  759. #define DUMPFILE    "screendump"
  760.  
  761.     refresh();
  762.     mvaddstr(LINES - 4, 0,
  763.      "F1 = make new window, F2 = next window, F3 = previous window, ");
  764.     mvaddstr(LINES - 3, 0,
  765.      "F4 = scroll current window forward, F5 = scroll current window backward");
  766.     mvaddstr(LINES - 2, 0,
  767.      "F6 = save window to file, F7 = restore window, F8 = resize, Ctrl-D = exit");
  768.     transient((char *)NULL);
  769.  
  770.     c = KEY_F(1);
  771.     do {
  772.     report();
  773.     if (current)
  774.         wrefresh(current->wind);
  775.  
  776.     switch(c)
  777.     {
  778.     case KEY_F(1):
  779.         neww = (struct frame *) malloc(sizeof(struct frame));
  780.         if ((neww->wind = getwindow()) == (WINDOW *)NULL)
  781.         goto breakout;
  782.  
  783.         if (current == NULL)    /* First element,  */
  784.         {
  785.         neww->next = neww; /*   so point it at itself */
  786.         neww->last = neww;
  787.         }
  788.         else
  789.         {
  790.         neww->next = current->next;
  791.         neww->last = current;
  792.         neww->last->next = neww;
  793.         neww->next->last = neww;
  794.         }
  795.         current = neww;
  796.         keypad(neww->wind, TRUE);
  797.         break;
  798.  
  799.     case KEY_F(2):        /* go to next window */
  800.         current = current->next;
  801.         break;
  802.  
  803.     case KEY_F(3):        /* go to previous window */
  804.         current = current->last;
  805.         break;
  806.  
  807.     case KEY_F(4):        /* scroll current window forward */
  808.         if (current)
  809.         wscrl(current->wind, 1);
  810.         break;
  811.  
  812.     case KEY_F(5):        /* scroll current window backwards */
  813.         if (current)
  814.         wscrl(current->wind, -1);
  815.         break;
  816.  
  817.     case KEY_F(6):        /* save window */
  818.         if ((fp = fopen(DUMPFILE, "w")) == (FILE *)NULL)
  819.         transient("Can't open screen dump file");
  820.         else
  821.         {
  822.         (void) putwin(current->wind, fp);
  823.         (void) fclose(fp);
  824.  
  825.         current->last->next = current->next;
  826.         current->next->last = current->last;
  827.  
  828.         werase(current->wind);
  829.         wrefresh(current->wind);
  830.         delwin(current->wind);
  831.  
  832.         neww = current->next;
  833.         free(current);
  834.         current = neww;
  835.         }
  836.         break;
  837.  
  838.     case KEY_F(7):        /* restore window */
  839.         if ((fp = fopen(DUMPFILE, "r")) == (FILE *)NULL)
  840.         transient("Can't open screen dump file");
  841.         else
  842.         {
  843.         neww = (struct frame *) malloc(sizeof(struct frame));
  844.  
  845.         neww->next = current->next;
  846.         neww->last = current;
  847.         neww->last->next = neww;
  848.         neww->next->last = neww;
  849.  
  850.         neww->wind = getwin(fp);
  851.         (void) fclose(fp);
  852.  
  853.         wrefresh(neww->wind);
  854.         }
  855.         break;
  856.  
  857. #ifdef NCURSES_VERSION
  858.     case KEY_F(8):        /* resize window */
  859.         if (current)
  860.         {
  861.         pair *tmp, ul, lr;
  862.  
  863.         move(0, 0); clrtoeol();
  864.         addstr("Use arrows to move cursor, anything else to mark new corner");
  865.         refresh();
  866.  
  867.         getbegyx(current->wind, ul.y, ul.x);
  868.  
  869.         tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2);
  870.         if (tmp == (pair *)NULL)
  871.                 break;
  872.  
  873.         getmaxyx(current->wind, lr.y, lr.x);
  874.         lr.y += (ul.y - 1);
  875.         lr.x += (ul.x - 1);
  876.         outerbox(ul, lr, FALSE);
  877.         wnoutrefresh(stdscr);
  878.  
  879.         /* strictly cosmetic hack for the test */
  880.         if (current->wind->_maxy > tmp->y - ul.y)
  881.         {
  882.           getyx(current->wind, lr.y, lr.x);
  883.           wmove(current->wind, tmp->y - ul.y + 1, 0);
  884.           wclrtobot(current->wind);
  885.           wmove(current->wind, lr.y, lr.x);
  886.         }
  887.         if (current->wind->_maxx > tmp->x - ul.x)
  888.           for (i = 0; i < current->wind->_maxy; i++)
  889.           {
  890.             wmove(current->wind, i, tmp->x - ul.x + 1);
  891.             wclrtoeol(current->wind);
  892.           }
  893.         wnoutrefresh(current->wind);
  894.  
  895.         memcpy(&lr, tmp, sizeof(pair));
  896.         (void) wresize(current->wind, lr.y-ul.y+1, lr.x-ul.x+1);
  897.  
  898.         getbegyx(current->wind, ul.y, ul.x);
  899.         getmaxyx(current->wind, lr.y, lr.x);
  900.         lr.y += (ul.y - 1);
  901.         lr.x += (ul.x - 1);
  902.         outerbox(ul, lr, TRUE);
  903.         wnoutrefresh(stdscr);
  904.  
  905.         wnoutrefresh(current->wind);
  906.         doupdate();
  907.         }
  908.         break;
  909. #endif    /* NCURSES_VERSION */
  910.  
  911.     case KEY_F(10):    /* undocumented --- use this to test area clears */
  912.         selectcell(0, 0, LINES - 1, COLS - 1);
  913.         clrtobot();
  914.         refresh();
  915.         break;
  916.  
  917.     case '\r':
  918.         c = '\n';
  919.         /* FALLTHROUGH */
  920.  
  921.     default:
  922.         waddch(current->wind, (chtype)c);
  923.         break;
  924.     }
  925.     report();
  926.     wrefresh(current->wind);
  927.     } while
  928.     ((c = wgetch(current->wind)) != '\004'
  929.      && (c != ERR));
  930.  
  931.  breakout:
  932.     erase();
  933.     endwin();
  934. }
  935.  
  936. /****************************************************************************
  937.  *
  938.  * Panels tester
  939.  *
  940.  ****************************************************************************/
  941.  
  942. #if HAVE_PANEL_H
  943. static PANEL *p1;
  944. static PANEL *p2;
  945. static PANEL *p3;
  946. static PANEL *p4;
  947. static PANEL *p5;
  948. static WINDOW *w1;
  949. static WINDOW *w2;
  950. static WINDOW *w3;
  951. static WINDOW *w4;
  952. static WINDOW *w5;
  953.  
  954. static unsigned long nap_msec = 1;
  955.  
  956. char *mod[] = 
  957. {
  958.     "test ",
  959.     "TEST ",
  960.     "(**) ",
  961.     "*()* ",
  962.     "<--> ",
  963.     "LAST "
  964. };
  965.  
  966. /*+-------------------------------------------------------------------------
  967.     wait_a_while(msec)
  968. --------------------------------------------------------------------------*/
  969. static void
  970. wait_a_while(unsigned long msec)
  971. {
  972. #ifdef NONAP
  973.     if(nap_msec == 1)
  974.         getchar();
  975.     else if(msec > 1000L)
  976.         sleep((int)msec/1000L);
  977.     else
  978.         sleep(1);
  979. #else
  980.     if(nap_msec == 1)
  981.         getchar();
  982.     else
  983.         napms(nap_msec);
  984. #endif
  985. }    /* end of wait_a_while */
  986.  
  987. /*+-------------------------------------------------------------------------
  988.     saywhat(text)
  989. --------------------------------------------------------------------------*/
  990. static void
  991. saywhat(char *text)
  992. {
  993.     wmove(stdscr,LINES - 1,0);
  994.     wclrtoeol(stdscr);
  995.     waddstr(stdscr, text);
  996. }    /* end of saywhat */
  997.  
  998. /*+-------------------------------------------------------------------------
  999.     mkpanel(rows,cols,tly,tlx) - alloc a win and panel and associate them
  1000. --------------------------------------------------------------------------*/
  1001. static PANEL *
  1002. mkpanel(int rows, int cols, int tly, int tlx)
  1003. {
  1004. WINDOW *win = newwin(rows,cols,tly,tlx);
  1005. PANEL *pan;
  1006.  
  1007.     if(!win)
  1008.         return((PANEL *)0);
  1009.     if((pan = new_panel(win)))
  1010.         return(pan);
  1011.     delwin(win);
  1012.     return((PANEL *)0);
  1013. }    /* end of mkpanel */
  1014.  
  1015. /*+-------------------------------------------------------------------------
  1016.     rmpanel(pan)
  1017. --------------------------------------------------------------------------*/
  1018. static void
  1019. rmpanel(PANEL *pan)
  1020. {
  1021. WINDOW *win = pan->win;
  1022.     del_panel(pan);
  1023.     delwin(win);
  1024. }    /* end of rmpanel */
  1025.  
  1026. /*+-------------------------------------------------------------------------
  1027.     pflush()
  1028. --------------------------------------------------------------------------*/
  1029. static void
  1030. pflush(void)
  1031. {
  1032.     update_panels();
  1033.     doupdate();
  1034. }    /* end of pflush */
  1035.  
  1036. /*+-------------------------------------------------------------------------
  1037.     fill_panel(win)
  1038. --------------------------------------------------------------------------*/
  1039. static void
  1040. fill_panel(PANEL *pan)
  1041. {
  1042. WINDOW *win = pan->win;
  1043. chtype num = *(pan->user + 1);
  1044. int y,x;
  1045.  
  1046.     box(win, 0, 0);  
  1047.     wmove(win,1,1);
  1048.     wprintw(win,"-pan%c-",num);
  1049.     for(y = 2; y < getmaxy(win) - 1; y++)
  1050.     {
  1051.         for(x = 1; x < getmaxx(win) - 1; x++)
  1052.         {
  1053.             wmove(win,y,x);
  1054.             waddch(win,num);
  1055.         }
  1056.     }
  1057. }    /* end of fill_panel */
  1058.  
  1059. /*+-------------------------------------------------------------------------
  1060.     main(argc,argv)
  1061. --------------------------------------------------------------------------*/
  1062.  
  1063. static void demo_panels(void)
  1064. {
  1065. int itmp;
  1066. register y,x;
  1067.  
  1068. #ifdef FOO
  1069.     if((argc > 1) && atol(argv[1]))
  1070.         nap_msec = atol(argv[1]);
  1071. #endif /* FOO */
  1072.  
  1073.     refresh();
  1074.  
  1075.     for(y = 0; y < LINES - 1; y++)
  1076.     {
  1077.         for(x = 0; x < COLS; x++)
  1078.             wprintw(stdscr,"%d",(y + x) % 10);
  1079.     }
  1080.     for(y = 0; y < 5; y++)
  1081.     {
  1082.         p1 = mkpanel(10,10,0,0);
  1083.         w1 = panel_window(p1);
  1084.         set_panel_userptr(p1,"p1");
  1085.  
  1086.         p2 = mkpanel(14,14,5,5);
  1087.         w2 = panel_window(p2);
  1088.         set_panel_userptr(p2,"p2");
  1089.  
  1090.         p3 = mkpanel(6,8,12,12);
  1091.         w3 = panel_window(p3);
  1092.         set_panel_userptr(p3,"p3");
  1093.  
  1094.         p4 = mkpanel(10,10,10,30);
  1095.         w4 = panel_window(p4);
  1096.         set_panel_userptr(p4,"p4");
  1097.  
  1098.         p5 = mkpanel(10,10,13,37);
  1099.         w5 = panel_window(p5);
  1100.         set_panel_userptr(p5,"p5");
  1101.  
  1102.         fill_panel(p1);
  1103.         fill_panel(p2);
  1104.         fill_panel(p3);
  1105.         fill_panel(p4);
  1106.         fill_panel(p5);
  1107.         hide_panel(p4);
  1108.         hide_panel(p5);
  1109.         pflush();
  1110.         saywhat("press any key to continue");
  1111.         wait_a_while(nap_msec);
  1112.  
  1113.         saywhat("h3 s1 s2 s4 s5; press any key to continue");
  1114.         move_panel(p1,0,0);
  1115.         hide_panel(p3);
  1116.         show_panel(p1);
  1117.         show_panel(p2);
  1118.         show_panel(p4);
  1119.         show_panel(p5);
  1120.         pflush();
  1121.         wait_a_while(nap_msec);
  1122.  
  1123.         saywhat("s1; press any key to continue");
  1124.         show_panel(p1);
  1125.         pflush();
  1126.         wait_a_while(nap_msec);
  1127.  
  1128.         saywhat("s2; press any key to continue");
  1129.         show_panel(p2);
  1130.         pflush();
  1131.         wait_a_while(nap_msec);
  1132.  
  1133.         saywhat("m2; press any key to continue");
  1134.         move_panel(p2,10,10);
  1135.         pflush();
  1136.         wait_a_while(nap_msec);
  1137.  
  1138.         saywhat("s3;");
  1139.         show_panel(p3);
  1140.         pflush();
  1141.         wait_a_while(nap_msec);
  1142.  
  1143.         saywhat("m3; press any key to continue");
  1144.         move_panel(p3,5,5);
  1145.         pflush();
  1146.         wait_a_while(nap_msec);
  1147.  
  1148.         saywhat("b3; press any key to continue");
  1149.         bottom_panel(p3);
  1150.         pflush();
  1151.         wait_a_while(nap_msec);
  1152.  
  1153.         saywhat("s4; press any key to continue");
  1154.         show_panel(p4);
  1155.         pflush();
  1156.         wait_a_while(nap_msec);
  1157.  
  1158.         saywhat("s5; press any key to continue");
  1159.         show_panel(p5);
  1160.         pflush();
  1161.         wait_a_while(nap_msec);
  1162.  
  1163.         saywhat("t3; press any key to continue");
  1164.         top_panel(p3);
  1165.         pflush();
  1166.         wait_a_while(nap_msec);
  1167.  
  1168.         saywhat("t1; press any key to continue");
  1169.         top_panel(p1);
  1170.         pflush();
  1171.         wait_a_while(nap_msec);
  1172.  
  1173.         saywhat("t2; press any key to continue");
  1174.         top_panel(p2);
  1175.         pflush();
  1176.         wait_a_while(nap_msec);
  1177.  
  1178.         saywhat("t3; press any key to continue");
  1179.         top_panel(p3);
  1180.         pflush();
  1181.         wait_a_while(nap_msec);
  1182.  
  1183.         saywhat("t4; press any key to continue");
  1184.         top_panel(p4);
  1185.         pflush();
  1186.         wait_a_while(nap_msec);
  1187.  
  1188.         for(itmp = 0; itmp < 6; itmp++)
  1189.         {
  1190.             saywhat("m4; press any key to continue");
  1191.             wmove(w4,3,1);
  1192.             waddstr(w4,mod[itmp]);
  1193.             move_panel(p4,4,itmp*10);
  1194.             wmove(w5,4,1);
  1195.             waddstr(w5,mod[itmp]);
  1196.             pflush();
  1197.             wait_a_while(nap_msec);
  1198.             saywhat("m5; press any key to continue");
  1199.             wmove(w4,4,1);
  1200.             waddstr(w4,mod[itmp]);
  1201.             move_panel(p5,7,(itmp*10) + 6);
  1202.             wmove(w5,3,1);
  1203.             waddstr(w5,mod[itmp]);
  1204.             pflush();
  1205.             wait_a_while(nap_msec);
  1206.         }
  1207.  
  1208.         saywhat("m4; press any key to continue");
  1209.         move_panel(p4,4,itmp*10);
  1210.         pflush();
  1211.         wait_a_while(nap_msec);
  1212.  
  1213.         saywhat("t5; press any key to continue");
  1214.         top_panel(p5);
  1215.         pflush();
  1216.         wait_a_while(nap_msec);
  1217.  
  1218.         saywhat("t2; press any key to continue");
  1219.         top_panel(p2);
  1220.         pflush();
  1221.         wait_a_while(nap_msec);
  1222.  
  1223.         saywhat("t1; press any key to continue");
  1224.         top_panel(p1);
  1225.         pflush();
  1226.         wait_a_while(nap_msec);
  1227.  
  1228.         saywhat("d2; press any key to continue");
  1229.         rmpanel(p2);
  1230.         pflush();
  1231.         wait_a_while(nap_msec);
  1232.  
  1233.         saywhat("h3; press any key to continue");
  1234.         hide_panel(p3);
  1235.         pflush();
  1236.         wait_a_while(nap_msec);
  1237.  
  1238.         saywhat("d1; press any key to continue");
  1239.         rmpanel(p1);
  1240.         pflush();
  1241.         wait_a_while(nap_msec);
  1242.  
  1243.         saywhat("d4; press any key to continue");
  1244.         rmpanel(p4);
  1245.         pflush();
  1246.         wait_a_while(nap_msec);
  1247.  
  1248.         saywhat("d5; press any key to continue");
  1249.         rmpanel(p5);
  1250.         pflush();
  1251.         wait_a_while(nap_msec);
  1252.         if(nap_msec == 1)
  1253.             break;
  1254.         nap_msec = 100L;
  1255.     }
  1256.  
  1257.     erase();
  1258.     endwin();
  1259. }
  1260.  
  1261. /****************************************************************************
  1262.  *
  1263.  * Pad tester
  1264.  *
  1265.  ****************************************************************************/
  1266.  
  1267. #define GRIDSIZE    3
  1268.  
  1269. static void panner(WINDOW *pad, int iy, int ix, int (*pgetc)(WINDOW *))
  1270. {
  1271. #if HAVE_GETTIMEOFDAY
  1272.     struct timeval before, after;
  1273. #endif
  1274.     static int porty, portx, basex = 0, basey = 0;
  1275.     int pxmax, pymax, lowend, highend, i, j, c;
  1276.     int top_x = 0, top_y = 0;
  1277.  
  1278.     porty = iy; portx = ix;
  1279.  
  1280.     getmaxyx(pad, pymax, pxmax);
  1281.  
  1282.     c = KEY_REFRESH;
  1283.     do {
  1284.     switch(c)
  1285.     {
  1286.     case KEY_REFRESH:
  1287.         /* do nothing */
  1288.         break;
  1289.  
  1290.         /* Move the top-left corner of the pad, keeping the bottom-right
  1291.          * corner fixed.
  1292.          */
  1293.     case 'h':    /* increase-columns */
  1294.         if (top_x <= 0)
  1295.         beep();
  1296.         else
  1297.         {
  1298.         if (top_x-- > 0)
  1299.             for (i = top_y; i < porty; i++)
  1300.             mvaddch(i, top_x, ' ');
  1301.         }
  1302.         break;
  1303.  
  1304.     case 'j':    /* decrease-lines */
  1305.         if (top_y >= porty)
  1306.         beep();
  1307.         else
  1308.         {
  1309.         if (top_y > 0)
  1310.             for (j = top_x - (top_x > 0); j < portx; j++)
  1311.             mvaddch(top_y-1, j, ' ');
  1312.         top_y++;
  1313.         }
  1314.         break;
  1315.  
  1316.     case 'k':    /* increase-lines */
  1317.         if (top_y <= 0)
  1318.         beep();
  1319.         else
  1320.         {
  1321.         top_y--;
  1322.         for (j = top_x; j < portx; j++)
  1323.             mvaddch(top_y, j, ' ');
  1324.         }
  1325.         break;
  1326.  
  1327.     case 'l':    /* decrease-columns */
  1328.         if (top_x >= portx)
  1329.         beep();
  1330.         else
  1331.         {
  1332.         if (top_x > 0)
  1333.             for (i = top_y - (top_y > 0); i <= porty; i++)
  1334.             mvaddch(i, top_x-1, ' ');
  1335.         top_x++;
  1336.         }
  1337.         break;
  1338.  
  1339.         /* Move the bottom-right corner of the pad, keeping the top-left
  1340.          * corner fixed.
  1341.          */
  1342.     case KEY_IC:    /* increase-columns */
  1343.         if (portx >= pxmax || portx >= ix)
  1344.         beep();
  1345.         else
  1346.         {
  1347.         for (i = top_y; i < porty; i++)
  1348.             mvaddch(i, portx-1, ' ');
  1349.         ++portx;
  1350.         }
  1351.         break;
  1352.  
  1353.     case KEY_IL:    /* increase-lines */
  1354.         if (porty >= pymax || porty >= iy)
  1355.         beep();
  1356.         else
  1357.         {
  1358.         for (j = top_x; j < portx; j++)
  1359.             mvaddch(porty-1, j, ' ');
  1360.         ++porty;
  1361.         }
  1362.         break;
  1363.  
  1364.     case KEY_DC:    /* decrease-columns */
  1365.         if (portx <= top_x)
  1366.         beep();
  1367.         else
  1368.         {
  1369.         for (i = top_y - (top_y > 0); i < porty; i++)
  1370.             mvaddch(i, portx-1, ' ');
  1371.         --portx;
  1372.         }
  1373.         break;
  1374.  
  1375.     case KEY_DL:    /* decrease-lines */
  1376.         if (porty <= top_y)
  1377.         beep();
  1378.         else
  1379.         {
  1380.         for (j = top_x; j < portx; j++)
  1381.             mvaddch(porty-1, j, ' ');
  1382.         --porty;
  1383.         }
  1384.         break;
  1385.  
  1386.     case KEY_LEFT:
  1387.         if (basex > 0)
  1388.         basex--;
  1389.         else
  1390.         beep();
  1391.         break;
  1392.  
  1393.     case KEY_RIGHT:
  1394.         if (basex + portx - (pymax > porty) < pxmax)
  1395.         basex++;
  1396.         else
  1397.         beep();
  1398.         break;
  1399.  
  1400.     case KEY_UP:
  1401.         if (basey > 0)
  1402.         basey--;
  1403.         else
  1404.         beep();
  1405.         break;
  1406.  
  1407.     case KEY_DOWN:
  1408.         if (basey + porty - (pxmax > portx) < pymax)
  1409.         basey++;
  1410.         else
  1411.         beep();
  1412.         break;
  1413.     }
  1414.  
  1415.     if (top_x > 0) {
  1416.         for (i = top_y; i < porty; i++)
  1417.         mvaddch(i, top_x - 1, ACS_VLINE);
  1418.     }
  1419.  
  1420.     if (top_y > 0) {
  1421.         for (j = top_x; j < portx; j++)
  1422.         mvaddch(top_y - 1, j, ACS_HLINE);
  1423.     }
  1424.  
  1425.     if (top_x > 0 && top_y > 0)
  1426.         mvaddch(top_y - 1, top_x - 1, ACS_ULCORNER);
  1427.  
  1428.     if (pxmax > portx - 1) {
  1429.         int length  = (portx - top_x - 1);
  1430.         float ratio = ((float) length) / ((float) pxmax);
  1431.  
  1432.         lowend  = top_x + (basex * ratio);
  1433.         highend = top_x + ((basex + length) * ratio);
  1434.  
  1435.         for (j = top_x; j < lowend; j++)
  1436.         mvaddch(porty - 1, j, ACS_HLINE);
  1437.         attron(A_REVERSE);
  1438.         for (j = lowend; j <= highend; j++)
  1439.         mvaddch(porty - 1, j, ' ');
  1440.         attroff(A_REVERSE);
  1441.         for (j = highend + 1; j < portx; j++)
  1442.         mvaddch(porty - 1, j, ACS_HLINE);
  1443.         }
  1444.     if (pymax > porty - 1) {
  1445.         int length  = (porty - top_y - 1);
  1446.         float ratio = ((float) length) / ((float) pymax);
  1447.  
  1448.         lowend  = top_y + (basey * ratio);
  1449.         highend = top_y + ((basey + length) * ratio);
  1450.  
  1451.         for (i = top_y; i < lowend; i++)
  1452.         mvaddch(i, portx - 1, ACS_VLINE);
  1453.         attron(A_REVERSE);
  1454.         for (i = lowend; i <= highend; i++)
  1455.         mvaddch(i, portx - 1, ' ');
  1456.         attroff(A_REVERSE);
  1457.         for (i = highend + 1; i < porty; i++)
  1458.         mvaddch(i, portx - 1, ACS_VLINE);
  1459.         }
  1460.  
  1461.     if (top_y > 0)
  1462.         mvaddch(top_y - 1, portx - 1, ACS_URCORNER);
  1463.  
  1464.     if (top_x > 0)
  1465.         mvaddch(porty - 1, top_x - 1, ACS_LLCORNER);
  1466.  
  1467.     mvaddch(porty - 1, portx - 1, ACS_LRCORNER);
  1468.  
  1469. #if HAVE_GETTIMEOFDAY
  1470.     gettimeofday(&before, NULL);
  1471. #endif
  1472.     wnoutrefresh(stdscr);
  1473.  
  1474.     prefresh(pad,
  1475.          basey, basex,
  1476.          top_y, top_x,
  1477.          porty - (pxmax > portx) - 1,
  1478.          portx - (pymax > porty) - 1); 
  1479.  
  1480.     doupdate();
  1481. #if HAVE_GETTIMEOFDAY
  1482.     {
  1483.         double elapsed;
  1484.         gettimeofday(&after, NULL);
  1485.         elapsed = (after.tv_sec  + after.tv_usec  / 1.0e6)
  1486.              - (before.tv_sec + before.tv_usec / 1.0e6);
  1487.         move(LINES-1, COLS-15);
  1488.         printw("Secs: %8.03f", elapsed);
  1489.         refresh();
  1490.     }
  1491. #endif
  1492.  
  1493.     } while
  1494.     ((c = pgetc(pad)) != KEY_EXIT);
  1495. }
  1496.  
  1497. static
  1498. int padgetch(WINDOW *win)
  1499. {
  1500.     int    c;
  1501.  
  1502.     switch(c = wgetch(win))
  1503.     {
  1504.     case 'U': return(KEY_UP);
  1505.     case 'D': return(KEY_DOWN);
  1506.     case 'R': return(KEY_RIGHT);
  1507.     case 'L': return(KEY_LEFT);
  1508.     case '+': return(KEY_IL);
  1509.     case '-': return(KEY_DL);
  1510.     case '>': return(KEY_IC);
  1511.     case '<': return(KEY_DC);
  1512.     case 'q': return(KEY_EXIT);
  1513.     default: return(c);
  1514.     }
  1515. }
  1516.  
  1517. static void demo_pad(void)
  1518. /* Demonstrate pads. */
  1519. {
  1520.     int i, j;
  1521.     unsigned gridcount = 0;
  1522.     WINDOW *panpad = newpad(200, 200);
  1523.  
  1524.     for (i = 0; i < 200; i++)
  1525.     {
  1526.     for (j = 0; j < 200; j++)
  1527.         if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0)
  1528.         {
  1529.         if (i == 0 || j == 0)
  1530.             waddch(panpad, '+');
  1531.         else
  1532.             waddch(panpad, (chtype)('A' + (gridcount++ % 26)));
  1533.         }
  1534.             else if (i % GRIDSIZE == 0)
  1535.         waddch(panpad, '-');
  1536.             else if (j % GRIDSIZE == 0)
  1537.         waddch(panpad, '|');
  1538.         else
  1539.         waddch(panpad, ' ');
  1540.     }
  1541.     mvprintw(LINES - 3, 0, "Use arrow keys (or U,D,L,R) to pan over the test pattern - 'q' to quit");
  1542.     mvprintw(LINES - 2, 0, "Use +,- (or j,k) to grow/shrink the panner vertically.");
  1543.     mvprintw(LINES - 1, 0, "Use <,> (or h,l) to grow/shrink the panner horizontally.");
  1544.  
  1545.     keypad(panpad, TRUE);
  1546.     panner(panpad, LINES - 4, COLS, padgetch);
  1547.  
  1548.     endwin();
  1549.     erase();
  1550. }
  1551. #endif /* HAVE_PANEL_H */
  1552.  
  1553. /****************************************************************************
  1554.  *
  1555.  * Tests from John Burnell's PDCurses tester
  1556.  *
  1557.  ****************************************************************************/
  1558.  
  1559. static void Continue (WINDOW *win)
  1560. {
  1561.     noecho();
  1562.     wmove(win, 10, 1);
  1563.     mvwaddstr(win, 10, 1, " Press any key to continue");
  1564.     wrefresh(win);
  1565.     wgetch(win);
  1566. }
  1567.  
  1568. static void input_test(WINDOW *win)
  1569. /* Input test, adapted from John Burnell's PDCurses tester */
  1570. {
  1571.     int w, h, bx, by, sw, sh, i;
  1572.  
  1573.     WINDOW *subWin;
  1574.     wclear (win);
  1575.  
  1576. #ifdef FOO
  1577.     char buffer [80];
  1578.     int num;
  1579. #endif /* FOO */
  1580.  
  1581.     w  = win->_maxx;
  1582.     h  = win->_maxy;
  1583.     bx = win->_begx;
  1584.     by = win->_begy;
  1585.     sw = w / 3;
  1586.     sh = h / 3;
  1587.     if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
  1588.         return;
  1589.  
  1590. #ifdef A_COLOR
  1591.     if (has_colors())
  1592.     {
  1593.     init_pair(2,COLOR_CYAN,COLOR_BLUE);
  1594.     wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
  1595.     }
  1596.     else
  1597.     wattrset(subWin, A_BOLD);
  1598. #else
  1599.     wattrset(subWin, A_BOLD);
  1600. #endif
  1601.     box(subWin, ACS_VLINE, ACS_HLINE);
  1602. #ifdef FOO
  1603.     mvwaddstr(subWin, 2, 1, "This is a subwindow");
  1604. #endif /* FOO */
  1605.     wrefresh(win);
  1606.  
  1607.     nocbreak();
  1608.     mvwaddstr(win, 1, 1, "Type random keys for 5 seconds.");
  1609.     mvwaddstr(win, 2, 1,
  1610.       "These should be discarded (not echoed) after the subwindow goes away.");
  1611.     wrefresh(win);
  1612.  
  1613.     for (i = 0; i < 5; i++)
  1614.     {
  1615.     mvwprintw (subWin, 1, 1, "Time = %d", i);
  1616.     wrefresh(subWin);
  1617.     sleep(1);
  1618.     flushinp();
  1619.     }
  1620.  
  1621.     delwin (subWin);
  1622.     werase(win);
  1623.     flash();
  1624.     wrefresh(win);
  1625.     sleep(1);
  1626.  
  1627.     mvwaddstr(win, 2, 1, "Press a key");
  1628.     wmove(win, 9, 10);
  1629.     wrefresh(win);
  1630.     echo();
  1631.     wgetch(win);
  1632.     flushinp();
  1633.     mvwaddstr(win, 12, 0,
  1634.           "If you see any key other than what you typed, flushinp() is broken.");
  1635.     Continue(win);
  1636.  
  1637.     wmove(win, 9, 10);
  1638.     wdelch(win);
  1639.     wrefresh(win);
  1640.     wmove(win, 12, 0);
  1641.     clrtoeol();
  1642.     waddstr(win,
  1643.         "What you typed should now have been deleted; if not, wdelch() failed.");
  1644.     Continue(win);
  1645.  
  1646. #ifdef FOO
  1647.     /*
  1648.      * This test won't be portable until vsscanf() is
  1649.      */
  1650.     mvwaddstr(win, 6, 2, "Enter a number then a string separated by space");
  1651.     echo();
  1652.     mvwscanw(win, 7, 6, "%d %s", &num,buffer);
  1653.     mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num);
  1654. #endif /* FOO */
  1655.  
  1656.     Continue(win);
  1657. }
  1658.  
  1659. /****************************************************************************
  1660.  *
  1661.  * Menu test
  1662.  *
  1663.  ****************************************************************************/
  1664.  
  1665. #if HAVE_MENU_H
  1666.  
  1667. #define MENU_Y    4
  1668. #define MENU_X    4
  1669.  
  1670. static int menu_virtualize(int c)
  1671. {
  1672.     if (c == '\n' || c == KEY_EXIT)
  1673.     return(MAX_COMMAND + 1);
  1674.     else if (c == 'n' || c == KEY_DOWN)
  1675.     return(REQ_NEXT_ITEM);
  1676.     else if (c == 'p' || c == KEY_UP)
  1677.     return(REQ_PREV_ITEM);
  1678.     else
  1679.     return(c);
  1680. }
  1681.  
  1682. static char *animals[] =
  1683. {
  1684.     "Lions", "Tigers", "Bears", "(Oh my!)", "Newts", "Platypi", "Lemurs",
  1685.     (char *)NULL
  1686. };
  1687. static ITEM *items[sizeof(animals)/sizeof(char *)];
  1688.  
  1689. static void menu_test(void)
  1690. {
  1691.     MENU    *m;
  1692.     ITEM    **ip = items;
  1693.     char    **ap;
  1694.     int        mrows, mcols;
  1695.     WINDOW    *menuwin;
  1696.  
  1697.     mvaddstr(LINES - 3, 0, "This is the menu test.");
  1698.  
  1699.     for (ap = animals; *ap; ap++)
  1700.     *ip++ = new_item(*ap, "");
  1701.     *ip = (ITEM *)NULL;
  1702.  
  1703.     m = new_menu(items);
  1704.  
  1705.     scale_menu(m, &mrows, &mcols);
  1706.  
  1707.     menuwin = newwin(mrows + 2, mcols +  2, MENU_Y, MENU_X);
  1708.     set_menu_win(m, menuwin);
  1709.     keypad(menuwin, TRUE);
  1710.     box(menuwin, 0, 0);
  1711.  
  1712.     set_menu_sub(m, derwin(menuwin, mrows, mcols, 1, 1));
  1713.  
  1714.     post_menu(m);
  1715.  
  1716.     while (menu_driver(m, menu_virtualize(wgetch(menuwin))) != E_UNKNOWN_COMMAND)
  1717.     continue;
  1718.  
  1719.     (void) mvprintw(LINES - 2, 0,
  1720.              "You chose: %s\n", item_name(current_item(m)));
  1721.     (void) addstr("Press any key to continue...");
  1722.     wgetch(stdscr);
  1723.  
  1724.     unpost_menu(m);
  1725.     delwin(menuwin);
  1726.  
  1727.     for (ip = items; *ip; ip++)
  1728.     free_item(*ip);
  1729.     free_menu(m);
  1730. }
  1731. #endif /* HAVE_MENU_H */
  1732.  
  1733. /****************************************************************************
  1734.  *
  1735.  * Forms test
  1736.  *
  1737.  ****************************************************************************/
  1738. #if HAVE_FORM_H
  1739. static FIELD *make_label(int frow, int fcol, char *label)
  1740. {
  1741.     FIELD    *f = new_field(1, strlen(label), frow, fcol, 0, 0);
  1742.  
  1743.     if (f)
  1744.     {
  1745.     set_field_buffer(f, 0, label);
  1746.     set_field_opts(f, field_opts(f) & ~O_ACTIVE);
  1747.     }
  1748.     return(f);
  1749. }
  1750.  
  1751. static FIELD *make_field(int frow, int fcol, int rows, int cols)
  1752. {
  1753.     FIELD    *f = new_field(rows, cols, frow, fcol, 0, 0);
  1754.  
  1755.     if (f)
  1756.     set_field_back(f, A_UNDERLINE);
  1757.     return(f);
  1758. }
  1759.  
  1760. static void display_form(FORM *f)
  1761. {
  1762.     WINDOW    *w;
  1763.     int rows, cols;
  1764.  
  1765.     scale_form(f, &rows, &cols);
  1766.  
  1767.     if ((w =newwin(rows+2, cols+4, 0, 0)) != (WINDOW *)NULL)
  1768.     {
  1769.     set_form_win(f, w);
  1770.     set_form_sub(f, derwin(w, rows, cols, 1, 2));
  1771.     box(w, 0, 0);
  1772.     keypad(w, TRUE);
  1773.     }
  1774.  
  1775.     if (post_form(f) != E_OK)
  1776.     wrefresh(w);
  1777. }
  1778.  
  1779. static void erase_form(FORM *f)
  1780. {
  1781.     WINDOW    *w = form_win(f);
  1782.     WINDOW    *s = form_sub(f);
  1783.  
  1784.     unpost_form(f);
  1785.     werase(w);
  1786.     wrefresh(w);
  1787.     delwin(s);
  1788.     delwin(w);
  1789. }
  1790.  
  1791. static int form_virtualize(WINDOW *w)
  1792. {
  1793.     static int    mode = REQ_INS_MODE;
  1794.     int        c = wgetch(w);
  1795.  
  1796.     switch(c)
  1797.     {
  1798.     case CTRL('Q'):
  1799.     return(MAX_FORM_COMMAND + 1);
  1800.  
  1801.     /* demo doesn't use these three, leave them in anyway as sample code */
  1802.     case KEY_NPAGE:
  1803.     case CTRL('F'):
  1804.     return(REQ_NEXT_PAGE);
  1805.     case KEY_PPAGE:
  1806.     return(REQ_PREV_PAGE);
  1807.  
  1808.     case KEY_NEXT:
  1809.     case CTRL('N'):
  1810.     return(REQ_NEXT_FIELD);
  1811.     case KEY_PREVIOUS:
  1812.     case CTRL('P'):
  1813.     return(REQ_PREV_FIELD);
  1814.  
  1815.     case KEY_HOME:
  1816.     return(REQ_FIRST_FIELD);
  1817.     case KEY_END:
  1818.     case KEY_LL:
  1819.     return(REQ_LAST_FIELD);
  1820.  
  1821.     case CTRL('L'):
  1822.     return(REQ_LEFT_FIELD);
  1823.     case CTRL('R'):
  1824.     return(REQ_RIGHT_FIELD);
  1825.     case CTRL('U'):
  1826.     return(REQ_UP_FIELD);
  1827.     case CTRL('D'):
  1828.     return(REQ_DOWN_FIELD);
  1829.  
  1830.     case CTRL('W'):
  1831.     return(REQ_NEXT_WORD);
  1832.     case CTRL('T'):
  1833.     return(REQ_PREV_WORD);
  1834.     case CTRL('S'):
  1835.     return(REQ_BEG_FIELD);
  1836.     case CTRL('E'):
  1837.     return(REQ_END_FIELD);
  1838.  
  1839.     case KEY_LEFT:
  1840.     return(REQ_LEFT_CHAR);
  1841.     case KEY_RIGHT:
  1842.     return(REQ_RIGHT_CHAR);
  1843.     case KEY_UP:
  1844.     return(REQ_UP_CHAR);
  1845.     case KEY_DOWN:
  1846.     return(REQ_DOWN_CHAR);
  1847.  
  1848.     case CTRL('M'):
  1849.     return(REQ_NEW_LINE);
  1850.     case CTRL('I'):
  1851.     return(REQ_INS_CHAR);
  1852.     case CTRL('O'):
  1853.     return(REQ_INS_LINE);
  1854.     case CTRL('V'):
  1855.     return(REQ_DEL_CHAR);
  1856.  
  1857.     case CTRL('H'):
  1858.     case KEY_BACKSPACE:
  1859.     return(REQ_DEL_PREV);
  1860.     case CTRL('Y'):
  1861.     return(REQ_DEL_LINE);
  1862.     case CTRL('G'):
  1863.     return(REQ_DEL_WORD);
  1864.  
  1865.     case CTRL('C'):
  1866.     return(REQ_CLR_EOL);
  1867.     case CTRL('K'):
  1868.     return(REQ_CLR_EOF);
  1869.     case CTRL('X'):
  1870.     return(REQ_CLR_FIELD);
  1871.     case CTRL('A'):
  1872.     return(REQ_NEXT_CHOICE);
  1873.     case CTRL('Z'):
  1874.     return(REQ_PREV_CHOICE);
  1875.  
  1876.     case CTRL(']'):
  1877.     if (mode == REQ_INS_MODE)
  1878.         return(mode = REQ_OVL_MODE);
  1879.     else
  1880.         return(mode = REQ_INS_MODE);    
  1881.  
  1882.     default:
  1883.     return(c);
  1884.     }
  1885. }
  1886.  
  1887. static int my_form_driver(FORM *form, int c)
  1888. {
  1889.     if (c == (MAX_FORM_COMMAND + 1)
  1890.         && form_driver(form, REQ_VALIDATION) == E_OK)
  1891.     return(TRUE);
  1892.     else
  1893.     {
  1894.     beep();
  1895.     return(FALSE);
  1896.     }
  1897. }
  1898.  
  1899. static void demo_forms(void)
  1900. {
  1901.     WINDOW    *w;
  1902.     FORM    *form;
  1903.     FIELD    *f[10];
  1904.     int        finished = 0, c;
  1905.  
  1906.     mvaddstr(10, 57, "Forms Entry Test");
  1907.  
  1908.     move(18, 0);
  1909.     addstr("Defined form-traversal keys:   ^Q   -- exit form\n");
  1910.     addstr("^N   -- go to next field       ^P  -- go to previous field\n");
  1911.     addstr("Home -- go to first field      End -- go to last field\n");
  1912.     addstr("^L   -- go to field to left    ^R  -- go to field to right\n");
  1913.     addstr("^U   -- move upward to field   ^D  -- move downard to field\n");
  1914.     addstr("^W   -- go to next word        ^T  -- go to previous word\n");
  1915.     addstr("^S   -- go to start of field   ^E  -- go to end of field\n");
  1916.     addstr("^H   -- delete previous char   ^Y  -- delete line\n");
  1917.     addstr("^G   -- delete current word    ^C  -- clear to end of line\n");
  1918.     addstr("^K   -- clear to end of field  ^X  -- clear field\n");
  1919.     addstr("Arrow keys move within a field as you would expect.");
  1920.     refresh();
  1921.  
  1922.     /* describe the form */
  1923.     f[0] = make_label(0, 15, "Sample Form");
  1924.     f[1] = make_label(2, 0, "Last Name");
  1925.     f[2] = make_field(3, 0, 1, 18);
  1926.     f[3] = make_label(2, 20, "First Name");
  1927.     f[4] = make_field(3, 20, 1, 12);
  1928.     f[5] = make_label(2, 34, "Middle Name");
  1929.     f[6] = make_field(3, 34, 1, 12);
  1930.     f[7] = make_label(5, 0, "Comments");
  1931.     f[8] = make_field(6, 0, 4, 46);
  1932.     f[9] = (FIELD *)NULL;
  1933.  
  1934.     form = new_form(f);
  1935.  
  1936.     display_form(form);
  1937.  
  1938.     w = form_win(form);
  1939.     raw();
  1940.     while (!finished)
  1941.     {
  1942.     switch(form_driver(form, c = form_virtualize(w)))
  1943.     {
  1944.     case E_OK:
  1945.         break;
  1946.     case E_UNKNOWN_COMMAND:
  1947.         finished = my_form_driver(form, c);
  1948.         break;
  1949.     default:
  1950.         beep();
  1951.         break;
  1952.     }       
  1953.     }
  1954.  
  1955.     erase_form(form);
  1956.  
  1957.     free_form(form);
  1958. }
  1959. #endif    /* HAVE_FORM_H */
  1960.  
  1961. /****************************************************************************
  1962.  *
  1963.  * Overlap test
  1964.  *
  1965.  ****************************************************************************/
  1966.  
  1967. static void fillwin(WINDOW *win, char ch)
  1968. {
  1969.     int y, x;
  1970.  
  1971.     for (y = 0; y <= win->_maxy; y++)
  1972.     {
  1973.     wmove(win, y, 0);
  1974.     for (x = 0; x <= win->_maxx; x++)
  1975.         waddch(win, ch);
  1976.     }
  1977. }
  1978.  
  1979. static void crosswin(WINDOW *win, char ch)
  1980. {
  1981.     int y, x;
  1982.  
  1983.     for (y = 0; y <= win->_maxy; y++)
  1984.     {
  1985.     for (x = 0; x <= win->_maxx; x++)
  1986.         if (((x > win->_maxx / 3) && (x <= 2 * win->_maxx / 3))
  1987.             || (((y > win->_maxy / 3) && (y <= 2 * win->_maxy / 3))))
  1988.         {
  1989.         wmove(win, y, x);
  1990.         waddch(win, ch);
  1991.         }
  1992.     }
  1993. }
  1994.  
  1995. static void overlap_test(void)
  1996. /* test effects of overlapping windows */
  1997. {
  1998.     int    ch;
  1999.  
  2000.     WINDOW *win1 = newwin(9, 20, 3, 3);
  2001.     WINDOW *win2 = newwin(9, 20, 9, 16);
  2002.  
  2003.     refresh();
  2004.     move(0, 0);
  2005.     printw("This test shows the behavior of wnoutrefresh() with respect to\n");
  2006.     printw("the shared region of two overlapping windows.  The cross pattern\n");
  2007.     printw("in each wind does not overlap the other.\n");
  2008.  
  2009.  
  2010.     move(18, 0);
  2011.     printw("F1 = refresh window A, then window B, then doupdaute.\n");
  2012.     printw("F2 = refresh window B, then window A, then doupdaute.\n");
  2013.     printw("F3 = fill window A with letter A.  F4 = fill window B with letter B.\n");
  2014.     printw("F5 = cross pattern in window A.    F6 = cross pattern in window B.\n");
  2015.     printw("F7 = clear window A.               F8 = clear window B.\n");
  2016.     printw("F9 = terminate test.");
  2017.  
  2018.     while ((ch = getch()) != CTRL('D') && ch != KEY_F(9))
  2019.     switch (ch)
  2020.     {
  2021.     case KEY_F(1):        /* refresh window A first, then B */
  2022.         wnoutrefresh(win1);
  2023.         wnoutrefresh(win2);
  2024.         doupdate();
  2025.         break;
  2026.  
  2027.     case KEY_F(2):        /* refresh window B first, then A */
  2028.         wnoutrefresh(win2);
  2029.         wnoutrefresh(win1);
  2030.         doupdate();
  2031.         break;
  2032.  
  2033.     case KEY_F(3):        /* fill window A so it's visible */
  2034.         fillwin(win1, 'A');
  2035.         break;
  2036.  
  2037.     case KEY_F(4):        /* fill window B so it's visible */
  2038.         fillwin(win2, 'B');
  2039.         break;
  2040.  
  2041.     case KEY_F(5):        /* cross test pattern in window A */
  2042.         crosswin(win1, 'A');
  2043.         break;
  2044.  
  2045.     case KEY_F(6):        /* cross test pattern in window A */
  2046.         crosswin(win2, 'B');
  2047.         break;
  2048.  
  2049.     case KEY_F(7):        /* clear window A */
  2050.         wclear(win1);
  2051.         wmove(win1, 0, 0);
  2052.         break;
  2053.  
  2054.     case KEY_F(8):        /* clear window B */
  2055.         wclear(win2);
  2056.         wmove(win2, 0, 0);
  2057.         break;
  2058.     }
  2059.  
  2060.     erase();
  2061.     endwin();
  2062. }
  2063.  
  2064. /****************************************************************************
  2065.  *
  2066.  * Main sequence
  2067.  *
  2068.  ****************************************************************************/
  2069.  
  2070. static bool
  2071. do_single_test(const char c)
  2072. /* perform a single specified test */
  2073. {
  2074.     switch (c)
  2075.     {
  2076.     case 'a':
  2077.     getch_test();
  2078.     return(TRUE);
  2079.  
  2080.     case 'b':
  2081.     attr_test();
  2082.     return(TRUE);
  2083.  
  2084.     case 'c':
  2085.     if (!has_colors())
  2086.         Cannot("does not support color.");
  2087.     else
  2088.         color_test();
  2089.     return(TRUE);
  2090.  
  2091.     case 'd':
  2092.     if (!has_colors())
  2093.         Cannot("does not support color.");
  2094.     else if (!can_change_color())
  2095.         Cannot("has hardwired color values.");
  2096.     else
  2097.         color_edit();
  2098.     return(TRUE);
  2099.  
  2100.     case 'e':
  2101.     slk_test();
  2102.     return(TRUE);
  2103.  
  2104.     case 'f':
  2105.     acs_display();
  2106.     return(TRUE);
  2107.  
  2108. #if HAVE_PANEL_H
  2109.     case 'o':
  2110.     demo_panels();
  2111.     return(TRUE);
  2112. #endif
  2113.  
  2114.     case 'g':
  2115.     acs_and_scroll();
  2116.     return(TRUE);
  2117.  
  2118.     case 'i':
  2119.     input_test(stdscr);
  2120.     return(TRUE);
  2121.  
  2122. #if HAVE_MENU_H
  2123.     case 'm':
  2124.     menu_test();
  2125.     return(TRUE);
  2126. #endif
  2127.  
  2128. #if HAVE_PANEL_H
  2129.     case 'p':
  2130.     demo_pad();
  2131.     return(TRUE);
  2132. #endif
  2133.  
  2134. #if HAVE_FORM_H
  2135.     case 'r':
  2136.     demo_forms();
  2137.     return(TRUE);
  2138. #endif
  2139.  
  2140.     case 's':
  2141.         overlap_test();
  2142.     return(TRUE);
  2143.  
  2144.     case '?':
  2145.     (void) puts("This is the ncurses capability tester.");
  2146.     (void) puts("You may select a test from the main menu by typing the");
  2147.     (void) puts("key letter of the choice (the letter to left of the =)");
  2148.     (void) puts("at the > prompt.  The commands `x' or `q' will exit.");
  2149.     return(TRUE);
  2150.     }
  2151.  
  2152.     return(FALSE);
  2153. }
  2154.  
  2155. int main(const int argc, const char *argv[])
  2156. {
  2157.     char    buf[BUFSIZ];
  2158.  
  2159. #ifdef TRACE
  2160.     /* enable debugging */
  2161.     trace(TRACE_CALLS);
  2162. #endif
  2163.  
  2164.     /* tell it we're going to play with soft keys */
  2165.     slk_init(1);
  2166.  
  2167.     /* we must initialize the curses data structure only once */
  2168.     initscr();
  2169.  
  2170.     /* tests, in general, will want these modes */
  2171.     start_color();
  2172.     cbreak();
  2173.     noecho();
  2174.     scrollok(stdscr, TRUE);
  2175.     keypad(stdscr, TRUE);
  2176.  
  2177.     /*
  2178.      * Return to terminal mode, so we're guaranteed of being able to
  2179.      * select terminal commands even if the capabilities are wrong.
  2180.      */
  2181.     endwin();
  2182.  
  2183.     (void) puts("Welcome to ncurses.  Press ? for help.");
  2184.  
  2185.     do {
  2186.     (void) puts("This is the ncurses main menu");
  2187.     (void) puts("a = keyboard and mouse input test");
  2188.     (void) puts("b = character attribute test");
  2189.     (void) puts("c = color test pattern");
  2190.     (void) puts("d = edit RGB color values");
  2191.     (void) puts("e = exercise soft keys");
  2192.     (void) puts("f = display ACS characters");
  2193.     (void) puts("g = display windows and scrolling");
  2194.     (void) puts("i = subwindow input test");
  2195. #if HAVE_MENU_H
  2196.     (void) puts("m = menu code test");
  2197. #endif
  2198. #if HAVE_PANEL_H
  2199.     (void) puts("o = exercise panels library");
  2200.     (void) puts("p = exercise pad features");
  2201. #endif
  2202. #if HAVE_FORM_H
  2203.     (void) puts("r = exercise forms code");
  2204. #endif
  2205.     (void) puts("s = overlapping-refresh test");
  2206.     (void) puts("? = repeat this command summary");
  2207.  
  2208.     (void) fputs("> ", stdout);
  2209.     (void) fflush(stdout);        /* necessary under SVr4 curses */
  2210.     (void) fgets(buf, BUFSIZ, stdin);
  2211.  
  2212.     if (do_single_test(buf[0])) {
  2213.         clear();
  2214.         refresh();
  2215.         endwin();
  2216.         continue;
  2217.     }
  2218.     } while
  2219.     (buf[0] != 'q' && buf[0] != 'x');
  2220.  
  2221.     exit(0);
  2222. }
  2223.  
  2224. /* ncurses.c ends here */
  2225.