ncurses 5.3
[ncurses.git] / test / gdc.c
index ecef2bb1e1d1e876ac1d397e18184f981335ddd7..c466f2fde2674d95849d355f4bd980da2913f581 100644 (file)
  * modified 10-18-89 for curses (jrl)
  * 10-18-89 added signal handling
  *
- * $Id: gdc.c,v 1.10 1997/10/18 20:06:06 tom Exp $
+ * $Id: gdc.c,v 1.23 2002/08/10 19:20:14 tom Exp $
  */
 
-#include <test.priv.h>
-
 #include <time.h>
-#include <signal.h>
-#include <string.h>
+
+#include <test.priv.h>
 
 #define YBASE  10
 #define XBASE  10
 #define XLENGTH        54
 #define YDEPTH 5
 
-/* it won't be */
-static time_t now; /* yeah! */
-static struct tm *tm;
-
-static short disp[11] = {
-       075557, 011111, 071747, 071717, 055711,
-       074717, 074757, 071111, 075757, 075717, 002020
+static short disp[11] =
+{
+    075557, 011111, 071747, 071717, 055711,
+    074717, 074757, 071111, 075757, 075717, 002020
 };
 static long older[6], next[6], newer[6], mask;
-static char scrol;
 
 static int sigtermed = 0;
+static bool redirected = FALSE;
+static bool hascolor = FALSE;
 
-static int hascolor = 0;
-
-static void set(int, int);
-static void standt(int);
-static void movto(int, int);
-
-static
-RETSIGTYPE sighndl(int signo)
+static RETSIGTYPE
+sighndl(int signo)
 {
-       signal(signo, sighndl);
-       sigtermed=signo;
+    signal(signo, sighndl);
+    sigtermed = signo;
+    if (redirected) {
+       endwin();
+       ExitProgram(EXIT_FAILURE);
+    }
 }
 
 static void
 drawbox(void)
 {
-       chtype bottom[XLENGTH+1];
-       int n;
+    chtype bottom[XLENGTH + 1];
+    int n;
 
-       if(hascolor)
-               attrset(COLOR_PAIR(3));
+    if (hascolor)
+       attrset(COLOR_PAIR(3));
 
-       mvaddch(YBASE - 1,  XBASE - 1, ACS_ULCORNER);
-       hline(ACS_HLINE, XLENGTH);
-       mvaddch(YBASE - 1,  XBASE + XLENGTH, ACS_URCORNER);
+    mvaddch(YBASE - 1, XBASE - 1, ACS_ULCORNER);
+    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++)
-               bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
-       mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
-       mvaddch(YBASE + YDEPTH,  XBASE + XLENGTH, ACS_LRCORNER);
+    mvaddch(YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
+    mvinchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
+    for (n = 0; n < XLENGTH; n++)
+       bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
+    mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
+    mvaddch(YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
 
-       move(YBASE,  XBASE - 1);
-       vline(ACS_VLINE, YDEPTH);
+    move(YBASE, XBASE - 1);
+    vline(ACS_VLINE, YDEPTH);
 
-       move(YBASE,  XBASE + XLENGTH);
-       vline(ACS_VLINE, YDEPTH);
+    move(YBASE, XBASE + XLENGTH);
+    vline(ACS_VLINE, YDEPTH);
 
-       if(hascolor)
-               attrset(COLOR_PAIR(2));
+    if (hascolor)
+       attrset(COLOR_PAIR(2));
 }
 
-int
-main(int argc, char *argv[])
+static void
+standt(int on)
 {
-long t, a;
-int i, j, s, k;
-int n = 0;
-
-       signal(SIGINT,sighndl);
-       signal(SIGTERM,sighndl);
-       signal(SIGKILL,sighndl);
-
-       initscr();
-       cbreak();
-       noecho();
-       nodelay(stdscr, 1);
-       curs_set(0);
-
-       hascolor = has_colors();
-
-       if(hascolor) {
-               int bg = COLOR_BLACK;
-               start_color();
-#ifdef NCURSES_VERSION
-               if (use_default_colors() == OK)
-                       bg = -1;
-#endif
-               init_pair(1, COLOR_BLACK, COLOR_RED);
-               init_pair(2, COLOR_RED,   bg);
-               init_pair(3, COLOR_WHITE, bg);
-               attrset(COLOR_PAIR(2));
+    if (on) {
+       if (hascolor) {
+           attron(COLOR_PAIR(1));
+       } else {
+           attron(A_STANDOUT);
        }
-
-       clear();
-       refresh();
-       while(--argc > 0) {
-               if(**++argv == '-')
-                       scrol = 1;
-               else
-                       n = atoi(*argv);
+    } else {
+       if (hascolor) {
+           attron(COLOR_PAIR(2));
+       } else {
+           attroff(A_STANDOUT);
        }
-
-       drawbox();
-       do {
-               char    buf[30];
-
-               mask = 0;
-               time(&now);
-               tm = localtime(&now);
-               set(tm->tm_sec%10, 0);
-               set(tm->tm_sec/10, 4);
-               set(tm->tm_min%10, 10);
-               set(tm->tm_min/10, 14);
-               set(tm->tm_hour%10, 20);
-               set(tm->tm_hour/10, 24);
-               set(10, 7);
-               set(10, 17);
-               for(k=0; k<6; k++) {
-                       if(scrol) {
-                               for(i=0; i<5; i++)
-                                       newer[i] = (newer[i]&~mask) | (newer[i+1]&mask);
-                               newer[5] = (newer[5]&~mask) | (next[k]&mask);
-                       } else
-                               newer[k] = (newer[k]&~mask) | (next[k]&mask);
-                       next[k] = 0;
-                       for(s=1; s>=0; s--) {
-                               standt(s);
-                               for(i=0; i<6; i++) {
-                                       if((a = (newer[i]^older[i])&(s ? newer : older)[i]) != 0) {
-                                               for(j=0,t=1<<26; t; t>>=1,j++) {
-                                                       if(a&t) {
-                                                               if(!(a&(t<<1))) {
-                                                                       movto(YBASE + i, XBASE + 2*j);
-                                                               }
-                                                               addstr("  ");
-                                                       }
-                                               }
-                                       }
-                                       if(!s) {
-                                               older[i] = newer[i];
-                                       }
-                               }
-                               if(!s) {
-                                       if (scrol)
-                                               drawbox();
-                                       refresh();
-                                       if (scrol)
-                                               napms(150);
-                               }
-                       }
-               }
-
-               /* this depends on the detailed format of ctime(3) */
-               (void) strcpy(buf, ctime(&now));
-               (void) strcpy(buf + 10, buf + 19);
-               mvaddstr(16, 30, buf);
-
-               movto(6, 0);
-               drawbox();
-               refresh();
-               sleep(1);
-               while(wgetch(stdscr) != ERR)
-                       continue;
-               if (sigtermed) {
-                       standend();
-                       clear();
-                       refresh();
-                       curs_set(1);
-                       endwin();
-                       fprintf(stderr, "gdc terminated by signal %d\n", sigtermed);
-                       return EXIT_FAILURE;
-               }
-       } while(--n);
-       standend();
-       clear();
-       refresh();
-       curs_set(1);
-       endwin();
-       return EXIT_SUCCESS;
+    }
 }
 
 static void
 set(int t, int n)
 {
-int i, m;
+    int i, m;
 
-       m = 7<<n;
-       for(i=0; i<5; i++) {
-               next[i] |= ((disp[t]>>(4-i)*3)&07)<<n;
-               mask |= (next[i]^older[i])&m;
-       }
-       if(mask&m)
-               mask |= m;
+    m = 7 << n;
+    for (i = 0; i < 5; i++) {
+       next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n;
+       mask |= (next[i] ^ older[i]) & m;
+    }
+    if (mask & m)
+       mask |= m;
 }
 
 static void
-standt(int on)
+usage(void)
+{
+    static const char *msg[] =
+    {
+       "Usage: gdc [options] [count]"
+       ,""
+       ,"Options:"
+       ,"  -n  redirect input to /dev/null"
+       ,"  -s  scroll each number into place, rather than flipping"
+       ,""
+       ,"If you specify a count, gdc runs for that number of seconds"
+    };
+    unsigned j;
+    for (j = 0; j < SIZEOF(msg); j++)
+       fprintf(stderr, "%s\n", msg[j]);
+    ExitProgram(EXIT_FAILURE);
+}
+
+int
+main(int argc, char *argv[])
 {
-       if (on) {
-               if(hascolor) {
-                       attron(COLOR_PAIR(1));
-               } else {
-                       attron(A_STANDOUT);
+    time_t now;
+    struct tm *tm;
+    long t, a;
+    int i, j, s, k;
+    int count = 0;
+    FILE *ofp = stdout;
+    FILE *ifp = stdin;
+    bool scrol = FALSE;
+
+    setlocale(LC_ALL, "");
+
+    signal(SIGINT, sighndl);
+    signal(SIGTERM, sighndl);
+
+    while ((k = getopt(argc, argv, "sn")) != EOF) {
+       switch (k) {
+       case 's':
+           scrol = TRUE;
+           break;
+       case 'n':
+           ifp = fopen("/dev/null", "r");
+           redirected = TRUE;
+           break;
+       default:
+           usage();
+       }
+    }
+    if (optind < argc) {
+       count = atoi(argv[optind++]);
+    }
+    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);
+       }
+
+    } else {
+       initscr();
+    }
+    cbreak();
+    noecho();
+    nodelay(stdscr, 1);
+    curs_set(0);
+
+    hascolor = has_colors();
+
+    if (hascolor) {
+       int bg = COLOR_BLACK;
+       start_color();
+#if HAVE_USE_DEFAULT_COLORS
+       if (use_default_colors() == OK)
+           bg = -1;
+#endif
+       init_pair(1, COLOR_BLACK, COLOR_RED);
+       init_pair(2, COLOR_RED, bg);
+       init_pair(3, COLOR_WHITE, bg);
+       attrset(COLOR_PAIR(2));
+    }
+
+  restart:
+    for (j = 0; j < 5; j++)
+       older[j] = newer[j] = next[j] = 0;
+
+    clear();
+    drawbox();
+
+    do {
+       char buf[30];
+
+       time(&now);
+       tm = localtime(&now);
+
+       mask = 0;
+       set(tm->tm_sec % 10, 0);
+       set(tm->tm_sec / 10, 4);
+       set(tm->tm_min % 10, 10);
+       set(tm->tm_min / 10, 14);
+       set(tm->tm_hour % 10, 20);
+       set(tm->tm_hour / 10, 24);
+       set(10, 7);
+       set(10, 17);
+
+       for (k = 0; k < 6; k++) {
+           if (scrol) {
+               for (i = 0; i < 5; i++)
+                   newer[i] = (newer[i] & ~mask) | (newer[i + 1] & mask);
+               newer[5] = (newer[5] & ~mask) | (next[k] & mask);
+           } else
+               newer[k] = (newer[k] & ~mask) | (next[k] & mask);
+           next[k] = 0;
+           for (s = 1; s >= 0; s--) {
+               standt(s);
+               for (i = 0; i < 6; i++) {
+                   if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
+                       != 0) {
+                       for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
+                           if (a & t) {
+                               if (!(a & (t << 1))) {
+                                   move(YBASE + i, XBASE + 2 * j);
+                               }
+                               addstr("  ");
+                           }
+                       }
+                   }
+                   if (!s) {
+                       older[i] = newer[i];
+                   }
                }
-       } else {
-               if(hascolor) {
-                       attron(COLOR_PAIR(2));
-               } else {
-                       attroff(A_STANDOUT);
+               if (!s) {
+                   if (scrol)
+                       drawbox();
+                   refresh();
+                   /*
+                    * If we're scrolling, space out the refreshes to fake
+                    * movement.  That's 7 frames, or 6 intervals, which would
+                    * be 166 msec if we spread it out over a second.  It looks
+                    * better (but will well on a slow terminal, e.g., less
+                    * than 9600bd) to squeeze that into a half-second, and use
+                    * half of 170 msec to ensure that the program doesn't eat
+                    * a lot of time when asking what time it is, at the top of
+                    * this loop -TD
+                    */
+                   if (scrol)
+                       napms(85);
                }
+           }
        }
-}
 
-static void
-movto(int line, int col)
-{
-       move(line, col);
+       /* this depends on the detailed format of ctime(3) */
+       (void) strcpy(buf, ctime(&now));
+       (void) strcpy(buf + 10, buf + 19);
+       mvaddstr(16, 30, buf);
+
+       move(6, 0);
+       drawbox();
+       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 (scrol)
+           napms(500);
+       else
+           napms(1000);
+
+       /*
+        * This is a safe way to check if we're interrupted - making the signal
+        * handler set a flag that we can check.  Since we're running
+        * nodelay(), the wgetch() call returns immediately, and in particular
+        * will return an error if interrupted.  This works only if we can
+        * read from the input, of course.
+        */
+       switch (wgetch(stdscr)) {
+       case 'q':
+           count = 1;
+           break;
+       case 's':
+           nodelay(stdscr, FALSE);
+           break;
+       case ' ':
+           nodelay(stdscr, TRUE);
+           break;
+#ifdef KEY_RESIZE
+       case KEY_RESIZE:
+#endif
+       case '?':
+           goto restart;
+       case ERR:
+           if (sigtermed) {
+               standend();
+               endwin();
+               fprintf(stderr, "gdc terminated by signal %d\n", sigtermed);
+               ExitProgram(EXIT_FAILURE);
+           }
+           /* FALLTHRU */
+       default:
+           continue;
+       }
+    } while (--count);
+    standend();
+    endwin();
+    ExitProgram(EXIT_SUCCESS);
 }