ncurses 6.2 - patch 20200627
[ncurses.git] / test / blue.c
index 0f15d01dce81958668ec971753a0760b697dbe94..922caab94396181e9c957a5b9ebe5421072329f4 100644 (file)
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc.              *
+ * Copyright 2019,2020 Thomas E. Dickey                                     *
+ * Copyright 1998-2016,2017 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            *
  *****************************************************************************/
 
 /*
- * Compile this with the command `cc -O blue.c -lcurses -o blue'.  For best
- * results, use the ncurses(3) library.  On non-Intel machines, SVr4 curses is
- * just as good.
- *
- * $Id: blue.c,v 1.29 2006/05/20 15:38:18 tom Exp $
+ * $Id: blue.c,v 1.53 2020/02/02 23:34:34 tom Exp $
  */
 
 #include <test.priv.h>
 
 #include <time.h>
 
+#if HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+
 #define NOCARD         (-1)
 
 #define ACE            0
@@ -70,7 +71,7 @@
 #define BLACK_ON_WHITE  2
 #define BLUE_ON_WHITE   3
 
-static RETSIGTYPE die(int onsig) GCC_NORETURN;
+static void die(int onsig) GCC_NORETURN;
 
 static int deck_size = PACK_SIZE;      /* initial deck */
 static int deck[PACK_SIZE];
@@ -97,42 +98,40 @@ static chtype ranks[SUIT_LENGTH][2] =
     {' ', 'K'}
 };
 
-/* Please note, that this is a bad example.
-   Color values should not be or'ed in. This
-   only works, because the characters used here
-   are plain and have no color attribute themselves. */
-#ifdef COLOR_PAIR
-#define OR_COLORS(value,pair) ((value) | COLOR_PAIR(pair))
-#else
-#define OR_COLORS(value,pair) (value)
-#endif
+static int letters[4] =
+{
+    'h',                       /* hearts */
+    's',                       /* spades */
+    'd',                       /* diamonds */
+    'c',                       /* clubs */
+};
 
-#define PC_COLORS(value,pair) (OR_COLORS(value,pair) | A_ALTCHARSET)
+#if HAVE_LANGINFO_CODESET
 
-static chtype letters[4] =
+#if HAVE_TIGETSTR
+static int glyphs[] =
 {
-    OR_COLORS('h', RED_ON_WHITE),      /* hearts */
-    OR_COLORS('s', BLACK_ON_WHITE),    /* spades */
-    OR_COLORS('d', RED_ON_WHITE),      /* diamonds */
-    OR_COLORS('c', BLACK_ON_WHITE),    /* clubs */
+    '\003',                    /* hearts */
+    '\006',                    /* spades */
+    '\004',                    /* diamonds */
+    '\005',                    /* clubs */
 };
+#endif
 
-#if defined(__i386__) && defined(A_ALTCHARSET) && HAVE_TIGETSTR
-static chtype glyphs[] =
+#if USE_WIDEC_SUPPORT
+static int uglyphs[] =
 {
-    PC_COLORS('\003', RED_ON_WHITE),   /* hearts */
-    PC_COLORS('\006', BLACK_ON_WHITE), /* spades */
-    PC_COLORS('\004', RED_ON_WHITE),   /* diamonds */
-    PC_COLORS('\005', BLACK_ON_WHITE), /* clubs */
+    0x2665,                    /* hearts */
+    0x2660,                    /* spades */
+    0x2666,                    /* diamonds */
+    0x2663                     /* clubs */
 };
-#define USE_CP437 1
-#else
-#define USE_CP437 0
-#endif /* __i386__ */
+#endif
+#endif /* HAVE_LANGINFO_CODESET */
 
-static chtype *suits = letters;        /* this may change to glyphs below */
+static int *suits = letters;   /* this may change to glyphs below */
 
-static RETSIGTYPE
+static void
 die(int onsig)
 {
     (void) signal(onsig, SIG_IGN);
@@ -155,14 +154,14 @@ init_vars(void)
 static void
 shuffle(int size)
 {
-    int i, j, numswaps, swapnum, temp;
+    int numswaps, swapnum;
 
     numswaps = size * 10;      /* an arbitrary figure */
 
     for (swapnum = 0; swapnum < numswaps; swapnum++) {
-       i = rand() % size;
-       j = rand() % size;
-       temp = deck[i];
+       int i = rand() % size;
+       int j = rand() % size;
+       int temp = deck[i];
        deck[i] = deck[j];
        deck[j] = temp;
     }
@@ -171,10 +170,11 @@ shuffle(int size)
 static void
 deal_cards(void)
 {
-    int ptr, card = 0, value, csuit, crank, suit, aces[4];
+    int card = 0, value, csuit, crank, suit, aces[4];
 
+    memset(aces, 0, sizeof(aces));
     for (suit = HEARTS; suit <= CLUBS; suit++) {
-       ptr = freeptr[suit];
+       int ptr = freeptr[suit];
        grid[ptr++] = NOCARD;   /* 1st card space is blank */
        while ((ptr % GRID_WIDTH) != 0) {
            value = deck[card++];
@@ -197,15 +197,41 @@ deal_cards(void)
 static void
 printcard(int value)
 {
-    (void) addch(' ');
-    if (value == NOCARD)
+    AddCh(' ');
+    if (value == NOCARD) {
        (void) addstr("   ");
-    else {
-       addch(ranks[value % SUIT_LENGTH][0] | COLOR_PAIR(BLUE_ON_WHITE));
-       addch(ranks[value % SUIT_LENGTH][1] | COLOR_PAIR(BLUE_ON_WHITE));
-       addch(suits[value / SUIT_LENGTH]);
+    } else {
+       int which = (value / SUIT_LENGTH);
+       int isuit = (value % SUIT_LENGTH);
+       chtype color = (chtype) COLOR_PAIR(((which % 2) == 0)
+                                          ? RED_ON_WHITE
+                                          : BLACK_ON_WHITE);
+
+       AddCh(ranks[isuit][0] | (chtype) COLOR_PAIR(BLUE_ON_WHITE));
+       AddCh(ranks[isuit][1] | (chtype) COLOR_PAIR(BLUE_ON_WHITE));
+
+#ifdef NCURSES_VERSION
+       (attron) ((int) color); /* quieter compiler warnings */
+#else
+       attron(color);          /* PDCurses, etc., either no macro or wrong */
+#endif
+#if USE_WIDEC_SUPPORT
+       {
+           wchar_t values[2];
+           values[0] = (wchar_t) suits[which];
+           values[1] = 0;
+           addwstr(values);
+       }
+#else
+       AddCh(suits[which]);
+#endif
+#ifdef NCURSES_VERSION
+       (attroff) ((int) color);
+#else
+       attroff(color);
+#endif
     }
-    (void) addch(' ');
+    AddCh(' ');
 }
 
 static void
@@ -299,7 +325,7 @@ play_game(void)
                if (selection[i] != NOCARD) {
                    move(BASEROW + (selection[i] / GRID_WIDTH) * 2 + 3,
                         (selection[i] % GRID_WIDTH) * 5);
-                   (void) printw("   %c ", *lp++ = 'a' + i);
+                   (void) printw("   %c ", (*lp++ = (char) ('a' + i)));
                }
            };
            *lp = '\0';
@@ -314,18 +340,20 @@ play_game(void)
            } else {
                char buf[BUFSIZ];
 
-               (void) sprintf(buf,
-                              "Type [%s] to move, r to redraw, q or INTR to quit: ",
-                              live);
+               _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+                           "Type [%s] to move, r to redraw, q or INTR to quit: ",
+                           live);
 
                do {
                    move(PROMPTROW, 0);
                    (void) addstr(buf);
                    move(PROMPTROW, (int) strlen(buf));
                    clrtoeol();
-                   (void) addch(' ');
+                   AddCh(' ');
                } while
-                   (((c = getch()) < 'a' || c > 'd') && (c != 'r') && (c != 'q'));
+                   (((c = (char) getch()) < 'a' || c > 'd')
+                    && (c != 'r')
+                    && (c != 'q'));
            }
 
            for (j = 0; j < 4; j++)
@@ -352,19 +380,19 @@ play_game(void)
     }
 
     move(PROMPTROW, 0);
-    standout();
+    (void) standout();
     (void) printw("Finished deal %d - type any character to continue...", deal_number);
-    standend();
+    (void) standend();
     (void) getch();
 }
 
 static int
 collect_discards(void)
 {
-    int row, col, cardno = 0, finish, gridno;
+    int row, col, cardno = 0, gridno;
 
     for (row = HEARTS; row <= CLUBS; row++) {
-       finish = 0;
+       int finish = 0;
        for (col = 1; col < GRID_WIDTH; col++) {
            gridno = row * GRID_WIDTH + col;
 
@@ -385,7 +413,7 @@ game_finished(int deal)
 {
     clear();
     (void) printw("You finished the game in %d deals. This is ", deal);
-    standout();
+    (void) standout();
     if (deal < 2)
        (void) addstr("excellent");
     else if (deal < 4)
@@ -394,46 +422,63 @@ game_finished(int deal)
        (void) addstr("average");
     else
        (void) addstr("poor");
-    standend();
+    (void) standend();
     (void) addstr(".         ");
     refresh();
 }
 
+#if HAVE_LANGINFO_CODESET
+/*
+ * This program first appeared in ncurses in January 1995.  At that point, the
+ * Linux console was able to display CP437 graphic characters, e.g., in the
+ * range 0-31.  As of 2016, most Linux consoles are running with the UTF-8
+ * (partial) support.  Incidentally, that makes all of the cards diamonds.
+ */
+static void
+use_pc_display(void)
+{
+    char *check = nl_langinfo(CODESET);
+    if (!strcmp(check, "UTF-8")) {
+#if USE_WIDEC_SUPPORT
+       suits = uglyphs;
+#endif
+    } else {
+#if HAVE_TIGETSTR
+       if (!strcmp(check, "IBM437") ||
+           !strcmp(check, "CP437") ||
+           !strcmp(check, "IBM850") ||
+           !strcmp(check, "CP850")) {
+           char *smacs = tigetstr("smacs");
+           char *smpch = tigetstr("smpch");
+           /*
+            * The ncurses library makes this check to decide whether to allow
+            * the alternate character set for the (normally) nonprinting codes.
+            */
+           if (smacs != 0 && smpch != 0 && !strcmp(smacs, smpch)) {
+               suits = glyphs;
+           }
+       }
+#endif
+    }
+}
+#else
+#define use_pc_display()       /* nothing */
+#endif /* HAVE_LANGINFO_CODESET */
+
 int
 main(int argc, char *argv[])
 {
-    CATCHALL(die);
-
     setlocale(LC_ALL, "");
 
-    initscr();
+    use_pc_display();
+
+    InitAndCatch(initscr(), die);
 
-    /*
-     * We use COLOR_GREEN because COLOR_BLACK is wired to the wrong thing.
-     */
     start_color();
     init_pair(RED_ON_WHITE, COLOR_RED, COLOR_WHITE);
     init_pair(BLUE_ON_WHITE, COLOR_BLUE, COLOR_WHITE);
     init_pair(BLACK_ON_WHITE, COLOR_BLACK, COLOR_WHITE);
 
-#ifndef COLOR_PAIR
-    letters[0] = OR_COLORS('h', RED_ON_WHITE); /* hearts */
-    letters[1] = OR_COLORS('s', BLACK_ON_WHITE);       /* spades */
-    letters[2] = OR_COLORS('d', RED_ON_WHITE); /* diamonds */
-    letters[3] = OR_COLORS('c', BLACK_ON_WHITE);       /* clubs */
-#if USE_CP437
-    glyphs[0] = PC_COLORS('\003', RED_ON_WHITE);       /* hearts */
-    glyphs[1] = PC_COLORS('\006', BLACK_ON_WHITE);     /* spades */
-    glyphs[2] = PC_COLORS('\004', RED_ON_WHITE);       /* diamonds */
-    glyphs[3] = PC_COLORS('\005', BLACK_ON_WHITE);     /* clubs */
-#endif
-#endif
-
-#if USE_CP437
-    if (tigetstr("smpch"))
-       suits = glyphs;
-#endif /* USE_CP437 */
-
     cbreak();
 
     if (argc == 2)