)]}'
{
  "commit": "6acafdaef76a4505b7cd87d7612d59dee4302f7d",
  "tree": "7a51a95a573621bddde80cf9b8d323edfc6580cc",
  "parents": [
    "9bea9aa7d29330783541861d7498d51fbb0002c7"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Sat Dec 24 20:45:51 2022 +0000"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Fri Jan 27 16:20:10 2023 +0000"
  },
  "message": "gdb/tui: rewrite of tui_source_window_base to handle very long lines\n\nThis commit addresses an issue that is exposed by the test script\ngdb.tui/tui-disasm-long-lines.exp, that is, tui_source_window_base\ndoes not handle very long lines.\n\nThe problem can be traced back to the newpad call in\ntui_source_window_base::show_source_content, this is where we allocate\na backing pad to hold the window content.\n\nUnfortunately, there appears to be a limit to the size of pad that can\nbe allocated, and the gdb.tui/tui-disasm-long-lines.exp test goes\nbeyond this limit.  As a consequence the newpad call fails and returns\nnullptr.\n\nIt just so happens that the reset of the tui_source_window_base code\ncan handle the pad being nullptr (this happens anyway when the window\nis first created, so we already depend on nullptr handling), so all\nthat happens is the source window displays no content.\n\n... well, sort of ... something weird does happen in the command\nwindow, we seem to see a whole bunch of blank lines.  I\u0027ve not\nbothered to track down exactly what\u0027s happening there, but it\u0027s some\nconsequence of GDB attempting to write content to a WINDOW* that is\nnullptr.\n\nBefore explaining my solution, I\u0027ll outline how things currently work:\n\nConsider we have the following window content to display:\n\n  aaaaaaaaaa\n  bbbbbbbbbbbbbbbbbbbb\n  ccccccccccccccc\n\nthe longest line here is 20 characters.  If our display window is 10\ncharacters wide, then we will create a pad that is 20 characters wide,\nand then copy the lines of content into the pad:\n\n  .--------------------.\n  |aaaaaaaaaa          |\n  |bbbbbbbbbbbbbbbbbbbb|\n  |ccccccccccccccc     |\n  .--------------------.\n\nNow we will copy a 10 character wide view into this pad to the\ndisplay, our display will then see:\n\n  .----------.\n  |aaaaaaaaaa|\n  |bbbbbbbbbb|\n  |cccccccccc|\n  .----------.\n\nAs the user scrolls left and right we adjust m_horizontal_offset and\nuse this to select which part of the pad is copied onto the display.\n\nThe benefit of this is that we only need to copy the content to the\npad once, which includes processing the ansi escape sequences, and\nthen the user can scroll left and right as much as they want\nrelatively cheaply.\n\nThe problem then, is that if the longest content line is very long,\nthen we try to allocate a very large pad, which can fail.\n\nWhat I propose is that we allow both the pad and the display view to\nscroll.  Once we allow this, then it becomes possible to allocate a\npad that is smaller than the longest display line.  We then copy part\nof the content into the pad.  As the user scrolls the view left and\nright GDB will continue to copy content from the pad just as it does\nright now.  But, when the user scrolls to the edge of the pad, GDB\nwill copy a new block of content into the pad, and then update the\nview as normal.  This all works fine so long as the maximum pad size\nis larger than the current window size - which seems a reasonable\nrestriction, if ncurses can\u0027t support a pad of a given size it seems\nlikely it will not support a display window of that size either.\n\nIf we return to our example above, but this time we assume that the\nmaximum pad size is 15 characters, then initially the pad would be\nloaded like this:\n\n  .---------------.\n  |aaaaaaaaaa     |\n  |bbbbbbbbbbbbbbb|\n  |ccccccccccccccc|\n  .---------------.\n\nNotice that the last 5 characters from the \u0027b\u0027 line are no longer\nincluded in the pad.  There is still enough content though to fill the\n10 character wide display, just as we did before.\n\nThe pad contents remain unchanged until the user scrolls the display\nright to this point:\n\n  .----------.\n  |aaaaa     |\n  |bbbbbbbbbb|\n  |cccccccccc|\n  .----------.\n\nNow, when the user scrolls right once more GDB spots that the user has\nreached the end of the pad, and the pad contents are reloaded, like\nthis:\n\n  .---------------.\n  |aaaaa          |\n  |bbbbbbbbbbbbbbb|\n  |cccccccccc     |\n  .---------------.\n\nThe display can now be updated from the pad again just like normal.\n\nWith this change in place the gdb.tui/tui-disasm-long-lines.exp test\nnow correctly loads the assembler code, and we can scroll around as\nexpected.\n\nMost of the changes are pretty mundane, just updating to match the\nabove.  One interesting change though is the new member function\ntui_source_window_base::puts_to_pad_with_skip.  This replaces direct\ncalls to tui_puts when copying content to the pad.\n\nThe content strings contain ansi escape sequences.  When these strings\nare written to the pad these escape sequences are translated into\nncurses attribute setting calls.\n\nNow however, we sometimes only write a partial string to the pad,\nskipping some of the leading content.  Imagine then that we have a\ncontent line like this:\n\n  \"\\033[31mABCDEFGHIJKLM\\033[0m\"\n\nNow the escape sequences in this content mean that the actual\ncontent (the \u0027ABCDEFGHIJKLM\u0027) will have a red foreground color.\n\nIf we want to copy this to the pad, but skip the first 3 characters,\nthen what we expect is to have the pad contain \u0027DEFGHIJKLM\u0027, but this\ntext should still have a red foreground color.\n\nIt is this problem that puts_to_pad_with_skip solves.  This function\nskips some number of printable characters, but processes all the\nescape sequences.  This means that when we do start printing the\nactual content the content will have the expected attributes.\n/\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "ae19f2e69cb293d1a49a9e5577536a66fa4fdb08",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp",
      "new_id": "5d395cd604b506638cd5d3630999989fc0adee47",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.tui/tui-disasm-long-lines.exp"
    },
    {
      "type": "modify",
      "old_id": "87099ac26f5a0b6045948da6bc1e47d2ecf3ccad",
      "old_mode": 33188,
      "old_path": "gdb/tui/tui-winsource.c",
      "new_id": "6e22638ec746a572d9e48379b5044341542c3457",
      "new_mode": 33188,
      "new_path": "gdb/tui/tui-winsource.c"
    },
    {
      "type": "modify",
      "old_id": "bf0ca96c09b03806b55baadcbc87f8f488f15ed1",
      "old_mode": 33188,
      "old_path": "gdb/tui/tui-winsource.h",
      "new_id": "2762afff0106b06676c4ad5568119df6b6a89e0d",
      "new_mode": 33188,
      "new_path": "gdb/tui/tui-winsource.h"
    }
  ]
}
