width = pos = 0;
while (string[pos])
{
- if (CTRL_CHAR (string[pos]) || string[pos] == RUBOUT)
+ if (c_iscntrl (string[pos]))
{
width += 2;
pos++;
s = to_print + prefix_bytes;
while (*s)
{
- if (CTRL_CHAR (*s))
+ if (c_iscntrl (*s))
{
displayer->putch (displayer, '^');
- displayer->putch (displayer, UNCTRL (*s));
- printed_len += 2;
- s++;
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
- }
- else if (*s == RUBOUT)
- {
- displayer->putch (displayer, '^');
- displayer->putch (displayer, '?');
+ displayer->putch (displayer, c_unctrl (*s));
printed_len += 2;
s++;
#if defined (HANDLE_MULTIBYTE)
break;
c = (unsigned char) rl_line_buffer[in];
- if (CTRL_CHAR (c) || c == RUBOUT)
+ if (c_iscntrl (c))
{
waddch (w, '^');
- waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
+ waddch (w, c_unctrl (c));
}
else if (c == '\t')
{
rl_bind_key_in_map ('a', tui_rl_switch_mode, tui_ctlx_keymap);
rl_bind_key_in_map ('A', tui_rl_switch_mode, emacs_ctlx_keymap);
rl_bind_key_in_map ('A', tui_rl_switch_mode, tui_ctlx_keymap);
- rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, emacs_ctlx_keymap);
- rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, tui_ctlx_keymap);
+ rl_bind_key_in_map (c_ctrl ('A'), tui_rl_switch_mode, emacs_ctlx_keymap);
+ rl_bind_key_in_map (c_ctrl ('A'), tui_rl_switch_mode, tui_ctlx_keymap);
rl_bind_key_in_map ('1', tui_rl_delete_other_windows, emacs_ctlx_keymap);
rl_bind_key_in_map ('1', tui_rl_delete_other_windows, tui_ctlx_keymap);
rl_bind_key_in_map ('2', tui_rl_change_windows, emacs_ctlx_keymap);
return filename;
}
+/* See utils.h. */
+
+unsigned char
+c_unctrl (unsigned char c)
+{
+ if (!c_iscntrl (c))
+ return c;
+
+ unsigned char res = c;
+ if (res >= 0x40)
+ {
+ /* Map 0x7f (^?) to 0x3f (?). */
+ res -= 0x40;
+ }
+ else
+ {
+ /* Map 0x03 (^C) to 0x43 (C). */
+ res += 0x40;
+ }
+
+ return res;
+}
+
+/* See utils.h. */
+
+unsigned char
+c_ctrl (unsigned char c)
+{
+ unsigned char res = c;
+ if (res < 0x40)
+ {
+ /* Map 0x3f (?) to 0x7f (^?). */
+ res += 0x40;
+ }
+ else
+ {
+ res = c_toupper (res);
+
+ /* Map 0x43 (C) to 0x03 (^C). */
+ res -= 0x40;
+ }
+
+ return c_iscntrl (res) ? res : c;
+}
+
+#if GDB_SELF_TEST
+static void
+test_c_ctrl_unctrl ()
+{
+ /* Basic check. */
+ SELF_CHECK (c_ctrl ('C') == 0x03);
+ SELF_CHECK (c_ctrl ('c') == 0x03);
+ SELF_CHECK (c_unctrl (0x03) == 'C');
+
+ /* Function c_iscntrl considers ^? to be a control character, but for some
+ reason, readline's CTRL_CHAR doesn't, so CTRL/UNCTRL don't handle it.
+ Check that c_ctrl/c_unctrl do handle it. */
+ SELF_CHECK (c_ctrl ('?') == 0x7f);
+ SELF_CHECK (c_unctrl (0x7f) == '?');
+
+ /* Consistency check. */
+ for (unsigned int i = 0; i < 0x100; i++)
+ {
+ unsigned char ch = i;
+ unsigned char unctrl_ch = c_unctrl (ch);
+ if (!c_iscntrl (ch))
+ {
+ SELF_CHECK (unctrl_ch == ch);
+ continue;
+ }
+
+ SELF_CHECK (!c_iscntrl (unctrl_ch));
+ SELF_CHECK (!c_islower (unctrl_ch));
+ SELF_CHECK (c_ctrl (unctrl_ch) == ch);
+ SELF_CHECK (c_ctrl (c_tolower (unctrl_ch)) == ch);
+ }
+}
+#endif
+
#if GDB_SELF_TEST
static void
test_assign_set_return_if_changed ()
selftests::register_test ("pager", test_pager);
selftests::register_test ("assign_set_return_if_changed",
test_assign_set_return_if_changed);
+ selftests::register_test ("c_ctrl_unctrl", test_c_ctrl_unctrl);
#endif
}
std::vector<string_file> m_warnings;
};
+/* Re-implementation of readline's CTRL/UNCTRL (compatible with readline's
+ CTRL_CHAR), designed to be compatible with gnulib's c_iscntrl.
+ While gnulib's c-ctype.h still uses int for character parameters and
+ results, we use unsigned char here for maximum clarity. */
+
+extern unsigned char c_ctrl (unsigned char c);
+extern unsigned char c_unctrl (unsigned char c);
+
#endif /* GDB_UTILS_H */