/****************************************************************************
- * 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 *
* 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
*
#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);
static void
cleanup(int code)
{
- stop_curses();
+ pause_curses();
close_log();
ExitProgram(code);
/* NOTREACHED */
struct stat sb;
if (!quiet) {
- stop_curses();
+ pause_curses();
printf("** %s\n", filename);
}
};
size_t n;
- stop_curses();
+ pause_curses();
fflush(stdout);
for (n = 0; n < SIZEOF(msg); n++)
{
va_list ap;
- stop_curses();
+ pause_curses();
fflush(stdout);
va_start(ap, fmt);
continue;
}
}
- s += strlen(s);
if (tries & 2) {
int len = (int) strlen(filename);
int ch;
int *ip;
char *cp;
+ float *fp;
long lv;
va_start(ap, 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 {
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 *);
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)
{
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;
}
{
int n;
int state = 0;
- char buf[BUFSIZ];
+ char buf[2048];
int num;
char ch;
char *s;
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);
}
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;
}
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 */
++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;
}
(void) opt_d;
if (isatty(fileno(stdout))) {
in_curses = TRUE;
+ setlocale(LC_ALL, "");
initscr();
cbreak();
noecho();
init_palette(palette_path);
}
scrollok(stdscr, FALSE);
- exit_curses();
+ stop_curses();
}
}
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;