ncurses 5.6 - patch 20080209
[ncurses.git] / test / demo_menus.c
index 3e77c487978f4c312ff0f62536f80c32d7b9b876..84322eb4a8da1053efa1a149e58a1ad6b07b56b0 100644 (file)
@@ -1,5 +1,32 @@
+/****************************************************************************
+ * Copyright (c) 2005-2007,2008 Free Software Foundation, Inc.              *
+ *                                                                          *
+ * Permission is hereby granted, free of charge, to any person obtaining a  *
+ * copy of this software and associated documentation files (the            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
 /*
- * $Id: demo_menus.c,v 1.13 2005/10/01 15:54:31 tom Exp $
+ * $Id: demo_menus.c,v 1.22 2008/02/09 18:09:26 tom Exp $
  *
  * Demonstrate a variety of functions from the menu library.
  * Thomas Dickey - 2005/4/9
@@ -18,10 +45,8 @@ menu_fore                    -
 menu_format                    -
 menu_grey                      -
 menu_init                      -
-menu_mark                      -
 menu_opts                      -
 menu_pad                       -
-menu_pattern                   -
 menu_request_by_name           -
 menu_request_name              -
 menu_sub                       -
@@ -65,14 +90,17 @@ static MENU *mpTrace;
 #endif
 
 typedef enum {
-    eUnknown = -1
-    ,eFile = 0
+    eBanner = -1
+    ,eFile
     ,eSelect
 #ifdef TRACE
     ,eTrace
 #endif
+    ,eMAX
 } MenuNo;
 
+#define okMenuNo(n) (((n) > eBanner) && ((n) < eMAX))
+
 #define MENU_Y 1
 
 static MENU *mpBanner;
@@ -162,7 +190,7 @@ menu_offset(MenuNo number)
 {
     int result = 0;
 
-    if ((int) number >= 0) {
+    if (okMenuNo(number)) {
        int spc_desc, spc_rows, spc_cols;
 
 #ifdef NCURSES_VERSION
@@ -172,7 +200,7 @@ menu_offset(MenuNo number)
 #endif
 
        /* FIXME: MENU.itemlen seems the only way to get actual width of items */
-       result = number * (mpBanner->itemlen + spc_rows);
+       result = (number - (eBanner + 1)) * (mpBanner->itemlen + spc_rows);
     }
     return result;
 }
@@ -183,7 +211,7 @@ menu_create(ITEM ** items, int count, int ncols, MenuNo number)
     MENU *result;
     WINDOW *menuwin;
     int mrows, mcols;
-    int y = ((int) number >= 0) ? MENU_Y : 0;
+    int y = okMenuNo(number) ? MENU_Y : 0;
     int x = menu_offset(number);
     int margin = (y == MENU_Y) ? 1 : 0;
     int maxcol = (ncols + x) < COLS ? ncols : (COLS - x - 1);
@@ -232,6 +260,7 @@ menu_destroy(MENU * m)
     int count;
 
     if (m != 0) {
+       delwin(menu_sub(m));
        delwin(menu_win(m));
 
        ip = menu_items(m);
@@ -262,7 +291,7 @@ menu_display(MENU * m)
 static void
 build_file_menu(MenuNo number)
 {
-    static const char *labels[] =
+    static CONST_MENUS char *labels[] =
     {
        "Exit",
        (char *) 0
@@ -270,7 +299,7 @@ build_file_menu(MenuNo number)
     static ITEM *items[SIZEOF(labels)];
 
     ITEM **ip = items;
-    const char **ap;
+    CONST_MENUS char **ap;
 
     for (ap = labels; *ap; ap++)
        *ip++ = new_item(*ap, "");
@@ -290,7 +319,7 @@ perform_file_menu(int cmd)
 static void
 build_select_menu(MenuNo number, char *filename)
 {
-    static const char *labels[] =
+    static CONST_MENUS char *labels[] =
     {
        "Lions",
        "Tigers",
@@ -310,7 +339,7 @@ build_select_menu(MenuNo number, char *filename)
     static ITEM **items;
 
     ITEM **ip;
-    const char **ap = 0;
+    CONST_MENUS char **ap = 0;
     unsigned count = 0;
 
     if (filename != 0) {
@@ -321,7 +350,8 @@ build_select_menu(MenuNo number, char *filename)
            unsigned size = sb.st_size;
            unsigned j, k;
            char *blob = malloc(size + 1);
-           const char **list = (const char **) calloc(sizeof(*list), size + 1);
+           CONST_MENUS char **list =
+           (CONST_MENUS char **) calloc(sizeof(*list), size + 1);
 
            items = (ITEM **) calloc(sizeof(ITEM *), size + 1);
            if (blob != 0 && list != 0) {
@@ -510,7 +540,7 @@ perform_trace_menu(int cmd)
 static int
 menu_number(void)
 {
-    return item_index(current_item(mpBanner));
+    return item_index(current_item(mpBanner)) - (eBanner + 1);
 }
 
 static MENU *
@@ -540,7 +570,7 @@ current_menu(void)
 static void
 build_menus(char *filename)
 {
-    static const char *labels[] =
+    static CONST_MENUS char *labels[] =
     {
        "File",
        "Select",
@@ -552,13 +582,13 @@ build_menus(char *filename)
     static ITEM *items[SIZEOF(labels)];
 
     ITEM **ip = items;
-    const char **ap;
+    CONST_MENUS char **ap;
 
     for (ap = labels; *ap; ap++)
        *ip++ = new_item(*ap, "");
     *ip = (ITEM *) 0;
 
-    mpBanner = menu_create(items, SIZEOF(labels) - 1, SIZEOF(labels) - 1, eUnknown);
+    mpBanner = menu_create(items, SIZEOF(labels) - 1, SIZEOF(labels) - 1, eBanner);
     set_menu_mark(mpBanner, ">");
 
     build_file_menu(eFile);
@@ -568,12 +598,77 @@ build_menus(char *filename)
 #endif
 }
 
+static int
+move_menu(MENU * menu, MENU * current, int by_y, int by_x)
+{
+    WINDOW *top_win = menu_win(menu);
+    WINDOW *sub_win = menu_sub(menu);
+    int y0, x0;
+    int y1, x1;
+    int result;
+
+    getbegyx(top_win, y0, x0);
+    y0 += by_y;
+    x0 += by_x;
+
+    getbegyx(sub_win, y1, x1);
+    y1 += by_y;
+    x1 += by_x;
+
+    if ((result = mvwin(top_win, y0, x0)) != ERR) {
+#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20060218)
+       sub_win->_begy = y1;
+       sub_win->_begx = x1;
+#else
+       mvwin(sub_win, y1, x1);
+#endif
+       if (menu == current) {
+           touchwin(top_win);
+           wnoutrefresh(top_win);
+       }
+    }
+    return result;
+}
+
+/*
+ * Move the menus around on the screen, to test mvwin().
+ */
+static void
+move_menus(MENU * current, int by_y, int by_x)
+{
+    if (move_menu(mpBanner, current, by_y, by_x) != ERR) {
+       erase();
+       wnoutrefresh(stdscr);
+       move_menu(mpFile, current, by_y, by_x);
+       move_menu(mpSelect, current, by_y, by_x);
+#ifdef TRACE
+       move_menu(mpTrace, current, by_y, by_x);
+#endif
+       doupdate();
+    }
+}
+
+static void
+show_status(int ch, MENU * menu)
+{
+    move(LINES - 1, 0);
+    printw("key %s, menu %d, mark %s, match %s",
+          keyname(ch),
+          menu_number(),
+          menu_mark(menu),
+          menu_pattern(menu));
+    clrtoeol();
+    refresh();
+}
+
 static void
 perform_menus(void)
 {
     MENU *this_menu;
     MENU *last_menu = mpFile;
-    int code = E_UNKNOWN_COMMAND, cmd, ch;
+    int code = E_UNKNOWN_COMMAND;
+    int cmd;
+    int ch = ERR;
 
 #ifdef NCURSES_MOUSE_VERSION
     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
@@ -582,7 +677,30 @@ perform_menus(void)
     menu_display(last_menu);
 
     for (;;) {
+
+       if (ch != ERR)
+           show_status(ch, last_menu);
+
        ch = menu_getc(mpBanner);
+
+       /*
+        * Provide for moving the menu around in the screen using shifted
+        * cursor keys.
+        */
+       switch (ch) {
+       case KEY_SF:
+           move_menus(last_menu, 1, 0);
+           continue;
+       case KEY_SR:
+           move_menus(last_menu, -1, 0);
+           continue;
+       case KEY_SLEFT:
+           move_menus(last_menu, 0, -1);
+           continue;
+       case KEY_SRIGHT:
+           move_menus(last_menu, 0, 1);
+           continue;
+       }
        cmd = menu_virtualize(ch);
 
        switch (cmd) {
@@ -664,11 +782,79 @@ destroy_menus(void)
     menu_destroy(mpBanner);
 }
 
+#if HAVE_RIPOFFLINE
+static int
+rip_footer(WINDOW *win, int cols)
+{
+    wbkgd(win, A_REVERSE);
+    werase(win);
+    wmove(win, 0, 0);
+    wprintw(win, "footer: %d columns", cols);
+    wnoutrefresh(win);
+    return OK;
+}
+
+static int
+rip_header(WINDOW *win, int cols)
+{
+    wbkgd(win, A_REVERSE);
+    werase(win);
+    wmove(win, 0, 0);
+    wprintw(win, "header: %d columns", cols);
+    wnoutrefresh(win);
+    return OK;
+}
+#endif /* HAVE_RIPOFFLINE */
+
+static void
+usage(void)
+{
+    static const char *const tbl[] =
+    {
+       "Usage: demo_menus [options]"
+       ,""
+       ,"Options:"
+#if HAVE_RIPOFFLINE
+       ,"  -f       rip-off footer line (can repeat)"
+       ,"  -h       rip-off header line (can repeat)"
+#endif
+#ifdef TRACE
+       ,"  -t mask  specify default trace-level (may toggle with ^T)"
+#endif
+    };
+    size_t n;
+    for (n = 0; n < SIZEOF(tbl); n++)
+       fprintf(stderr, "%s\n", tbl[n]);
+    ExitProgram(EXIT_FAILURE);
+}
+
 int
 main(int argc, char *argv[])
 {
+    int c;
+
     setlocale(LC_ALL, "");
 
+    while ((c = getopt(argc, argv, "a:de:fhmp:s:t:")) != -1) {
+       switch (c) {
+#if HAVE_RIPOFFLINE
+       case 'f':
+           ripoffline(-1, rip_footer);
+           break;
+       case 'h':
+           ripoffline(1, rip_header);
+           break;
+#endif /* HAVE_RIPOFFLINE */
+#ifdef TRACE
+       case 't':
+           trace(strtoul(optarg, 0, 0));
+           break;
+#endif
+       default:
+           usage();
+       }
+    }
+
     initscr();
     noraw();
     cbreak();
@@ -684,7 +870,7 @@ main(int argc, char *argv[])
     destroy_menus();
 
     endwin();
-    return EXIT_SUCCESS;
+    ExitProgram(EXIT_SUCCESS);
 }
 #else
 int