public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [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).