+ n = skip; /* make it easy */
+ k = my_size - 1;
+ init_attr_string();
+
+ do {
+ int row = 2;
+ chtype normal = A_NORMAL | BLANK;
+ chtype extras = (chtype) ac;
+
+ if (use_colors) {
+ NCURSES_PAIRS_T pair = 0;
+ if ((fg != COLOR_BLACK) || (bg != COLOR_BLACK)) {
+ pair = 1;
+ if (init_pair(pair, fg, bg) == ERR) {
+ beep();
+ } else {
+ normal |= (chtype) COLOR_PAIR(pair);
+ }
+ }
+ if (tx >= 0) {
+ pair = 2;
+ if (init_pair(pair, tx, bg) == ERR) {
+ beep();
+ } else {
+ extras |= (chtype) COLOR_PAIR(pair);
+ normal &= ~A_COLOR;
+ }
+ }
+ }
+ bkgd(normal);
+ bkgdset(normal);
+ erase();
+
+ box(stdscr, 0, 0);
+ MvAddStr(0, 20, "Character attribute test display");
+
+ for (j = 0; j < my_size; ++j) {
+ bool arrow = (j == k);
+ row = show_attr(my_wins[j], row, n, arrow,
+ normal |
+ extras |
+ my_list[j].attr |
+ my_list[k].attr,
+ my_list[j].name);
+ }
+
+ MvPrintw(row, 8,
+ "This terminal does %shave the magic-cookie glitch",
+ get_xmc() > -1 ? "" : "not ");
+ MvPrintw(row + 1, 8, "Enter '?' for help.");
+ show_color_attr(fg, bg, tx);
+ printw(" ACS (%d)", ac != 0);
+
+ refresh();
+ } while (attr_getc(&n, &fg, &bg, &tx, &ac, &k, my_size));
+
+ bkgdset(A_NORMAL | BLANK);
+ erase();
+ endwin();
+ } else {
+ Cannot("does not support video attributes.");
+ }
+}
+
+#if USE_WIDEC_SUPPORT
+static bool use_fullwidth;
+static wchar_t wide_attr_test_string[MAX_ATTRSTRING + 1];
+
+#define FULL_LO 0xff00
+#define FULL_HI 0xff5e
+#define HALF_LO 0x20
+
+#define isFullWidth(ch) ((int)(ch) >= FULL_LO && (int)(ch) <= FULL_HI)
+#define ToNormalWidth(ch) (wchar_t) (((int)(ch) - FULL_LO) + HALF_LO)
+#define ToFullWidth(ch) (wchar_t) (((int)(ch) - HALF_LO) + FULL_LO)
+
+/*
+ * Returns an ASCII code in [32..126]
+ */
+static wchar_t
+normal_wchar(int ch)
+{
+ wchar_t result = (wchar_t) ch;
+ if (isFullWidth(ch))
+ result = ToNormalWidth(ch);
+ return result;
+}
+
+/*
+ * Returns either an ASCII code in in [32..126] or full-width in
+ * [0xff00..0xff5e], according to use_fullwidth setting.
+ */
+static wchar_t
+target_wchar(int ch)
+{
+ wchar_t result = (wchar_t) ch;
+ if (use_fullwidth) {
+ if (!isFullWidth(ch))
+ result = ToFullWidth(ch);
+ } else {
+ if (isFullWidth(ch))
+ result = ToNormalWidth(ch);
+ }
+ return result;
+}
+
+static void
+wide_adjust_attr_string(int adjust)
+{
+ wchar_t save = wide_attr_test_string[0];
+ int first = ((int) normal_wchar(save)) + adjust;
+ int j, k;
+
+ if (first >= ATTRSTRING_1ST) {
+ for (j = 0, k = first; j < MAX_ATTRSTRING; ++j, ++k) {
+ if (k > ATTRSTRING_END)
+ break;
+ wide_attr_test_string[j] = target_wchar(k);
+ if (((k + 1 - first) % 5) == 0) {
+ if (++j >= MAX_ATTRSTRING)
+ break;
+ wide_attr_test_string[j] = ' ';
+ }
+ }
+ if ((LEN_ATTRSTRING - j) > 5) {
+ wide_attr_test_string[0] = save;
+ wide_adjust_attr_string(adjust - 1);
+ } else {
+ while (j < MAX_ATTRSTRING)
+ wide_attr_test_string[j++] = ' ';
+ wide_attr_test_string[j] = '\0';
+ }
+ }
+}
+
+static void
+wide_init_attr_string(void)
+{
+ use_fullwidth = FALSE;
+ wide_attr_test_string[0] = (wchar_t) default_attr_string();
+ wide_adjust_attr_string(0);
+}
+
+static void
+set_wide_background(NCURSES_PAIRS_T pair)
+{
+ cchar_t normal;
+ wchar_t blank[2];
+
+ blank[0] = ' ';
+ blank[1] = 0;
+ setcchar(&normal, blank, A_NORMAL, pair, 0);
+ bkgrnd(&normal);
+ bkgrndset(&normal);
+}
+
+static attr_t
+get_wide_background(void)
+{
+ attr_t result = A_NORMAL;
+ attr_t attr;
+ cchar_t ch;
+ NCURSES_PAIRS_T pair;
+ wchar_t wch[10];
+
+ memset(&ch, 0, sizeof(ch));
+ if (getbkgrnd(&ch) != ERR) {
+ if (getcchar(&ch, wch, &attr, &pair, 0) != ERR) {
+ result = attr;
+ }
+ }
+ return result;
+}
+
+static int
+wide_show_attr(WINDOW *win,
+ int row,
+ int skip,
+ bool arrow,
+ chtype attr,
+ NCURSES_PAIRS_T pair,
+ const char *name)
+{
+ int ncv = get_ncv();
+ chtype test = attr & ~WA_ALTCHARSET;
+
+ if (arrow)
+ MvPrintw(row, 5, "-->");
+ MvPrintw(row, 8, "%s mode:", name);
+ MvPrintw(row, COL_ATTRSTRING - 1, "|");
+ if (skip)
+ printw("%*s", skip, " ");
+
+ /*
+ * Just for testing, write text using the alternate character set one
+ * character at a time (to pass its rendition directly), and use the
+ * string operation for the other attributes.
+ */
+ wmove(win, 0, 0);
+ werase(win);
+ if (attr & WA_ALTCHARSET) {
+ const wchar_t *s;
+ cchar_t ch;
+
+ for (s = wide_attr_test_string; *s != L'\0'; ++s) {
+ wchar_t fill[2];
+ fill[0] = *s;
+ fill[1] = L'\0';
+ setcchar(&ch, fill, attr, pair, 0);
+ (void) wadd_wch(win, &ch);
+ }
+ } else {
+ attr_t old_attr = 0;
+ NCURSES_PAIRS_T old_pair = 0;
+
+ (void) (wattr_get) (win, &old_attr, &old_pair, 0);
+ (void) wattr_set(win, attr, pair, 0);
+ (void) waddwstr(win, wide_attr_test_string);
+ (void) wattr_set(win, old_attr, old_pair, 0);
+ }
+ if (skip)
+ printw("%*s", skip, " ");
+ MvPrintw(row, COL_ATTRSTRING + LEN_ATTRSTRING, "|");
+ if (test != A_NORMAL) {
+ if (!(term_attrs() & test)) {
+ printw(" (N/A)");
+ } else {
+ if (ncv > 0 && (get_wide_background() & A_COLOR)) {
+ static const attr_t table[] =
+ {
+ WA_STANDOUT,
+ WA_UNDERLINE,
+ WA_REVERSE,
+ WA_BLINK,
+ WA_DIM,
+ WA_BOLD,
+ WA_INVIS,
+ WA_PROTECT,
+ WA_ALTCHARSET
+ };
+ unsigned n;
+ bool found = FALSE;
+ for (n = 0; n < SIZEOF(table); n++) {
+ if ((table[n] & attr) != 0
+ && ((1 << n) & ncv) != 0) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ printw(" (NCV)");
+ }
+ if ((term_attrs() & test) != test)
+ printw(" (Part)");
+ }
+ }
+ return row + 2;
+}
+
+static bool
+wide_attr_getc(int *skip,
+ NCURSES_COLOR_T *fg, NCURSES_COLOR_T *bg,
+ NCURSES_COLOR_T *tx, int *ac,
+ unsigned *kc, unsigned limit)
+{
+ bool result = TRUE;
+ bool error = FALSE;
+ WINDOW *helpwin;