Author: Eric S. Raymond <esr@snark.thyrsus.com> 1993
Thomas E. Dickey (beginning revision 1.27 in 1996).
-$Id: ncurses.c,v 1.437 2016/05/07 23:56:59 tom Exp $
+$Id: ncurses.c,v 1.446 2016/09/17 21:12:04 tom Exp $
***************************************************************************/
static RGB_DATA *all_colors;
static void main_menu(bool);
+static void failed(const char *s) GCC_NORETURN;
static void
failed(const char *s)
}
static bool
-isQuit(int c)
+isQuit(int c, bool escape)
{
- return ((c) == QUIT || (c) == ESCAPE);
+ return ((c) == QUIT || (escape && ((c) == ESCAPE)));
}
#define case_QUIT QUIT: case ESCAPE
{
static char buf[80 + (5 * 10) + (32 * 15)];
- (void) sprintf(buf, "id %2d at (%2d, %2d, %d) state %4lx = {",
- ep->id, ep->x, ep->y, ep->z, (unsigned long) ep->bstate);
+ (void) _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+ "id %2d at (%2d, %2d, %d) state %4lx = {",
+ ep->id, ep->x, ep->y, ep->z, (unsigned long) ep->bstate);
-#define SHOW(m, s) if ((ep->bstate & m)==m) {strcat(buf,s); strcat(buf, ", ");}
+#define SHOW(m, s) \
+ if ((ep->bstate & m)==m) { \
+ _nc_STRCAT(buf, s, sizeof(buf)); \
+ _nc_STRCAT(buf, ", ", sizeof(buf)); \
+ }
SHOW(BUTTON1_RELEASED, "release-1");
SHOW(BUTTON1_PRESSED, "press-1");
if (buf[strlen(buf) - 1] == ' ')
buf[strlen(buf) - 2] = '\0';
- (void) strcat(buf, "}");
+ _nc_STRCAT(buf, "}", sizeof(buf));
return (buf);
}
return ((delay < 0) && flags['t']);
}
+#define ExitOnEscape() (flags[UChar('k')] && flags[UChar('t')])
+
static void
wgetch_help(WINDOW *win, GetchFlags flags)
{
printw("Type any key to see its %s value. Also:\n",
flags['k'] ? "keypad" : "literal");
for (n = 0; n < SIZEOF(help); ++n) {
+ const char *msg = help[n];
int row = 1 + (int) (n % chk);
int col = (n >= chk) ? COLS / 2 : 0;
- int flg = ((strstr(help[n], "toggle") != 0)
- && (flags[UChar(*help[n])] != FALSE));
+ int flg = ((strstr(msg, "toggle") != 0)
+ && (flags[UChar(*msg)] != FALSE));
+ if (*msg == '^' && ExitOnEscape())
+ msg = "^[,^q -- quit";
if (flg)
(void) standout();
- MvPrintw(row, col, "%s", help[n]);
+ MvPrintw(row, col, "%s", msg);
if (col == 0)
clrtoeol();
if (flg)
if (c == ERR && blocking_getch(flags, delay)) {
wprintw(win, "ERR");
wgetch_wrap(win, first_y);
- } else if (isQuit(c)) {
+ } else if (isQuit(c, ExitOnEscape())) {
break;
} else if (c == 'e') {
flags[UChar('e')] = !flags[UChar('e')];
if (code == ERR && blocking_getch(flags, delay)) {
wprintw(win, "ERR");
wgetch_wrap(win, first_y);
- } else if (isQuit((int) c)) {
+ } else if (isQuit((int) c, ExitOnEscape())) {
break;
} else if (c == 'e') {
flags[UChar('e')] = !flags[UChar('e')];
int width = 8;
if (wide) {
- sprintf(temp, "%02d", color);
+ _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+ "%02d", color);
width = 4;
} else if (color >= 8) {
- sprintf(temp, "[%02d]", color);
+ _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+ "[%02d]", color);
} else if (color < 0) {
- strcpy(temp, "default");
+ _nc_STRCPY(temp, "default", sizeof(temp));
} else {
- sprintf(temp, "%.*s", 16, the_color_names[color]);
+ _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+ "%.*s", 16, the_color_names[color]);
}
printw("%-*.*s", width, width, temp);
}
attron(A_REVERSE);
if (opt_nums) {
- sprintf(numbered, "{%02X}", (int) i);
+ _nc_SPRINTF(numbered, _nc_SLIMIT((size_t) (COLS + 1))
+ "{%02X}", (int) i);
hello = numbered;
}
printw("%-*.*s", width, width, hello);
attr_on(A_REVERSE, NULL);
if (opt_nums) {
- sprintf(numbered, "{%02X}", i);
+ _nc_SPRINTF(numbered,
+ _nc_SLIMIT((size_t) (COLS + 1) * sizeof(wchar_t))
+ "{%02X}", i);
if (opt_xchr) {
make_fullwidth_text(buffer, numbered);
} else {
int n;
int got;
char result[BUFSIZ];
- int check_n, check_r, check_g, check_b;
+ int check_n;
+ unsigned check_r, check_g, check_b;
raw();
noecho();
&& (i < max_colors); i++) {
char numeric[80];
- sprintf(numeric, "[%d]", i);
+ _nc_SPRINTF(numeric, _nc_SLIMIT(sizeof(numeric)) "[%d]", i);
MvPrintw(2 + i - top_color, 0, "%c %-8s:",
(i == current ? '>' : ' '),
(i < (int) SIZEOF(the_color_names)
MvPrintw(LINES - 1, 0, "Number: %d", value);
clrtoeol();
} while
- (!isQuit(this_c));
+ (!isQuit(this_c, TRUE));
erase();
case '7':
case '8':
MvAddStr(SLK_WORK, 0, "Please enter the label value: ");
- strcpy(buf, "");
+ _nc_STRCPY(buf, "", sizeof(buf));
if ((s = slk_label(c - '0')) != 0) {
- strncpy(buf, s, (size_t) 8);
+ _nc_STRNCPY(buf, s, (size_t) 8);
}
wGetstring(stdscr, buf, 8);
slk_set((c - '0'), buf, fmt);
beep();
break;
}
- } while (!isQuit(c = Getchar()));
+ } while (!isQuit(c = Getchar(), TRUE));
done:
slk_clear();
beep();
break;
}
- } while (!isQuit(c = Getchar()));
+ } while (!isQuit(c = Getchar(), TRUE));
done:
slk_clear();
int row = 2 + ((int) (code - first) % (pagesize / 2));
int col = ((int) (code - first) / (pagesize / 2)) * COLS / 2;
char tmp[80];
- sprintf(tmp, "%3u (0x%x)", code, code);
+ _nc_SPRINTF(tmp, _nc_SLIMIT(sizeof(tmp)) "%3u (0x%x)", code, code);
MvPrintw(row, col, "%*s: ", COLS / 4, tmp);
do {
my_list[at_code].name);
}
refresh();
- } while (!isQuit(c = Getchar()));
+ } while (!isQuit(c = Getchar(), TRUE));
Pause();
erase();
int count = repeat;
int y, x;
- sprintf(tmp, "%3ld (0x%lx)", (long) code, (long) code);
+ _nc_SPRINTF(tmp, _nc_SLIMIT(sizeof(tmp))
+ "%3ld (0x%lx)", (long) code, (long) code);
MvPrintw(row, col, "%*s: ", COLS / 4, tmp);
memset(&codes, 0, sizeof(codes));
MvPrintw(row, col, "%*s : ", COLS / 4, name);
(void) attr_set(attr, pair, 0);
- addstr(strncpy(temp, code, 20));
+ _nc_STRNCPY(temp, code, 20);
+ addstr(temp);
(void) attr_set(A_NORMAL, 0, 0);
return n + 1;
}
my_list[at_code].name);
}
refresh();
- } while (!isQuit(c = Getchar()));
+ } while (!isQuit(c = Getchar(), TRUE));
Pause();
erase();
for (n = 0; n < SIZEOF(legend); n++) {
switch (legend[n].code) {
default:
- strcpy(buf, legend[n].msg);
+ _nc_STRCPY(buf, legend[n].msg, sizeof(buf));
break;
case 1:
- sprintf(buf, legend[n].msg, do_keypad ? "yes" : "no");
+ _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+ legend[n].msg, do_keypad ? "yes" : "no");
break;
case 2:
- sprintf(buf, legend[n].msg, do_scroll ? "yes" : "no");
+ _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+ legend[n].msg, do_scroll ? "yes" : "no");
break;
case 3:
- sprintf(buf, legend[n].msg, do_keypad ? "/ESC" : "");
+ _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+ legend[n].msg, do_keypad ? "/ESC" : "");
break;
}
x = getcurx(stdscr);
usescr = frame_win(current);
wrefresh(usescr);
} while
- (!isQuit(c = wGetchar(usescr))
+ (!isQuit(c = wGetchar(usescr), TRUE)
&& (c != ERR));
breakout:
tracetrace(unsigned tlevel)
{
static char *buf;
+ static size_t need = 12;
int n;
if (buf == 0) {
- size_t need = 12;
for (n = 0; t_tbl[n].name != 0; n++)
need += strlen(t_tbl[n].name) + 2;
buf = typeMalloc(char, need);
if (!buf)
failed("tracetrace");
}
- sprintf(buf, "0x%02x = {", tlevel);
+ _nc_SPRINTF(buf, _nc_SLIMIT(need) "0x%02x = {", tlevel);
if (tlevel == 0) {
- sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name);
+ _nc_STRCAT(buf, t_tbl[0].name, need);
+ _nc_STRCAT(buf, ", ", need);
} else {
for (n = 1; t_tbl[n].name != 0; n++)
if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask) {
- strcat(buf, t_tbl[n].name);
- strcat(buf, ", ");
+ _nc_STRCAT(buf, t_tbl[n].name, need);
+ _nc_STRCAT(buf, ", ", need);
}
}
if (buf[strlen(buf) - 2] == ',')
buf[strlen(buf) - 2] = '\0';
- return (strcat(buf, "}"));
+ _nc_STRCAT(buf, "}", need);
+ return buf;
}
/* fake a dynamically reconfigurable menu using the 0th entry to deselect
size_t len;
if (temp != 0) {
- strncpy(temp, source ? source : "", have + 1);
+ _nc_STRNCPY(temp, source ? source : "", have + 1);
len = (size_t) (char *) field_userptr(me);
if (c <= KEY_MAX) {
if (isgraph(c) && (len + 1) < sizeof(temp)) {
switch (row) {
case 0:
flavors[row] = 0;
- sprintf(msg, "refresh %s, then %s, then doupdate.", ths, tht);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "refresh %s, then %s, then doupdate.", ths, tht);
break;
case 1:
if (use_colors) {
flavors[row] %= 2;
}
overlap_test_1_attr(stdscr, flavors[row], col);
- sprintf(msg, "fill window %s with letter %s.", ths, ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "fill window %s with letter %s.", ths, ths);
break;
case 2:
if (use_colors) {
}
switch (flavors[row]) {
case 0:
- sprintf(msg, "cross pattern in window %s.", ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "cross pattern in window %s.", ths);
break;
case 1:
- sprintf(msg, "draw box in window %s.", ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "draw box in window %s.", ths);
break;
case 2:
- sprintf(msg, "set background of window %s.", ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "set background of window %s.", ths);
break;
case 3:
- sprintf(msg, "reset background of window %s.", ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "reset background of window %s.", ths);
break;
}
break;
case 3:
flavors[row] = 0;
- sprintf(msg, "clear window %s.", ths);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "clear window %s.", ths);
break;
case 4:
flavors[row] %= 4;
switch (flavors[row]) {
case 0:
- sprintf(msg, "overwrite %s onto %s.", ths, tht);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "overwrite %s onto %s.", ths, tht);
break;
case 1:
- sprintf(msg, "copywin(FALSE) %s onto %s.", ths, tht);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "copywin(FALSE) %s onto %s.", ths, tht);
break;
case 2:
- sprintf(msg, "copywin(TRUE) %s onto %s.", ths, tht);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "copywin(TRUE) %s onto %s.", ths, tht);
break;
case 3:
- sprintf(msg, "overlay %s onto %s.", ths, tht);
+ _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+ "overlay %s onto %s.", ths, tht);
break;
}
break;
memset(flavor, 0, sizeof(flavor));
state = overlap_help(0, flavor);
- while (!isQuit(ch = Getchar()))
+ while (!isQuit(ch = Getchar(), TRUE))
switch (ch) {
case 'a': /* refresh window A first, then B */
overlap_test_0(win1, win2);
endwin();
}
+static void
+show_setting_name(const char *name)
+{
+ printw("%-25s ", name);
+}
+
+static void
+show_string_setting(const char *name, const char *value)
+{
+ show_setting_name(name);
+ if (value) {
+ printw("\"%s\"", value);
+ } else {
+ attron(A_REVERSE);
+ addstr("<NULL>");
+ attroff(A_REVERSE);
+ }
+ addch('\n');
+}
+
+static void
+show_number_setting(const char *name, int value)
+{
+ show_setting_name(name);
+ if (value >= 0) {
+ printw("%d", value);
+ } else {
+ attron(A_REVERSE);
+ printw("%d", value);
+ attroff(A_REVERSE);
+ }
+ addch('\n');
+}
+
+static void
+show_boolean_setting(const char *name, int value)
+{
+ show_setting_name(name);
+ if (value >= 0) {
+ printw("%s", value ? "TRUE" : "FALSE");
+ } else {
+ attron(A_REVERSE);
+ printw("%d", value);
+ attroff(A_REVERSE);
+ }
+ addch('\n');
+}
+
+static void
+show_settings(void)
+{
+#if USE_WIDEC_SUPPORT
+ wchar_t ch;
+#endif
+
+ move(0, 0);
+ show_string_setting("termname", termname());
+ show_string_setting("longname", longname());
+ show_number_setting("baudrate", baudrate());
+ if (erasechar() > 0) {
+ show_string_setting("unctrl(erasechar)", unctrl((chtype) erasechar()));
+ show_string_setting("keyname(erasechar)", keyname(erasechar()));
+ }
+ if (killchar() > 0) {
+ show_string_setting("unctrl(killchar)", unctrl((chtype) killchar()));
+ show_string_setting("keyname(killchar)", keyname(killchar()));
+ }
+#if USE_WIDEC_SUPPORT
+ if (erasewchar(&ch) == OK) {
+ show_string_setting("key_name(erasewchar)", key_name(ch));
+ }
+ if (killwchar(&ch) == OK) {
+ show_string_setting("key_name(killwchar)", key_name(ch));
+ }
+#endif
+ show_boolean_setting("has_ic", has_ic());
+ show_boolean_setting("has_il", has_il());
+ Pause();
+ erase();
+ endwin();
+}
+
/****************************************************************************
*
* Main sequence
break;
#endif
+ case 'v':
+ show_settings();
+ break;
+
case '?':
break;
#if USE_LIBMENU && defined(TRACE)
(void) puts("t = set trace level");
#endif
+ (void) puts("v = show terminal name and settings");
(void) puts("? = repeat this command summary");
(void) fputs("> ", stdout);