ncurses 6.1 - patch 20191123
[ncurses.git] / test / gdc.c
index 7aa2e0cadacbf694c27720b5f28049f5f07fcb5b..c2ef5b11522bf5c252b57e715dd91737f4a93959 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2017,2019 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            *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  ****************************************************************************/
 /*
  * Grand digital clock for curses compatible terminals
  ****************************************************************************/
 /*
  * Grand digital clock for curses compatible terminals
- * Usage: gdc [-s] [n]   -- run for n seconds (default infinity)
+ * Usage: gdc [-s] [-t hh:mm:ss] [n] -- run for n seconds (default infinity)
  * Flags: -s: scroll
  *
  * modified 10-18-89 for curses (jrl)
  * 10-18-89 added signal handling
  *
  * Flags: -s: scroll
  *
  * modified 10-18-89 for curses (jrl)
  * 10-18-89 added signal handling
  *
- * $Id: gdc.c,v 1.29 2007/07/21 17:45:09 tom Exp $
+ * $Id: gdc.c,v 1.52 2019/08/24 23:11:01 tom Exp $
  */
 
 #include <test.priv.h>
  */
 
 #include <test.priv.h>
@@ -60,13 +60,24 @@ static int sigtermed = 0;
 static bool redirected = FALSE;
 static bool hascolor = FALSE;
 
 static bool redirected = FALSE;
 static bool hascolor = FALSE;
 
-static RETSIGTYPE
+static void
 sighndl(int signo)
 {
     signal(signo, sighndl);
     sigtermed = signo;
     if (redirected) {
 sighndl(int signo)
 {
     signal(signo, sighndl);
     sigtermed = signo;
     if (redirected) {
-       endwin();
+       exit_curses();
+       ExitProgram(EXIT_FAILURE);
+    }
+}
+
+static void
+check_term(void)
+{
+    if (sigtermed) {
+       (void) standend();
+       exit_curses();
+       fprintf(stderr, "gdc terminated by signal %d\n", sigtermed);
        ExitProgram(EXIT_FAILURE);
     }
 }
        ExitProgram(EXIT_FAILURE);
     }
 }
@@ -75,24 +86,25 @@ static void
 drawbox(bool scrolling)
 {
     chtype bottom[XLENGTH + 1];
 drawbox(bool scrolling)
 {
     chtype bottom[XLENGTH + 1];
-    int n;
 
     if (hascolor)
 
     if (hascolor)
-       attrset(COLOR_PAIR(PAIR_FRAMES));
+       (void) attrset(AttrArg(COLOR_PAIR(PAIR_FRAMES), 0));
 
 
-    mvaddch(YBASE - 1, XBASE - 1, ACS_ULCORNER);
+    MvAddCh(YBASE - 1, XBASE - 1, ACS_ULCORNER);
     hline(ACS_HLINE, XLENGTH);
     hline(ACS_HLINE, XLENGTH);
-    mvaddch(YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
-
-    mvaddch(YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
-    mvinchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
-    for (n = 0; n < XLENGTH; n++) {
-       if (!scrolling)
-           bottom[n] &= ~A_COLOR;
-       bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
+    MvAddCh(YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
+
+    MvAddCh(YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
+    if ((mvinchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH)) != ERR) {
+       int n;
+       for (n = 0; n < XLENGTH; n++) {
+           if (!scrolling)
+               bottom[n] &= ~A_COLOR;
+           bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
+       }
+       (void) mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
     }
     }
-    mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
-    mvaddch(YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
+    MvAddCh(YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
 
     move(YBASE, XBASE - 1);
     vline(ACS_VLINE, YDEPTH);
 
     move(YBASE, XBASE - 1);
     vline(ACS_VLINE, YDEPTH);
@@ -101,7 +113,7 @@ drawbox(bool scrolling)
     vline(ACS_VLINE, YDEPTH);
 
     if (hascolor)
     vline(ACS_VLINE, YDEPTH);
 
     if (hascolor)
-       attrset(COLOR_PAIR(PAIR_OTHERS));
+       (void) attrset(AttrArg(COLOR_PAIR(PAIR_OTHERS), 0));
 }
 
 static void
 }
 
 static void
@@ -144,8 +156,12 @@ usage(void)
        "Usage: gdc [options] [count]"
        ,""
        ,"Options:"
        "Usage: gdc [options] [count]"
        ,""
        ,"Options:"
-       ,"  -n  redirect input to /dev/null"
-       ,"  -s  scroll each number into place, rather than flipping"
+#if HAVE_USE_DEFAULT_COLORS
+       ,"  -d       invoke use_default_colors"
+#endif
+       ,"  -n       redirect input to /dev/null"
+       ,"  -s       scroll each number into place, rather than flipping"
+       ,"  -t hh:mm:ss specify starting time (default is ``now'')"
        ,""
        ,"If you specify a count, gdc runs for that number of seconds"
     };
        ,""
        ,"If you specify a count, gdc runs for that number of seconds"
     };
@@ -155,6 +171,43 @@ usage(void)
     ExitProgram(EXIT_FAILURE);
 }
 
     ExitProgram(EXIT_FAILURE);
 }
 
+static time_t
+parse_time(const char *value)
+{
+    int hh, mm, ss;
+    int check;
+    time_t result;
+    char c;
+    struct tm *tm;
+
+    if (sscanf(value, "%d:%d:%d%c", &hh, &mm, &ss, &c) != 3) {
+       if (sscanf(value, "%02d%02d%02d%c", &hh, &mm, &ss, &c) != 3) {
+           usage();
+       }
+    }
+
+    if ((hh < 0) || (hh >= 24) ||
+       (mm < 0) || (mm >= 60) ||
+       (ss < 0) || (ss >= 60)) {
+       usage();
+    }
+
+    /* adjust so that the localtime in the main loop will give usable time */
+    result = (hh * 3600) + ((mm * 60) + ss);
+    for (check = 0; check < 24; ++check) {
+       tm = localtime(&result);
+       if (tm->tm_hour == hh)
+           break;
+       result += 3600;
+    }
+
+    if (tm->tm_hour != hh) {
+       fprintf(stderr, "Cannot find local time for %s!\n", value);
+       usage();
+    }
+    return result;
+}
+
 int
 main(int argc, char *argv[])
 {
 int
 main(int argc, char *argv[])
 {
@@ -165,42 +218,57 @@ main(int argc, char *argv[])
     int count = 0;
     FILE *ofp = stdout;
     FILE *ifp = stdin;
     int count = 0;
     FILE *ofp = stdout;
     FILE *ifp = stdin;
-    bool scrol = FALSE;
+    bool smooth = FALSE;
+    bool stages = FALSE;
+    time_t starts = 0;
+#if HAVE_USE_DEFAULT_COLORS
+    bool d_option = FALSE;
+#endif
 
     setlocale(LC_ALL, "");
 
 
     setlocale(LC_ALL, "");
 
-    CATCHALL(sighndl);
-
-    while ((k = getopt(argc, argv, "sn")) != -1) {
+    while ((k = getopt(argc, argv, "dnst:")) != -1) {
        switch (k) {
        switch (k) {
-       case 's':
-           scrol = TRUE;
+#if HAVE_USE_DEFAULT_COLORS
+       case 'd':
+           d_option = TRUE;
            break;
            break;
+#endif
        case 'n':
            ifp = fopen("/dev/null", "r");
            redirected = TRUE;
            break;
        case 'n':
            ifp = fopen("/dev/null", "r");
            redirected = TRUE;
            break;
+       case 's':
+           smooth = TRUE;
+           break;
+       case 't':
+           starts = parse_time(optarg);
+           break;
        default:
            usage();
        }
     }
     if (optind < argc) {
        count = atoi(argv[optind++]);
        default:
            usage();
        }
     }
     if (optind < argc) {
        count = atoi(argv[optind++]);
+       assert(count >= 0);
+       if (optind < argc)
+           usage();
     }
     }
-    if (optind < argc)
-       usage();
 
 
-    if (redirected) {
-       char *name = getenv("TERM");
-       if (name == 0
-           || newterm(name, ofp, ifp) == 0) {
-           fprintf(stderr, "cannot open terminal\n");
-           ExitProgram(EXIT_FAILURE);
+    InitAndCatch({
+       if (redirected) {
+           char *name = getenv("TERM");
+           if (name == 0
+               || newterm(name, ofp, ifp) == 0) {
+               fprintf(stderr, "cannot open terminal\n");
+               ExitProgram(EXIT_FAILURE);
+           }
+       } else {
+           initscr();
        }
        }
-
-    } else {
-       initscr();
     }
     }
+    ,sighndl);
+
     cbreak();
     noecho();
     nodelay(stdscr, 1);
     cbreak();
     noecho();
     nodelay(stdscr, 1);
@@ -209,16 +277,16 @@ main(int argc, char *argv[])
     hascolor = has_colors();
 
     if (hascolor) {
     hascolor = has_colors();
 
     if (hascolor) {
-       int bg = COLOR_BLACK;
+       short bg = COLOR_BLACK;
        start_color();
 #if HAVE_USE_DEFAULT_COLORS
        start_color();
 #if HAVE_USE_DEFAULT_COLORS
-       if (use_default_colors() == OK)
+       if (d_option && (use_default_colors() == OK))
            bg = -1;
 #endif
        init_pair(PAIR_DIGITS, COLOR_BLACK, COLOR_RED);
        init_pair(PAIR_OTHERS, COLOR_RED, bg);
        init_pair(PAIR_FRAMES, COLOR_WHITE, bg);
            bg = -1;
 #endif
        init_pair(PAIR_DIGITS, COLOR_BLACK, COLOR_RED);
        init_pair(PAIR_OTHERS, COLOR_RED, bg);
        init_pair(PAIR_FRAMES, COLOR_WHITE, bg);
-       attrset(COLOR_PAIR(PAIR_OTHERS));
+       (void) attrset(AttrArg(COLOR_PAIR(PAIR_OTHERS), 0));
     }
 
   restart:
     }
 
   restart:
@@ -229,9 +297,13 @@ main(int argc, char *argv[])
     drawbox(FALSE);
 
     do {
     drawbox(FALSE);
 
     do {
-       char buf[30];
+       char buf[40];
 
 
-       time(&now);
+       if (starts != 0) {
+           now = ++starts;
+       } else {
+           time(&now);
+       }
        tm = localtime(&now);
 
        mask = 0;
        tm = localtime(&now);
 
        mask = 0;
@@ -245,12 +317,13 @@ main(int argc, char *argv[])
        set(10, 17);
 
        for (k = 0; k < 6; k++) {
        set(10, 17);
 
        for (k = 0; k < 6; k++) {
-           if (scrol) {
+           if (smooth) {
                for (i = 0; i < 5; i++)
                    newer[i] = (newer[i] & ~mask) | (newer[i + 1] & mask);
                newer[5] = (newer[5] & ~mask) | (next[k] & mask);
                for (i = 0; i < 5; i++)
                    newer[i] = (newer[i] & ~mask) | (newer[i + 1] & mask);
                newer[5] = (newer[5] & ~mask) | (next[k] & mask);
-           } else
+           } else {
                newer[k] = (newer[k] & ~mask) | (next[k] & mask);
                newer[k] = (newer[k] & ~mask) | (next[k] & mask);
+           }
            next[k] = 0;
            for (s = 1; s >= 0; s--) {
                standt(s);
            next[k] = 0;
            for (s = 1; s >= 0; s--) {
                standt(s);
@@ -271,7 +344,7 @@ main(int argc, char *argv[])
                    }
                }
                if (!s) {
                    }
                }
                if (!s) {
-                   if (scrol)
+                   if (smooth)
                        drawbox(TRUE);
                    refresh();
                    /*
                        drawbox(TRUE);
                    refresh();
                    /*
@@ -284,27 +357,58 @@ main(int argc, char *argv[])
                     * a lot of time when asking what time it is, at the top of
                     * this loop -T.Dickey
                     */
                     * a lot of time when asking what time it is, at the top of
                     * this loop -T.Dickey
                     */
-                   if (scrol)
+                   if (smooth)
                        napms(85);
                        napms(85);
+                   if (stages) {
+                       stages = FALSE;
+                       switch (wgetch(stdscr)) {
+                       case 'q':
+                           count = 1;
+                           break;
+                       case 'S':
+                           stages = TRUE;
+                           /* FALLTHRU */
+                       case 's':
+                           nodelay(stdscr, FALSE);
+                           break;
+                       case ' ':
+                           nodelay(stdscr, TRUE);
+                           break;
+#ifdef KEY_RESIZE
+                       case KEY_RESIZE:
+#endif
+                       case '?':
+                           goto restart;
+                       case ERR:
+                           check_term();
+                           /* FALLTHRU */
+                       default:
+                           continue;
+                       }
+                   }
                }
            }
        }
 
        /* this depends on the detailed format of ctime(3) */
                }
            }
        }
 
        /* this depends on the detailed format of ctime(3) */
-       (void) strcpy(buf, ctime(&now));
-       (void) strcpy(buf + 10, buf + 19);
-       mvaddstr(16, 30, buf);
+       _nc_STRNCPY(buf, ctime(&now), (size_t) 30);
+       {
+           char *d2 = buf + 10;
+           char *s2 = buf + 19;
+           while ((*d2++ = *s2++) != '\0') ;
+       }
+       MvAddStr(16, 30, buf);
 
        move(6, 0);
        drawbox(FALSE);
        refresh();
 
        /*
 
        move(6, 0);
        drawbox(FALSE);
        refresh();
 
        /*
-        * If we're not scrolling, wait 1000 msec (1 sec).  Use napms() rather
-        * than sleep() because the latter does odd things on some systems,
-        * e.g., suspending output as well.
+        * If we're not smooth-scrolling, wait 1000 msec (1 sec).  Use napms()
+        * rather than sleep() because the latter does odd things on some
+        * systems, e.g., suspending output as well.
         */
         */
-       if (scrol)
+       if (smooth)
            napms(500);
        else
            napms(1000);
            napms(500);
        else
            napms(1000);
@@ -316,10 +420,14 @@ main(int argc, char *argv[])
         * will return an error if interrupted.  This works only if we can
         * read from the input, of course.
         */
         * will return an error if interrupted.  This works only if we can
         * read from the input, of course.
         */
+       stages = FALSE;
        switch (wgetch(stdscr)) {
        case 'q':
            count = 1;
            break;
        switch (wgetch(stdscr)) {
        case 'q':
            count = 1;
            break;
+       case 'S':
+           stages = TRUE;
+           /* FALLTHRU */
        case 's':
            nodelay(stdscr, FALSE);
            break;
        case 's':
            nodelay(stdscr, FALSE);
            break;
@@ -332,18 +440,13 @@ main(int argc, char *argv[])
        case '?':
            goto restart;
        case ERR:
        case '?':
            goto restart;
        case ERR:
-           if (sigtermed) {
-               standend();
-               endwin();
-               fprintf(stderr, "gdc terminated by signal %d\n", sigtermed);
-               ExitProgram(EXIT_FAILURE);
-           }
+           check_term();
            /* FALLTHRU */
        default:
            continue;
        }
     } while (--count);
            /* FALLTHRU */
        default:
            continue;
        }
     } while (--count);
-    standend();
-    endwin();
+    (void) standend();
+    exit_curses();
     ExitProgram(EXIT_SUCCESS);
 }
     ExitProgram(EXIT_SUCCESS);
 }