+2019-08-15  Tom Tromey  <tom@tromey.com>
+
+       * tui/tui-winsource.h (struct tui_source_window_iterator): New.
+       (struct tui_source_windows): New.
+       * tui/tui-winsource.c (tui_display_main): Update.
+       * tui/tui-win.c (tui_resize_all, tui_adjust_win_heights)
+       (new_height_ok, parse_scrolling_args): Update.
+       * tui/tui-layout.c (show_layout, show_data): Update.
+       * tui/tui-data.h (tui_source_windows, tui_clear_source_windows)
+       (tui_add_to_source_windows): Don't declare.
+       * tui/tui-data.c (source_windows, tui_source_windows)
+       (tui_clear_source_windows, tui_add_to_source_windows): Remove.
+
 2019-08-15  Tom Tromey  <tom@tromey.com>
 
        * tui/tui-winsource.h (struct tui_source_window_base) <resize>:
 
 ** Private data
 ****************************/
 static int term_height, term_width;
-static std::vector<tui_source_window_base *> source_windows;
 static struct tui_win_info *win_with_focus = NULL;
 
 static int win_resized = FALSE;
 }
 
 
-/* Accessor for the current source window.  Usually there is only one
-   source window (either source or disassembly), but both can be
-   displayed at the same time.  */
-std::vector<tui_source_window_base *> &
-tui_source_windows ()
-{
-  return source_windows;
-}
-
-
-/* Clear the list of source windows.  Usually there is only one source
-   window (either source or disassembly), but both can be displayed at
-   the same time.  */
-void
-tui_clear_source_windows ()
-{
-  source_windows.clear ();
-}
-
-
 /* Clear the pertinent detail in the source windows.  */
 void
 tui_clear_source_windows_detail ()
 }
 
 
-/* Add a window to the list of source windows.  Usually there is only
-   one source window (either source or disassembly), but both can be
-   displayed at the same time.  */
-void
-tui_add_to_source_windows (struct tui_source_window_base *win_info)
-{
-  if (source_windows.size () < 2)
-    source_windows.push_back (win_info);
-}
-
 /* Accessor for the term_height.  */
 int
 tui_term_height (void)
 
 extern int tui_term_width (void);
 extern void tui_set_term_width_to (int);
 extern struct tui_locator_window *tui_locator_win_info_ptr (void);
-extern std::vector<tui_source_window_base *> &tui_source_windows ();
-extern void tui_clear_source_windows (void);
 extern void tui_clear_source_windows_detail (void);
-extern void tui_add_to_source_windows (struct tui_source_window_base *);
 extern struct tui_win_info *tui_win_with_focus (void);
 extern void tui_set_win_with_focus (struct tui_win_info *);
 extern int tui_win_resized (void);
 
 
   if (layout != cur_layout)
     {
-      /* Since the new layout may cause changes in window size, we
-         should free the content and reallocate on next display of
-         source/asm.  */
-      tui_clear_source_windows ();
       /* First make the current layout be invisible.  */
       tui_make_all_invisible ();
       tui_locator_win_info_ptr ()->make_visible (false);
          /* Now show the new layout.  */
        case SRC_COMMAND:
          show_source_command ();
-         tui_add_to_source_windows (TUI_SRC_WIN);
          break;
        case DISASSEM_COMMAND:
          show_disasm_command ();
-         tui_add_to_source_windows (TUI_DISASM_WIN);
          break;
        case SRC_DISASSEM_COMMAND:
          show_source_disasm_command ();
-         tui_add_to_source_windows (TUI_SRC_WIN);
-         tui_add_to_source_windows (TUI_DISASM_WIN);
          break;
        default:
          break;
   base->m_has_locator = true;
   locator->make_visible (true);
   tui_show_locator_content ();
-  tui_add_to_source_windows (base);
   TUI_CMD_WIN->make_visible (true);
   current_layout = new_layout;
 }
 
        {
        case SRC_COMMAND:
        case DISASSEM_COMMAND:
-         src_win = tui_source_windows ()[0];
+         src_win = *(tui_source_windows ().begin ());
          first_win = src_win;
          first_win->width += width_diff;
          locator->width += width_diff;
            {
              first_win = TUI_DATA_WIN;
              first_win->width += width_diff;
-             src_win = tui_source_windows ()[0];
+             src_win = *(tui_source_windows ().begin ());
              second_win = src_win;
              second_win->width += width_diff;
            }
              primary_win_info->make_invisible_and_set_new_height (new_height);
              if (primary_win_info->type == CMD_WIN)
                {
-                 win_info = tui_source_windows ()[0];
+                 win_info = *(tui_source_windows ().begin ());
                  src_win_info = win_info;
                }
              else
                {
                  src1 = nullptr;
                  first_win = TUI_DATA_WIN;
-                 second_win = tui_source_windows ()[0];
+                 second_win = *(tui_source_windows ().begin ());
                }
              if (primary_win_info == TUI_CMD_WIN)
                { /* Split the change in height accross the 1st & 2nd
              struct tui_win_info *win_info;
 
              if (primary_win_info == TUI_CMD_WIN)
-               win_info = tui_source_windows ()[0];
+               win_info = *(tui_source_windows ().begin ());
              else
                win_info = TUI_CMD_WIN;
              ok = ((new_height +
          else
            {
              first_win = TUI_DATA_WIN;
-             second_win = tui_source_windows ()[0];
+             second_win = *(tui_source_windows ().begin ());
            }
          /* We could simply add all the heights to obtain the same
             result but below is more explicit since we subtract 1 for
          if (!(*win_to_scroll)->is_visible)
            error (_("Window is not visible"));
          else if (*win_to_scroll == TUI_CMD_WIN)
-           *win_to_scroll = tui_source_windows ()[0];
+           *win_to_scroll = *(tui_source_windows ().begin ());
        }
     }
 }
 
 void
 tui_display_main ()
 {
-  if (!tui_source_windows ().empty ())
+  auto adapter = tui_source_windows ();
+  if (adapter.begin () != adapter.end ())
     {
       struct gdbarch *gdbarch;
       CORE_ADDR addr;
 
   std::vector<tui_source_element> content;
 };
 
+
+/* A wrapper for a TUI window iterator that only iterates over source
+   windows.  */
+
+struct tui_source_window_iterator
+{
+public:
+
+  typedef tui_source_window_iterator self_type;
+  typedef struct tui_source_window_base *value_type;
+  typedef struct tui_source_window_base *&reference;
+  typedef struct tui_source_window_base **pointer;
+  typedef std::forward_iterator_tag iterator_category;
+  typedef int difference_type;
+
+  explicit tui_source_window_iterator (bool dummy)
+    : m_iter (SRC_WIN)
+  {
+    advance ();
+  }
+
+  tui_source_window_iterator ()
+    : m_iter (tui_win_type (DISASSEM_WIN + 1))
+  {
+  }
+
+  bool operator!= (const self_type &other) const
+  {
+    return m_iter != other.m_iter;
+  }
+
+  value_type operator* () const
+  {
+    return (value_type) *m_iter;
+  }
+
+  self_type &operator++ ()
+  {
+    ++m_iter;
+    advance ();
+    return *this;
+  }
+
+private:
+
+  void advance ()
+  {
+    tui_window_iterator end;
+    while (m_iter != end && *m_iter == nullptr)
+      ++m_iter;
+  }
+
+  tui_window_iterator m_iter;
+};
+
+/* A range adapter for source windows.  */
+
+struct tui_source_windows
+{
+  tui_source_window_iterator begin () const
+  {
+    return tui_source_window_iterator (true);
+  }
+
+  tui_source_window_iterator end () const
+  {
+    return tui_source_window_iterator ();
+  }
+};
+
 /* Update the execution windows to show the active breakpoints.  This
    is called whenever a breakpoint is inserted, removed or has its
    state changed.  Normally BEING_DELETED is nullptr; if not nullptr,