binutils-gdb/gdb/testsuite/gdb.tui
Andrew Burgess 6acafdaef7 gdb/tui: rewrite of tui_source_window_base to handle very long lines
This commit addresses an issue that is exposed by the test script
gdb.tui/tui-disasm-long-lines.exp, that is, tui_source_window_base
does not handle very long lines.

The problem can be traced back to the newpad call in
tui_source_window_base::show_source_content, this is where we allocate
a backing pad to hold the window content.

Unfortunately, there appears to be a limit to the size of pad that can
be allocated, and the gdb.tui/tui-disasm-long-lines.exp test goes
beyond this limit.  As a consequence the newpad call fails and returns
nullptr.

It just so happens that the reset of the tui_source_window_base code
can handle the pad being nullptr (this happens anyway when the window
is first created, so we already depend on nullptr handling), so all
that happens is the source window displays no content.

... well, sort of ... something weird does happen in the command
window, we seem to see a whole bunch of blank lines.  I've not
bothered to track down exactly what's happening there, but it's some
consequence of GDB attempting to write content to a WINDOW* that is
nullptr.

Before explaining my solution, I'll outline how things currently work:

Consider we have the following window content to display:

  aaaaaaaaaa
  bbbbbbbbbbbbbbbbbbbb
  ccccccccccccccc

the longest line here is 20 characters.  If our display window is 10
characters wide, then we will create a pad that is 20 characters wide,
and then copy the lines of content into the pad:

  .--------------------.
  |aaaaaaaaaa          |
  |bbbbbbbbbbbbbbbbbbbb|
  |ccccccccccccccc     |
  .--------------------.

Now we will copy a 10 character wide view into this pad to the
display, our display will then see:

  .----------.
  |aaaaaaaaaa|
  |bbbbbbbbbb|
  |cccccccccc|
  .----------.

As the user scrolls left and right we adjust m_horizontal_offset and
use this to select which part of the pad is copied onto the display.

The benefit of this is that we only need to copy the content to the
pad once, which includes processing the ansi escape sequences, and
then the user can scroll left and right as much as they want
relatively cheaply.

The problem then, is that if the longest content line is very long,
then we try to allocate a very large pad, which can fail.

What I propose is that we allow both the pad and the display view to
scroll.  Once we allow this, then it becomes possible to allocate a
pad that is smaller than the longest display line.  We then copy part
of the content into the pad.  As the user scrolls the view left and
right GDB will continue to copy content from the pad just as it does
right now.  But, when the user scrolls to the edge of the pad, GDB
will copy a new block of content into the pad, and then update the
view as normal.  This all works fine so long as the maximum pad size
is larger than the current window size - which seems a reasonable
restriction, if ncurses can't support a pad of a given size it seems
likely it will not support a display window of that size either.

If we return to our example above, but this time we assume that the
maximum pad size is 15 characters, then initially the pad would be
loaded like this:

  .---------------.
  |aaaaaaaaaa     |
  |bbbbbbbbbbbbbbb|
  |ccccccccccccccc|
  .---------------.

Notice that the last 5 characters from the 'b' line are no longer
included in the pad.  There is still enough content though to fill the
10 character wide display, just as we did before.

The pad contents remain unchanged until the user scrolls the display
right to this point:

  .----------.
  |aaaaa     |
  |bbbbbbbbbb|
  |cccccccccc|
  .----------.

Now, when the user scrolls right once more GDB spots that the user has
reached the end of the pad, and the pad contents are reloaded, like
this:

  .---------------.
  |aaaaa          |
  |bbbbbbbbbbbbbbb|
  |cccccccccc     |
  .---------------.

The display can now be updated from the pad again just like normal.

With this change in place the gdb.tui/tui-disasm-long-lines.exp test
now correctly loads the assembler code, and we can scroll around as
expected.

Most of the changes are pretty mundane, just updating to match the
above.  One interesting change though is the new member function
tui_source_window_base::puts_to_pad_with_skip.  This replaces direct
calls to tui_puts when copying content to the pad.

The content strings contain ansi escape sequences.  When these strings
are written to the pad these escape sequences are translated into
ncurses attribute setting calls.

Now however, we sometimes only write a partial string to the pad,
skipping some of the leading content.  Imagine then that we have a
content line like this:

  "\033[31mABCDEFGHIJKLM\033[0m"

Now the escape sequences in this content mean that the actual
content (the 'ABCDEFGHIJKLM') will have a red foreground color.

If we want to copy this to the pad, but skip the first 3 characters,
then what we expect is to have the pad contain 'DEFGHIJKLM', but this
text should still have a red foreground color.

It is this problem that puts_to_pad_with_skip solves.  This function
skips some number of printable characters, but processes all the
escape sequences.  This means that when we do start printing the
actual content the content will have the expected attributes.
/
2023-01-27 16:20:10 +00:00
..
basic.exp
break.exp
completion.exp gdb/tui: better filtering of tab completion results for focus command 2023-01-25 10:55:44 +00:00
corefile-run.exp
empty.exp
info-win.exp
list-before.exp
list.exp
main-one-line.c
main.exp
new-layout.exp
regs.exp
resize.exp
scroll.exp
tui-disasm-long-lines.c
tui-disasm-long-lines.exp gdb/tui: rewrite of tui_source_window_base to handle very long lines 2023-01-27 16:20:10 +00:00
tui-focus.c gdb/testsuite/tui: more testing of the 'focus' command 2023-01-25 10:50:57 +00:00
tui-focus.exp gdb/tui: improve errors from tui focus command 2023-01-27 16:20:10 +00:00
tui-layout-asm-short-prog.exp
tui-layout-asm-short-prog.S
tui-layout-asm.exp
tui-layout.c
tui-layout.exp
tui-missing-src.exp
tui-nl-filtered-output.exp gdb/testsuite: update gdb.tui/tui-nl-filtered-output.exp 2023-01-25 10:37:36 +00:00
tuiterm.exp
winheight.exp
winwidth.exp