]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/picsmap.c
ncurses 6.3 - patch 20220416
[ncurses.git] / test / picsmap.c
index baa5de8465f04cab54befa838eabe4568ca303aa..bf8133a42399d4b1c4e5f245055e20af34dcb1be 100644 (file)
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2017-2018,2019 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2022 Thomas E. Dickey                                *
+ * Copyright 2017,2018 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            *
@@ -26,7 +27,7 @@
  * authorization.                                                           *
  ****************************************************************************/
 /*
- * $Id: picsmap.c,v 1.130 2019/08/24 23:07:34 tom Exp $
+ * $Id: picsmap.c,v 1.145 2022/04/16 18:21:05 tom Exp $
  *
  * Author: Thomas E. Dickey
  *
@@ -103,12 +104,12 @@ typedef struct {
 #define P2I(n) (((int)(my_intptr_t)(n)) - 1)
 #define I2P(n) (void *)(my_intptr_t)((n) + 1)
 
-#define stop_curses() if (in_curses) endwin()
+#define pause_curses() if (in_curses) stop_curses()
 
 #define debugmsg if (debugging) logmsg
 #define debugmsg2 if (debugging) logmsg2
 
-static void cleanup(int) GCC_NORETURN;
+static GCC_NORETURN void cleanup(int);
 static void giveup(const char *fmt, ...) GCC_PRINTFLIKE(1, 2);
 static void logmsg(const char *fmt, ...) GCC_PRINTFLIKE(1, 2);
 static void logmsg2(const char *fmt, ...) GCC_PRINTFLIKE(1, 2);
@@ -187,7 +188,7 @@ close_log(void)
 static void
 cleanup(int code)
 {
-    stop_curses();
+    pause_curses();
     close_log();
     ExitProgram(code);
     /* NOTREACHED */
@@ -423,7 +424,7 @@ read_file(const char *filename)
     struct stat sb;
 
     if (!quiet) {
-       stop_curses();
+       pause_curses();
        printf("** %s\n", filename);
     }
 
@@ -511,7 +512,7 @@ usage(void)
     };
     size_t n;
 
-    stop_curses();
+    pause_curses();
 
     fflush(stdout);
     for (n = 0; n < SIZEOF(msg); n++)
@@ -524,7 +525,7 @@ giveup(const char *fmt, ...)
 {
     va_list ap;
 
-    stop_curses();
+    pause_curses();
     fflush(stdout);
 
     va_start(ap, fmt);
@@ -603,7 +604,6 @@ read_palette(const char *filename)
                    continue;
                }
            }
-           s += strlen(s);
 
            if (tries & 2) {
                int len = (int) strlen(filename);
@@ -797,6 +797,7 @@ match_c(const char *source, const char *pattern, ...)
     int ch;
     int *ip;
     char *cp;
+    float *fp;
     long lv;
 
     va_start(ap, pattern);
@@ -810,10 +811,13 @@ match_c(const char *source, const char *pattern, ...)
            continue;
        }
        /* %c, %d, %s are like sscanf except for special treatment of blanks */
-       if (ch == '%' && *pattern != '\0' && strchr("cdnsx", *pattern)) {
+       if (ch == '%' && *pattern != '\0' && strchr("%cdnfsx", *pattern)) {
            bool found = FALSE;
            ch = *pattern++;
            switch (ch) {
+           case '%':
+               source++;
+               break;
            case 'c':
                cp = va_arg(ap, char *);
                do {
@@ -832,6 +836,29 @@ match_c(const char *source, const char *pattern, ...)
                    goto finish;
                }
                break;
+           case 'f':
+               /* floating point for pixels... */
+               fp = va_arg(ap, float *);
+               lv = strtol(source, &cp, 10);
+               if (cp == 0 || cp == source)
+                   goto finish;
+               *fp = (float) lv;
+               source = cp;
+               if (*source == '.') {
+                   lv = strtol(++source, &cp, 10);
+                   if (cp == 0 || cp == source)
+                       goto finish;
+                   {
+                       float scale = 1.0f;
+                       int digits = (int) (cp - source);
+                       while (digits-- > 0) {
+                           scale *= 10.0f;
+                       }
+                       *fp += (float) lv / scale;
+                   }
+                   source = cp;
+               }
+               break;
            case 'n':
                /* not really sscanf... */
                limit = *va_arg(ap, int *);
@@ -954,6 +981,20 @@ parse_rgb(char **data)
     return result;
 }
 
+#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
+
+static int
+CaselessCmp(const char *a, const char *b)
+{                              /* strcasecmp isn't portable */
+    while (*a && *b) {
+       int cmp = LOWERCASE(*a) - LOWERCASE(*b);
+       if (cmp != 0)
+           break;
+       a++, b++;
+    }
+    return LOWERCASE(*a) - LOWERCASE(*b);
+}
+
 static RGB_NAME *
 lookup_rgb(const char *name)
 {
@@ -961,7 +1002,7 @@ lookup_rgb(const char *name)
     if (rgb_table != 0) {
        int n;
        for (n = 0; rgb_table[n].name != 0; ++n) {
-           if (!strcasecmp(name, rgb_table[n].name)) {
+           if (!CaselessCmp(name, rgb_table[n].name)) {
                result = &rgb_table[n];
                break;
            }
@@ -975,7 +1016,7 @@ parse_xbm(char **data)
 {
     int n;
     int state = 0;
-    char buf[BUFSIZ];
+    char buf[2048];
     int num;
     char ch;
     char *s;
@@ -1000,7 +1041,7 @@ parse_xbm(char **data)
        case 0:
        case 1:
        case 2:
-           if (sscanf(s, "#define %s %d%c", buf, &num, &ch) >= 2) {
+           if (sscanf(s, "#define %1024s %d%c", buf, &num, &ch) >= 2) {
                if ((t = strstr(buf, "_width")) != 0) {
                    state |= 1;
                    result->wide = (short) bytes_of(num);
@@ -1021,7 +1062,7 @@ parse_xbm(char **data)
            }
            break;
        case 3:
-           if (sscanf(s, "static char %[^_ ]_bits[]%c", buf, &ch) >= 1) {
+           if (sscanf(s, "static char %1024[^_ ]_bits[]%c", buf, &ch) >= 1) {
                if (strcmp(result->name, buf)) {
                    goto finish;
                }
@@ -1332,11 +1373,16 @@ parse_img(const char *filename)
                    break;
                }
            } else {
-               /* subsequent lines begin "col,row: (r,g,b,a) #RGB" */
+               /*
+                * subsequent lines begin "col,row: (r,g,b,a) #RGB".
+                * Those r/g/b could be integers (0..255) or float-percentages.
+                */
                int r, g, b, nocolor;
+               float rf, gf, bf;
                unsigned check;
                char *t;
                char *s = t = strchr(buffer, '#');
+               bool matched = FALSE;
 
                if (s != 0) {
                    /* after the "#RGB", there are differences - just ignore */
@@ -1344,19 +1390,44 @@ parse_img(const char *filename)
                        ++s;
                    *++s = '\0';
                }
+
                if (match_c(buffer,
                            "%d,%d: (%d,%d,%d,%d) #%x ",
                            &col, &row,
                            &r, &g, &b, &nocolor,
                            &check)) {
+                   matched = TRUE;
+               } else if (match_c(buffer,
+                                  "%d,%d: (%f%%,%f%%,%f%%,%d) #%x ",
+                                  &col, &row,
+                                  &rf, &gf, &bf, &nocolor,
+                                  &check) ||
+                          match_c(buffer,
+                                  "%d,%d: (%f%%,%f%%,%f%%) #%x ",
+                                  &col, &row,
+                                  &rf, &gf, &bf,
+                                  &check)) {
+                   matched = TRUE;
+
+#define fp_fix(n) (int) (MaxRGB * (((n) > 100.0 ? 100.0 : (n)) / 100.0))
+
+                   r = fp_fix(rf);
+                   g = fp_fix(gf);
+                   b = fp_fix(bf);
+               }
+               if ((s - t) > 8)        /* 6 hex digits vs 8 */
+                   check /= 256;
+               if (matched) {
                    int which, c;
+                   int want_r = (check >> 16) & 0xff;
+                   int want_g = (check >> 8) & 0xff;
+                   int want_b = (check >> 0) & 0xff;
 
-                   if ((s - t) > 8)    /* 6 hex digits vs 8 */
-                       check /= 256;
-                   if (r > MaxRGB ||
-                       g > MaxRGB ||
-                       b > MaxRGB ||
-                       check != (unsigned) ((r << 16) | (g << 8) | b)) {
+#define fp_err(tst,ref) ((tst > MaxRGB) || ((tst - ref)*(tst - ref)) > 4)
+
+                   if (fp_err(r, want_r) ||
+                       fp_err(g, want_g) ||
+                       fp_err(b, want_b)) {
                        okay = FALSE;
                        break;
                    }
@@ -1456,6 +1527,7 @@ init_display(const char *palette_path, int opt_d)
     (void) opt_d;
     if (isatty(fileno(stdout))) {
        in_curses = TRUE;
+       setlocale(LC_ALL, "");
        initscr();
        cbreak();
        noecho();
@@ -1469,7 +1541,7 @@ init_display(const char *palette_path, int opt_d)
            init_palette(palette_path);
        }
        scrollok(stdscr, FALSE);
-       exit_curses();
+       stop_curses();
     }
 }
 
@@ -1597,7 +1669,7 @@ report_colors(PICS_HEAD * pics)
            for (k = 0; k < wide; ++k) {
                int n = j + (k * high);
                size_t want = (sizeof(buffer) - (size_t) (s - buffer));
-               if (want < 100)
+               if (want < 100 || want >= sizeof(buffer))
                    break;
                if (n >= pics->colors)
                    break;