* [PATCH 0/6] Handle UTF-8 in TUI source windows @ 2020-06-27 21:20 Tom Tromey 2020-06-27 21:20 ` [PATCH 1/6] Remove test duplicate from gdb.tui Tom Tromey ` (6 more replies) 0 siblings, 7 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches This series implements support for displaying UTF-8 sources in TUI windows. This implementation properly handles horizontal scrolling, which was an issue in earlier attempts. No new test case -- I tried to write one, but I could not get it to work. It's unclear if this is due to a bug in my test, a bug in tuiterm.exp, or a bug in curses; and I got irritated trying to find out. Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/6] Remove test duplicate from gdb.tui 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-06-27 21:20 ` [PATCH 2/6] Use an inner window in tui_py_window Tom Tromey ` (5 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey I noticed a duplicated test in gdb.tui. This patch removes it by wrapping a test in with_test_prefix. gdb/testsuite/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> * gdb.tui/new-layout.exp: Use with_test_prefix. --- gdb/testsuite/ChangeLog | 4 ++++ gdb/testsuite/gdb.tui/new-layout.exp | 10 ++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/gdb/testsuite/gdb.tui/new-layout.exp b/gdb/testsuite/gdb.tui/new-layout.exp index b4fca674e89..93e11619485 100644 --- a/gdb/testsuite/gdb.tui/new-layout.exp +++ b/gdb/testsuite/gdb.tui/new-layout.exp @@ -24,10 +24,12 @@ if {[build_executable "failed to prepare" ${testfile} ${srcfile}] == -1} { } # Make sure TUI is supported before continuing. -Term::clean_restart 24 80 $testfile -if {![Term::enter_tui]} { - unsupported "TUI not supported" - return +with_test_prefix "initial check" { + Term::clean_restart 24 80 $testfile + if {![Term::enter_tui]} { + unsupported "TUI not supported" + return + } } Term::clean_restart 24 80 $testfile -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/6] Use an inner window in tui_py_window 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 2020-06-27 21:20 ` [PATCH 1/6] Remove test duplicate from gdb.tui Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-06-27 21:20 ` [PATCH 3/6] Remove a call to show_source_line from TUI Tom Tromey ` (4 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This changes tui_py_window to create an inner curses window. This greatly simplifies tui_py_window::output, beacuse it no longer needs to be careful to avoid overwriting the window's border. This patch also makes it a bit easier for a later patch to rewrite tui_copy_source_line. gdb/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> * python/py-tui.c (class tui_py_window) <refresh_window>: New method. <erase>: Update. <cursor_x, cursor_y>: Remove. <m_inner_window>: New member. (tui_py_window::rerender): Create inner window. (tui_py_window::output): Write to inner window. --- gdb/ChangeLog | 10 ++++++++ gdb/python/py-tui.c | 59 ++++++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/gdb/python/py-tui.c b/gdb/python/py-tui.c index 95c71f1d2dd..3f44cfc3d12 100644 --- a/gdb/python/py-tui.c +++ b/gdb/python/py-tui.c @@ -86,15 +86,23 @@ class tui_py_window : public tui_win_info void do_scroll_vertical (int num_to_scroll) override; void do_scroll_horizontal (int num_to_scroll) override; + void refresh_window () override + { + tui_win_info::refresh_window (); + if (m_inner_window != nullptr) + { + touchwin (m_inner_window.get ()); + tui_wrefresh (m_inner_window.get ()); + } + } + /* Erase and re-box the window. */ void erase () { - if (is_visible ()) + if (is_visible () && m_inner_window != nullptr) { - werase (handle.get ()); + werase (m_inner_window.get ()); check_and_display_highlight_if_needed (); - cursor_x = 0; - cursor_y = 0; } } @@ -115,13 +123,13 @@ class tui_py_window : public tui_win_info private: - /* Location of the cursor. */ - int cursor_x = 0; - int cursor_y = 0; - /* The name of this window. */ std::string m_name; + /* We make our own inner window, so that it is easy to print without + overwriting the border. */ + std::unique_ptr<WINDOW, curses_deleter> m_inner_window; + /* The underlying Python window object. */ gdbpy_ref<> m_window; @@ -155,8 +163,21 @@ tui_py_window::~tui_py_window () void tui_py_window::rerender () { + tui_win_info::rerender (); + gdbpy_enter enter_py (get_current_arch (), current_language); + int h = viewport_height (); + int w = viewport_width (); + if (h == 0 || w == 0) + { + /* The window would be too small, so just remove the + contents. */ + m_inner_window.reset (nullptr); + return; + } + m_inner_window.reset (newwin (h, w, y + 1, x + 1)); + if (PyObject_HasAttrString (m_window.get (), "render")) { gdbpy_ref<> result (PyObject_CallMethod (m_window.get (), "render", @@ -197,27 +218,11 @@ tui_py_window::do_scroll_vertical (int num_to_scroll) void tui_py_window::output (const char *text) { - int vwidth = viewport_width (); - - while (cursor_y < viewport_height () && *text != '\0') + if (m_inner_window != nullptr) { - wmove (handle.get (), cursor_y + 1, cursor_x + 1); - - std::string line = tui_copy_source_line (&text, 0, 0, - vwidth - cursor_x, 0); - tui_puts (line.c_str (), handle.get ()); - - if (*text == '\n') - { - ++text; - ++cursor_y; - cursor_x = 0; - } - else - cursor_x = getcurx (handle.get ()) - 1; + tui_puts (text, m_inner_window.get ()); + tui_wrefresh (m_inner_window.get ()); } - - wrefresh (handle.get ()); } \f -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/6] Remove a call to show_source_line from TUI 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 2020-06-27 21:20 ` [PATCH 1/6] Remove test duplicate from gdb.tui Tom Tromey 2020-06-27 21:20 ` [PATCH 2/6] Use an inner window in tui_py_window Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-06-27 21:20 ` [PATCH 4/6] Use a curses pad for source and disassembly windows Tom Tromey ` (3 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This removes a call to show_source_line from tui_source_window_base. This call isn't needed because this function already calls the 'refill' method if the state changed. gdb/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> * tui/tui-winsource.c (tui_source_window_base::set_is_exec_point_at): Don't call show_source_line. --- gdb/ChangeLog | 6 ++++++ gdb/tui/tui-winsource.c | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c index db0add99688..6723bad82cc 100644 --- a/gdb/tui/tui-winsource.c +++ b/gdb/tui/tui-winsource.c @@ -411,7 +411,6 @@ tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l) { changed = true; m_content[i].is_exec_point = new_state; - show_source_line (i + 1); } i++; } -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/6] Use a curses pad for source and disassembly windows 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey ` (2 preceding siblings ...) 2020-06-27 21:20 ` [PATCH 3/6] Remove a call to show_source_line from TUI Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-06-27 21:20 ` [PATCH 5/6] Use ISCNTRL in tui_copy_source_line Tom Tromey ` (2 subsequent siblings) 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This changes the TUI source and disassembly windows to use a curses pad for their text. This is an important step toward properly handling non-ASCII characters, because it makes it easy to scroll horizontally without needing gdb to also understand multi-byte character boundaries -- this can be wholly delegated to curses. Horizontal scrolling is probably also faster now, because no re-rendering is required. gdb/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> * unittests/tui-selftests.c: Update. * tui/tui-winsource.h (struct tui_source_window_base) <extra_margin, show_line_number, refresh_pad>: New methods. <m_max_length, m_pad>: New members. (tui_copy_source_line): Update. * tui/tui-winsource.c (tui_copy_source_line): Remove line_no, first_col, line_width, ndigits parameters. Add length. (tui_source_window_base::show_source_line): Write to pad. Line number now 0-based. (tui_source_window_base::refresh_pad): New method. (tui_source_window_base::show_source_content): Write to pad. Call refresh_pad. (tui_source_window_base::do_scroll_horizontal): Call refresh_pad, not refill. (tui_source_window_base::update_exec_info): Call show_line_number. * tui/tui-source.h (struct tui_source_window) <extra_margin>: New method. <m_digits>: New member. * tui/tui-source.c (tui_source_window::set_contents): Set m_digits and m_max_length. (tui_source_window::show_line_number): New method. * tui/tui-io.h (tui_puts): Fix comment. * tui/tui-disasm.c (tui_disasm_window::set_contents): Set m_max_length. --- gdb/ChangeLog | 28 ++++++++++++ gdb/tui/tui-disasm.c | 9 ++-- gdb/tui/tui-io.h | 3 +- gdb/tui/tui-source.c | 29 ++++++++---- gdb/tui/tui-source.h | 11 +++++ gdb/tui/tui-winsource.c | 84 +++++++++++++++++------------------ gdb/tui/tui-winsource.h | 41 ++++++++++++----- gdb/unittests/tui-selftests.c | 6 +-- 8 files changed, 140 insertions(+), 71 deletions(-) diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c index d684b02fd12..0b7980ee80b 100644 --- a/gdb/tui/tui-disasm.c +++ b/gdb/tui/tui-disasm.c @@ -318,8 +318,7 @@ tui_disasm_window::set_contents (struct gdbarch *arch, const struct symtab_and_line &sal) { int i; - int offset = m_horizontal_offset; - int max_lines, line_width; + int max_lines; CORE_ADDR cur_pc; struct tui_locator_window *locator = tui_locator_win_info_ptr (); int tab_len = tui_tab_width; @@ -336,7 +335,6 @@ tui_disasm_window::set_contents (struct gdbarch *arch, /* Window size, excluding highlight box. */ max_lines = height - 2; - line_width = width - TUI_EXECINFO_SIZE - 2; /* Get temporary table that will hold all strings (addr & insn). */ std::vector<tui_asm_line> asm_lines; @@ -348,6 +346,7 @@ tui_disasm_window::set_contents (struct gdbarch *arch, /* Now construct each line. */ m_content.resize (max_lines); + m_max_length = -1; for (i = 0; i < max_lines; i++) { tui_source_element *src = &m_content[i]; @@ -370,7 +369,9 @@ tui_disasm_window::set_contents (struct gdbarch *arch, } const char *ptr = line.c_str (); - src->line = tui_copy_source_line (&ptr, -1, offset, line_width, 0); + int line_len; + src->line = tui_copy_source_line (&ptr, &line_len); + m_max_length = std::max (m_max_length, line_len); src->line_or_addr.loa = LOA_ADDRESS; src->line_or_addr.u.addr = addr; diff --git a/gdb/tui/tui-io.h b/gdb/tui/tui-io.h index f28cf4e12db..120d7be6ee6 100644 --- a/gdb/tui/tui-io.h +++ b/gdb/tui/tui-io.h @@ -27,7 +27,8 @@ struct ui_out; class cli_ui_out; -/* Print the string in the curses command window. */ +/* Print the string in the given curses window. If no window is + provided, the command window is used. */ extern void tui_puts (const char *, WINDOW * = nullptr); /* Print LENGTH characters from the buffer pointed to by BUF to the diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c index fd5bd7dd960..cc6680406d9 100644 --- a/gdb/tui/tui-source.c +++ b/gdb/tui/tui-source.c @@ -50,12 +50,9 @@ tui_source_window::set_contents (struct gdbarch *arch, if (s == NULL) return false; - int line_width, nlines; - - line_width = width - TUI_EXECINFO_SIZE - 1; /* Take hilite (window border) into account, when calculating the number of lines. */ - nlines = height - 2; + int nlines = height - 2; std::string srclines; const std::vector<off_t> *offsets; @@ -78,15 +75,16 @@ tui_source_window::set_contents (struct gdbarch *arch, m_start_line_or_addr.loa = LOA_LINE; cur_line_no = m_start_line_or_addr.u.line_no = line_no; - int digits = 0; + m_digits = 7; if (compact_source) { /* Solaris 11+gcc 5.5 has ambiguous overloads of log10, so we cast to double to get the right one. */ double l = log10 ((double) offsets->size ()); - digits = 1 + (int) l; + m_digits = 1 + (int) l; } + m_max_length = -1; const char *iter = srclines.c_str (); m_content.resize (nlines); while (cur_line < nlines) @@ -95,9 +93,11 @@ tui_source_window::set_contents (struct gdbarch *arch, std::string text; if (*iter != '\0') - text = tui_copy_source_line (&iter, cur_line_no, - m_horizontal_offset, - line_width, digits); + { + int line_len; + text = tui_copy_source_line (&iter, &line_len); + m_max_length = std::max (m_max_length, line_len); + } /* Set whether element is the execution point and whether there is a break point on it. */ @@ -225,3 +225,14 @@ tui_source_window::display_start_addr (struct gdbarch **gdbarch_p, *gdbarch_p = m_gdbarch; find_line_pc (cursal.symtab, m_start_line_or_addr.u.line_no, addr_p); } + +/* See tui-winsource.h. */ + +void +tui_source_window::show_line_number (int offset) const +{ + int lineno = m_content[0].line_or_addr.u.line_no + offset; + char text[20]; + xsnprintf (text, sizeof (text), "%*d ", m_digits - 1, lineno); + waddstr (handle.get (), text); +} diff --git a/gdb/tui/tui-source.h b/gdb/tui/tui-source.h index 1df84cf304c..020f710c237 100644 --- a/gdb/tui/tui-source.h +++ b/gdb/tui/tui-source.h @@ -63,12 +63,23 @@ struct tui_source_window : public tui_source_window_base bool set_contents (struct gdbarch *gdbarch, const struct symtab_and_line &sal) override; + int extra_margin () const override + { + return m_digits; + } + + void show_line_number (int lineno) const override; + private: /* Answer whether a particular line number or address is displayed in the current source window. */ bool line_is_displayed (int line) const; + /* How many digits to use when formatting the line number. This + includes the trailing space. */ + int m_digits; + /* It is the resolved form as returned by symtab_to_fullname. */ gdb::unique_xmalloc_ptr<char> m_fullname; }; diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c index 6723bad82cc..2300b9ab1e9 100644 --- a/gdb/tui/tui-winsource.c +++ b/gdb/tui/tui-winsource.c @@ -65,27 +65,13 @@ tui_display_main () /* See tui-winsource.h. */ std::string -tui_copy_source_line (const char **ptr, int line_no, int first_col, - int line_width, int ndigits) +tui_copy_source_line (const char **ptr, int *length) { const char *lineptr = *ptr; /* Init the line with the line number. */ std::string result; - if (line_no > 0) - { - if (ndigits > 0) - result = string_printf ("%*d ", ndigits, line_no); - else - { - result = string_printf ("%-6d", line_no); - int len = result.size (); - len = len - ((len / tui_tab_width) * tui_tab_width); - result.append (len, ' '); - } - } - int column = 0; char c; do @@ -112,21 +98,11 @@ tui_copy_source_line (const char **ptr, int line_no, int first_col, --column; for (int j = column % max_tab_len; - j < max_tab_len && column < first_col + line_width; + j < max_tab_len; column++, j++) - if (column >= first_col) - result.push_back (' '); + result.push_back (' '); }; - /* We have to process all the text in order to pick up all the - escapes. */ - if (column <= first_col || column > first_col + line_width) - { - if (c == '\t') - process_tab (); - continue; - } - if (c == '\n' || c == '\r' || c == '\0') { /* Nothing. */ @@ -135,11 +111,13 @@ tui_copy_source_line (const char **ptr, int line_no, int first_col, { result.push_back ('^'); result.push_back (c + 0100); + ++column; } else if (c == 0177) { result.push_back ('^'); result.push_back ('?'); + ++column; } else if (c == '\t') process_tab (); @@ -152,6 +130,9 @@ tui_copy_source_line (const char **ptr, int line_no, int first_col, ++lineptr; *ptr = lineptr; + if (length != nullptr) + *length = column; + return result; } @@ -254,24 +235,31 @@ void tui_source_window_base::show_source_line (int lineno) { struct tui_source_element *line; - int x; - line = &m_content[lineno - 1]; + line = &m_content[lineno]; if (line->is_exec_point) - tui_set_reverse_mode (handle.get (), true); + tui_set_reverse_mode (m_pad.get (), true); - wmove (handle.get (), lineno, TUI_EXECINFO_SIZE); - tui_puts (line->line.c_str (), handle.get ()); + wmove (m_pad.get (), lineno, 0); + tui_puts (line->line.c_str (), m_pad.get ()); if (line->is_exec_point) - tui_set_reverse_mode (handle.get (), false); + tui_set_reverse_mode (m_pad.get (), false); +} - /* Clear to end of line but stop before the border. */ - x = getcurx (handle.get ()); - while (x + 1 < width) - { - waddch (handle.get (), ' '); - x = getcurx (handle.get ()); - } +/* See tui-winsource.h. */ + +void +tui_source_window_base::refresh_pad () +{ + int pad_width = std::max (m_max_length, width); + int left_margin = 1 + TUI_EXECINFO_SIZE + extra_margin (); + int view_width = width - left_margin - 1; + int pad_x = std::min (pad_width - view_width, m_horizontal_offset); + /* Ensure that an equal number of scrolls will work if the user + scrolled beyond where we clip. */ + m_horizontal_offset = pad_x; + prefresh (m_pad.get (), 0, pad_x, y + 1, x + left_margin, + y + 1 + m_content.size (), x + left_margin + view_width - 1); } void @@ -279,10 +267,18 @@ tui_source_window_base::show_source_content () { gdb_assert (!m_content.empty ()); - for (int lineno = 1; lineno <= m_content.size (); lineno++) + check_and_display_highlight_if_needed (); + + int pad_width = std::max (m_max_length, width); + if (m_pad == nullptr || pad_width > getmaxx (m_pad.get ())) + m_pad.reset (newpad (m_content.size (), pad_width)); + + werase (m_pad.get ()); + for (int lineno = 0; lineno < m_content.size (); lineno++) show_source_line (lineno); - check_and_display_highlight_if_needed (); + refresh_pad (); + refresh_window (); } @@ -380,7 +376,7 @@ tui_source_window_base::do_scroll_horizontal (int num_to_scroll) if (offset < 0) offset = 0; m_horizontal_offset = offset; - refill (); + refresh_pad (); } } @@ -519,6 +515,8 @@ tui_source_window_base::update_exec_info () element[TUI_EXEC_POS] = '>'; mvwaddstr (handle.get (), i + 1, 1, element); + + show_line_number (i); } refresh_window (); } diff --git a/gdb/tui/tui-winsource.h b/gdb/tui/tui-winsource.h index 501dd31ccfd..b971b2a6d78 100644 --- a/gdb/tui/tui-winsource.h +++ b/gdb/tui/tui-winsource.h @@ -90,6 +90,20 @@ struct tui_source_window_base : public tui_win_info virtual bool set_contents (struct gdbarch *gdbarch, const struct symtab_and_line &sal) = 0; + /* Return the number of extra margin characters needed by this + instance. */ + virtual int extra_margin () const + { + return 0; + } + + /* Display the line number in the window margin. OFFSET indicates + which line to display; it is 0-based, with 0 meaning the line at + the top of the window. */ + virtual void show_line_number (int offset) const + { + } + /* Redraw the complete line of a source or disassembly window. */ void show_source_line (int lineno); @@ -102,6 +116,9 @@ struct tui_source_window_base : public tui_win_info std::vector<tui_source_element> m_content; + /* Length of longest line to be displayed. */ + int m_max_length; + public: /* Refill the source window's source cache and update it. If this @@ -145,11 +162,17 @@ struct tui_source_window_base : public tui_win_info void show_source_content (); + /* Re-display the pad in the window. */ + void refresh_pad (); + /* Called when the user "set style enabled" setting is changed. */ void style_changed (); /* A token used to register and unregister an observer. */ gdb::observers::token m_observable; + + /* Pad used to display fixme mumble */ + std::unique_ptr<WINDOW, curses_deleter> m_pad; }; @@ -242,19 +265,15 @@ extern void tui_display_main (void); extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR); extern void tui_update_source_windows_with_line (struct symtab_and_line sal); -/* Extract some source text from PTR. LINE_NO is the line number. If - it is positive, it is printed at the start of the line. FIRST_COL - is the first column to extract, and LINE_WIDTH is the number of - characters to display. NDIGITS is used to format the line number - (if it is positive). If NDIGITS is greater than 0, then that many - digits are used; otherwise the line number is formatted with 6 - digits and the text is aligned to the next tab stop. Returns a - string holding the desired text. PTR is updated to point to the - start of the next line. */ +/* Extract some source text from PTR. Returns a string holding the + desired text. PTR is updated to point to the start of the next + line. If LENGTH is non-NULL, then the length of the line is stored + there. Escape sequences are not counted against the length. + Actually an approximation is used -- each byte of a multi-byte + sequence counts as a character here. */ extern std::string tui_copy_source_line (const char **ptr, - int line_no, int first_col, - int line_width, int ndigits); + int *length = nullptr); /* Constant definitions. */ #define SCROLL_THRESHOLD 2 /* Threshold for lazy scroll. */ diff --git a/gdb/unittests/tui-selftests.c b/gdb/unittests/tui-selftests.c index 6144e23f394..7ab2a634b61 100644 --- a/gdb/unittests/tui-selftests.c +++ b/gdb/unittests/tui-selftests.c @@ -31,13 +31,13 @@ static void run_tests () { const char *text = "hello"; - std::string result = tui_copy_source_line (&text, 0, 0, 50, 0); + std::string result = tui_copy_source_line (&text); SELF_CHECK (result == "hello"); SELF_CHECK (*text == '\0'); text = "hello\n"; - result = tui_copy_source_line (&text, 0, 0, 3, 0); - SELF_CHECK (result == "hel"); + result = tui_copy_source_line (&text); + SELF_CHECK (result == "hello"); SELF_CHECK (*text == '\0'); } -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/6] Use ISCNTRL in tui_copy_source_line 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey ` (3 preceding siblings ...) 2020-06-27 21:20 ` [PATCH 4/6] Use a curses pad for source and disassembly windows Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-06-27 21:20 ` [PATCH 6/6] Rewrite tui_puts Tom Tromey 2020-07-10 20:45 ` [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This changes tui_copy_source_line to use ISCNTRL. This lets it work more nicely with UTF-8 input. Note that this still won't work for stateful multi-byte encodings; for that much more work would be required. However, I think this patch does not make gdb any worse in this scenario. gdb/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> PR tui/25342: * tui/tui-winsource.c (tui_copy_source_line): Use ISNCTRL. --- gdb/ChangeLog | 5 +++++ gdb/tui/tui-winsource.c | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c index 2300b9ab1e9..30b8f69027a 100644 --- a/gdb/tui/tui-winsource.c +++ b/gdb/tui/tui-winsource.c @@ -28,6 +28,7 @@ #include "source.h" #include "objfiles.h" #include "filenames.h" +#include "safe-ctype.h" #include "tui/tui.h" #include "tui/tui-data.h" @@ -107,7 +108,9 @@ tui_copy_source_line (const char **ptr, int *length) { /* Nothing. */ } - else if (c < 040 && c != '\t') + else if (c == '\t') + process_tab (); + else if (ISCNTRL (c)) { result.push_back ('^'); result.push_back (c + 0100); @@ -119,8 +122,6 @@ tui_copy_source_line (const char **ptr, int *length) result.push_back ('?'); ++column; } - else if (c == '\t') - process_tab (); else result.push_back (c); } -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/6] Rewrite tui_puts 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey ` (4 preceding siblings ...) 2020-06-27 21:20 ` [PATCH 5/6] Use ISCNTRL in tui_copy_source_line Tom Tromey @ 2020-06-27 21:20 ` Tom Tromey 2020-07-10 20:45 ` [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 6 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-06-27 21:20 UTC (permalink / raw) To: gdb-patches; +Cc: Tom Tromey This rewrites tui_puts. It now writes as many bytes as possible in a call to waddnstr, letting curses handle multi-byte sequences properly. Note that tui_puts_internal remains. It is needed to handle computing the start line of the readline prompt, which is difficult to do properly in the case where redisplaying can also cause the command window to scroll. This might be possible to implement by reverting to single "character" output, by using mbsrtowcs for its side effects to find character boundaries in the input. I have not attempted this. gdb/ChangeLog 2020-06-27 Tom Tromey <tom@tromey.com> PR tui/25342: * tui/tui-io.c (tui_puts): Rewrite. Move earlier. --- gdb/ChangeLog | 5 ++++ gdb/tui/tui-io.c | 75 ++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c index 277b560af4f..4ddb23577ae 100644 --- a/gdb/tui/tui-io.c +++ b/gdb/tui/tui-io.c @@ -435,6 +435,69 @@ tui_write (const char *buf, size_t length) tui_puts (copy.c_str ()); } +/* Print a string in the curses command window. The output is + buffered. It is up to the caller to refresh the screen if + necessary. */ + +void +tui_puts (const char *string, WINDOW *w) +{ + if (w == nullptr) + w = TUI_CMD_WIN->handle.get (); + + while (true) + { + const char *next = strpbrk (string, "\n\1\2\033\t"); + + /* Print the plain text prefix. */ + size_t n_chars = next == nullptr ? strlen (string) : next - string; + if (n_chars > 0) + waddnstr (w, string, n_chars); + + /* We finished. */ + if (next == nullptr) + break; + + char c = *next; + switch (c) + { + case '\1': + case '\2': + /* Ignore these, they are readline escape-marking + sequences. */ + ++next; + break; + + case '\n': + case '\t': + do_tui_putc (w, c); + ++next; + break; + + case '\033': + { + size_t bytes_read = apply_ansi_escape (w, next); + if (bytes_read > 0) + next += bytes_read; + else + { + /* Just drop the escape. */ + ++next; + } + } + break; + + default: + gdb_assert_not_reached ("missing case in tui_puts"); + } + + string = next; + } + + if (TUI_CMD_WIN != nullptr && w == TUI_CMD_WIN->handle.get ()) + update_cmdwin_start_line (); +} + static void tui_puts_internal (WINDOW *w, const char *string, int *height) { @@ -480,18 +543,6 @@ tui_puts_internal (WINDOW *w, const char *string, int *height) wrefresh (w); } -/* Print a string in the curses command window. The output is - buffered. It is up to the caller to refresh the screen if - necessary. */ - -void -tui_puts (const char *string, WINDOW *w) -{ - if (w == nullptr) - w = TUI_CMD_WIN->handle.get (); - tui_puts_internal (w, string, nullptr); -} - /* Readline callback. Redisplay the command line with its prompt after readline has changed the edited text. */ -- 2.17.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/6] Handle UTF-8 in TUI source windows 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey ` (5 preceding siblings ...) 2020-06-27 21:20 ` [PATCH 6/6] Rewrite tui_puts Tom Tromey @ 2020-07-10 20:45 ` Tom Tromey 2020-09-28 2:29 ` Tom Tromey 6 siblings, 1 reply; 9+ messages in thread From: Tom Tromey @ 2020-07-10 20:45 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches >>>>> "Tom" == Tom Tromey <tom@tromey.com> writes: Tom> This series implements support for displaying UTF-8 sources in TUI Tom> windows. This implementation properly handles horizontal scrolling, Tom> which was an issue in earlier attempts. Tom> No new test case -- I tried to write one, but I could not get it to Tom> work. It's unclear if this is due to a bug in my test, a bug in Tom> tuiterm.exp, or a bug in curses; and I got irritated trying to find Tom> out. Just FYI, I'm planning to hold this series until after the release branch is made. This introduces the first use of curses pads into gdb, which makes me a bit nervous. Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 0/6] Handle UTF-8 in TUI source windows 2020-07-10 20:45 ` [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey @ 2020-09-28 2:29 ` Tom Tromey 0 siblings, 0 replies; 9+ messages in thread From: Tom Tromey @ 2020-09-28 2:29 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches Tom> This series implements support for displaying UTF-8 sources in TUI Tom> windows. This implementation properly handles horizontal scrolling, Tom> which was an issue in earlier attempts. Tom> No new test case -- I tried to write one, but I could not get it to Tom> work. It's unclear if this is due to a bug in my test, a bug in Tom> tuiterm.exp, or a bug in curses; and I got irritated trying to find Tom> out. [... later ...] Tom> Just FYI, I'm planning to hold this series until after the release Tom> branch is made. This introduces the first use of curses pads into gdb, Tom> which makes me a bit nervous. I'm going to check this in now. Let me know if you encounter any problems. Tom ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-09-28 2:29 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-06-27 21:20 [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 2020-06-27 21:20 ` [PATCH 1/6] Remove test duplicate from gdb.tui Tom Tromey 2020-06-27 21:20 ` [PATCH 2/6] Use an inner window in tui_py_window Tom Tromey 2020-06-27 21:20 ` [PATCH 3/6] Remove a call to show_source_line from TUI Tom Tromey 2020-06-27 21:20 ` [PATCH 4/6] Use a curses pad for source and disassembly windows Tom Tromey 2020-06-27 21:20 ` [PATCH 5/6] Use ISCNTRL in tui_copy_source_line Tom Tromey 2020-06-27 21:20 ` [PATCH 6/6] Rewrite tui_puts Tom Tromey 2020-07-10 20:45 ` [PATCH 0/6] Handle UTF-8 in TUI source windows Tom Tromey 2020-09-28 2:29 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).