//===-- IOHandlerCursesGUI.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/IOHandlerCursesGUI.h"
#include "lldb/Host/Config.h"

#if LLDB_ENABLE_CURSES
#if CURSES_HAVE_NCURSES_CURSES_H
#include <ncurses/curses.h>
#include <ncurses/panel.h>
#else
#include <curses.h>
#include <panel.h>
#endif
#endif

#if defined(__APPLE__)
#include <deque>
#endif
#include <string>

#include "lldb/Core/Debugger.h"
#include "lldb/Host/File.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringList.h"
#include "lldb/ValueObject/ValueObjectUpdater.h"
#include "lldb/lldb-forward.h"

#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"

#if LLDB_ENABLE_CURSES
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/State.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectRegister.h"
#endif

#include "llvm/ADT/StringRef.h"

#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
#endif

#include <memory>
#include <mutex>

#include <cassert>
#include <cctype>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <functional>
#include <optional>
#include <type_traits>

using namespace lldb;
using namespace lldb_private;
using llvm::StringRef;

// we may want curses to be disabled for some builds for instance, windows
#if LLDB_ENABLE_CURSES

#define KEY_CTRL_A 1
#define KEY_CTRL_E 5
#define KEY_CTRL_K 11
#define KEY_RETURN 10
#define KEY_ESCAPE 27
#define KEY_DELETE 127

#define KEY_SHIFT_TAB (KEY_MAX + 1)
#define KEY_ALT_ENTER (KEY_MAX + 2)

namespace lldb_private {
namespace curses {
class Menu;
class MenuDelegate;
class Window;
class WindowDelegate;
typedef std::shared_ptr<Menu> MenuSP;
typedef std::shared_ptr<MenuDelegate> MenuDelegateSP;
typedef std::shared_ptr<Window> WindowSP;
typedef std::shared_ptr<WindowDelegate> WindowDelegateSP;
typedef std::vector<MenuSP> Menus;
typedef std::vector<WindowSP> Windows;
typedef std::vector<WindowDelegateSP> WindowDelegates;

#if 0
type summary add -s "x=${var.x}, y=${var.y}" curses::Point
type summary add -s "w=${var.width}, h=${var.height}" curses::Size
type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect
#endif

struct Point {
  int x;
  int y;

  Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}

  void Clear() {
    x = 0;
    y = 0;
  }

  Point &operator+=(const Point &rhs) {
    x += rhs.x;
    y += rhs.y;
    return *this;
  }

  void Dump() { printf("(x=%i, y=%i)\n", x, y); }
};

bool operator==(const Point &lhs, const Point &rhs) {
  return lhs.x == rhs.x && lhs.y == rhs.y;
}

bool operator!=(const Point &lhs, const Point &rhs) {
  return lhs.x != rhs.x || lhs.y != rhs.y;
}

struct Size {
  int width;
  int height;
  Size(int w = 0, int h = 0) : width(w), height(h) {}

  void Clear() {
    width = 0;
    height = 0;
  }

  void Dump() { printf("(w=%i, h=%i)\n", width, height); }
};

bool operator==(const Size &lhs, const Size &rhs) {
  return lhs.width == rhs.width && lhs.height == rhs.height;
}

bool operator!=(const Size &lhs, const Size &rhs) {
  return lhs.width != rhs.width || lhs.height != rhs.height;
}

struct Rect {
  Point origin;
  Size size;

  Rect() : origin(), size() {}

  Rect(const Point &p, const Size &s) : origin(p), size(s) {}

  void Clear() {
    origin.Clear();
    size.Clear();
  }

  void Dump() {
    printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width,
           size.height);
  }

  void Inset(int w, int h) {
    if (size.width > w * 2)
      size.width -= w * 2;
    origin.x += w;

    if (size.height > h * 2)
      size.height -= h * 2;
    origin.y += h;
  }

  // Return a status bar rectangle which is the last line of this rectangle.
  // This rectangle will be modified to not include the status bar area.
  Rect MakeStatusBar() {
    Rect status_bar;
    if (size.height > 1) {
      status_bar.origin.x = origin.x;
      status_bar.origin.y = size.height;
      status_bar.size.width = size.width;
      status_bar.size.height = 1;
      --size.height;
    }
    return status_bar;
  }

  // Return a menubar rectangle which is the first line of this rectangle. This
  // rectangle will be modified to not include the menubar area.
  Rect MakeMenuBar() {
    Rect menubar;
    if (size.height > 1) {
      menubar.origin.x = origin.x;
      menubar.origin.y = origin.y;
      menubar.size.width = size.width;
      menubar.size.height = 1;
      ++origin.y;
      --size.height;
    }
    return menubar;
  }

  void HorizontalSplitPercentage(float top_percentage, Rect &top,
                                 Rect &bottom) const {
    float top_height = top_percentage * size.height;
    HorizontalSplit(top_height, top, bottom);
  }

  void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const {
    top = *this;
    if (top_height < size.height) {
      top.size.height = top_height;
      bottom.origin.x = origin.x;
      bottom.origin.y = origin.y + top.size.height;
      bottom.size.width = size.width;
      bottom.size.height = size.height - top.size.height;
    } else {
      bottom.Clear();
    }
  }

  void VerticalSplitPercentage(float left_percentage, Rect &left,
                               Rect &right) const {
    float left_width = left_percentage * size.width;
    VerticalSplit(left_width, left, right);
  }

  void VerticalSplit(int left_width, Rect &left, Rect &right) const {
    left = *this;
    if (left_width < size.width) {
      left.size.width = left_width;
      right.origin.x = origin.x + left.size.width;
      right.origin.y = origin.y;
      right.size.width = size.width - left.size.width;
      right.size.height = size.height;
    } else {
      right.Clear();
    }
  }
};

bool operator==(const Rect &lhs, const Rect &rhs) {
  return lhs.origin == rhs.origin && lhs.size == rhs.size;
}

bool operator!=(const Rect &lhs, const Rect &rhs) {
  return lhs.origin != rhs.origin || lhs.size != rhs.size;
}

enum HandleCharResult {
  eKeyNotHandled = 0,
  eKeyHandled = 1,
  eQuitApplication = 2
};

enum class MenuActionResult {
  Handled,
  NotHandled,
  Quit // Exit all menus and quit
};

struct KeyHelp {
  int ch;
  const char *description;
};

// COLOR_PAIR index names
enum {
  // First 16 colors are 8 black background and 8 blue background colors,
  // needed by OutputColoredStringTruncated().
  BlackOnBlack = 1,
  RedOnBlack,
  GreenOnBlack,
  YellowOnBlack,
  BlueOnBlack,
  MagentaOnBlack,
  CyanOnBlack,
  WhiteOnBlack,
  BlackOnBlue,
  RedOnBlue,
  GreenOnBlue,
  YellowOnBlue,
  BlueOnBlue,
  MagentaOnBlue,
  CyanOnBlue,
  WhiteOnBlue,
  // Other colors, as needed.
  BlackOnWhite,
  MagentaOnWhite,
  LastColorPairIndex = MagentaOnWhite
};

class WindowDelegate {
public:
  virtual ~WindowDelegate() = default;

  virtual bool WindowDelegateDraw(Window &window, bool force) {
    return false; // Drawing not handled
  }

  virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) {
    return eKeyNotHandled;
  }

  virtual const char *WindowDelegateGetHelpText() { return nullptr; }

  virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; }
};

class HelpDialogDelegate : public WindowDelegate {
public:
  HelpDialogDelegate(const char *text, KeyHelp *key_help_array);

  ~HelpDialogDelegate() override;

  bool WindowDelegateDraw(Window &window, bool force) override;

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;

  size_t GetNumLines() const { return m_text.GetSize(); }

  size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); }

protected:
  StringList m_text;
  int m_first_visible_line = 0;
};

// A surface is an abstraction for something than can be drawn on. The surface
// have a width, a height, a cursor position, and a multitude of drawing
// operations. This type should be sub-classed to get an actually useful ncurses
// object, such as a Window or a Pad.
class Surface {
public:
  enum class Type { Window, Pad };

  Surface(Surface::Type type) : m_type(type) {}

  WINDOW *get() { return m_window; }

  operator WINDOW *() { return m_window; }

  Surface SubSurface(Rect bounds) {
    Surface subSurface(m_type);
    if (m_type == Type::Pad)
      subSurface.m_window =
          ::subpad(m_window, bounds.size.height, bounds.size.width,
                   bounds.origin.y, bounds.origin.x);
    else
      subSurface.m_window =
          ::derwin(m_window, bounds.size.height, bounds.size.width,
                   bounds.origin.y, bounds.origin.x);
    return subSurface;
  }

  // Copy a region of the surface to another surface.
  void CopyToSurface(Surface &target, Point source_origin, Point target_origin,
                     Size size) {
    ::copywin(m_window, target.get(), source_origin.y, source_origin.x,
              target_origin.y, target_origin.x,
              target_origin.y + size.height - 1,
              target_origin.x + size.width - 1, false);
  }

  int GetCursorX() const { return getcurx(m_window); }
  int GetCursorY() const { return getcury(m_window); }
  void MoveCursor(int x, int y) { ::wmove(m_window, y, x); }

  void AttributeOn(attr_t attr) { ::wattron(m_window, attr); }
  void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); }

  int GetMaxX() const { return getmaxx(m_window); }
  int GetMaxY() const { return getmaxy(m_window); }
  int GetWidth() const { return GetMaxX(); }
  int GetHeight() const { return GetMaxY(); }
  Size GetSize() const { return Size(GetWidth(), GetHeight()); }
  // Get a zero origin rectangle width the surface size.
  Rect GetFrame() const { return Rect(Point(), GetSize()); }

  void Clear() { ::wclear(m_window); }
  void Erase() { ::werase(m_window); }

  void SetBackground(int color_pair_idx) {
    ::wbkgd(m_window, COLOR_PAIR(color_pair_idx));
  }

  void PutChar(int ch) { ::waddch(m_window, ch); }
  void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); }

  void PutCStringTruncated(int right_pad, const char *s, int len = -1) {
    int bytes_left = GetWidth() - GetCursorX();
    if (bytes_left > right_pad) {
      bytes_left -= right_pad;
      ::waddnstr(m_window, s, len < 0 ? bytes_left : std::min(bytes_left, len));
    }
  }

  void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) {
    va_list args;
    va_start(args, format);
    vw_printw(m_window, format, args);
    va_end(args);
  }

  void PrintfTruncated(int right_pad, const char *format, ...)
      __attribute__((format(printf, 3, 4))) {
    va_list args;
    va_start(args, format);
    StreamString strm;
    strm.PrintfVarArg(format, args);
    va_end(args);
    PutCStringTruncated(right_pad, strm.GetData());
  }

  void VerticalLine(int n, chtype v_char = ACS_VLINE) {
    ::wvline(m_window, v_char, n);
  }
  void HorizontalLine(int n, chtype h_char = ACS_HLINE) {
    ::whline(m_window, h_char, n);
  }
  void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
    ::box(m_window, v_char, h_char);
  }

  void TitledBox(const char *title, chtype v_char = ACS_VLINE,
                 chtype h_char = ACS_HLINE) {
    Box(v_char, h_char);
    int title_offset = 2;
    MoveCursor(title_offset, 0);
    PutChar('[');
    PutCString(title, GetWidth() - title_offset);
    PutChar(']');
  }

  void Box(const Rect &bounds, chtype v_char = ACS_VLINE,
           chtype h_char = ACS_HLINE) {
    MoveCursor(bounds.origin.x, bounds.origin.y);
    VerticalLine(bounds.size.height);
    HorizontalLine(bounds.size.width);
    PutChar(ACS_ULCORNER);

    MoveCursor(bounds.origin.x + bounds.size.width - 1, bounds.origin.y);
    VerticalLine(bounds.size.height);
    PutChar(ACS_URCORNER);

    MoveCursor(bounds.origin.x, bounds.origin.y + bounds.size.height - 1);
    HorizontalLine(bounds.size.width);
    PutChar(ACS_LLCORNER);

    MoveCursor(bounds.origin.x + bounds.size.width - 1,
               bounds.origin.y + bounds.size.height - 1);
    PutChar(ACS_LRCORNER);
  }

  void TitledBox(const Rect &bounds, const char *title,
                 chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) {
    Box(bounds, v_char, h_char);
    int title_offset = 2;
    MoveCursor(bounds.origin.x + title_offset, bounds.origin.y);
    PutChar('[');
    PutCString(title, bounds.size.width - title_offset);
    PutChar(']');
  }

  // Curses doesn't allow direct output of color escape sequences, but that's
  // how we get source lines from the Highligher class. Read the line and
  // convert color escape sequences to curses color attributes. Use
  // first_skip_count to skip leading visible characters. Returns false if all
  // visible characters were skipped due to first_skip_count.
  bool OutputColoredStringTruncated(int right_pad, StringRef string,
                                    size_t skip_first_count,
                                    bool use_blue_background) {
    attr_t saved_attr;
    short saved_pair;
    bool result = false;
    wattr_get(m_window, &saved_attr, &saved_pair, nullptr);
    if (use_blue_background)
      ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
    while (!string.empty()) {
      size_t esc_pos = string.find(ANSI_ESC_START);
      if (esc_pos == StringRef::npos) {
        string = string.substr(skip_first_count);
        if (!string.empty()) {
          PutCStringTruncated(right_pad, string.data(), string.size());
          result = true;
        }
        break;
      }
      if (esc_pos > 0) {
        if (skip_first_count > 0) {
          int skip = std::min(esc_pos, skip_first_count);
          string = string.substr(skip);
          skip_first_count -= skip;
          esc_pos -= skip;
        }
        if (esc_pos > 0) {
          PutCStringTruncated(right_pad, string.data(), esc_pos);
          result = true;
          string = string.drop_front(esc_pos);
        }
      }
      bool consumed = string.consume_front(ANSI_ESC_START);
      assert(consumed);
      UNUSED_IF_ASSERT_DISABLED(consumed);
      // This is written to match our Highlighter classes, which seem to
      // generate only foreground color escape sequences. If necessary, this
      // will need to be extended.
      // Only 8 basic foreground colors, underline and reset, our Highlighter
      // doesn't use anything else.
      int value;
      if (!!string.consumeInteger(10, value) || // Returns false on success.
          !(value == 0 || value == ANSI_CTRL_UNDERLINE ||
            (value >= ANSI_FG_COLOR_BLACK && value <= ANSI_FG_COLOR_WHITE))) {
        llvm::errs() << "No valid color code in color escape sequence.\n";
        continue;
      }
      if (!string.consume_front(ANSI_ESC_END)) {
        llvm::errs() << "Missing '" << ANSI_ESC_END
                     << "' in color escape sequence.\n";
        continue;
      }
      if (value == 0) { // Reset.
        wattr_set(m_window, saved_attr, saved_pair, nullptr);
        if (use_blue_background)
          ::wattron(m_window, COLOR_PAIR(WhiteOnBlue));
      } else if (value == ANSI_CTRL_UNDERLINE) {
        ::wattron(m_window, A_UNDERLINE);
      } else {
        // Mapped directly to first 16 color pairs (black/blue background).
        ::wattron(m_window, COLOR_PAIR(value - ANSI_FG_COLOR_BLACK + 1 +
                                       (use_blue_background ? 8 : 0)));
      }
    }
    wattr_set(m_window, saved_attr, saved_pair, nullptr);
    return result;
  }

protected:
  Type m_type;
  WINDOW *m_window = nullptr;
};

class Pad : public Surface {
public:
  Pad(Size size) : Surface(Surface::Type::Pad) {
    m_window = ::newpad(size.height, size.width);
  }

  ~Pad() { ::delwin(m_window); }
};

class Window : public Surface {
public:
  Window(const char *name)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(false),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {}

  Window(const char *name, WINDOW *w, bool del = true)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(del),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
    if (w)
      Reset(w);
  }

  Window(const char *name, const Rect &bounds)
      : Surface(Surface::Type::Window), m_name(name), m_panel(nullptr),
        m_parent(nullptr), m_subwindows(), m_delegate_sp(),
        m_curr_active_window_idx(UINT32_MAX),
        m_prev_active_window_idx(UINT32_MAX), m_delete(false),
        m_needs_update(true), m_can_activate(true), m_is_subwin(false) {
    Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y,
                   bounds.origin.y));
  }

  virtual ~Window() {
    RemoveSubWindows();
    Reset();
  }

  void Reset(WINDOW *w = nullptr, bool del = true) {
    if (m_window == w)
      return;

    if (m_panel) {
      ::del_panel(m_panel);
      m_panel = nullptr;
    }
    if (m_window && m_delete) {
      ::delwin(m_window);
      m_window = nullptr;
      m_delete = false;
    }
    if (w) {
      m_window = w;
      m_panel = ::new_panel(m_window);
      m_delete = del;
    }
  }

  // Get the rectangle in our parent window
  Rect GetBounds() const { return Rect(GetParentOrigin(), GetSize()); }

  Rect GetCenteredRect(int width, int height) {
    Size size = GetSize();
    width = std::min(size.width, width);
    height = std::min(size.height, height);
    int x = (size.width - width) / 2;
    int y = (size.height - height) / 2;
    return Rect(Point(x, y), Size(width, height));
  }

  int GetChar() { return ::wgetch(m_window); }
  Point GetParentOrigin() const { return Point(GetParentX(), GetParentY()); }
  int GetParentX() const { return getparx(m_window); }
  int GetParentY() const { return getpary(m_window); }
  void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); }
  void Resize(int w, int h) { ::wresize(m_window, h, w); }
  void Resize(const Size &size) {
    ::wresize(m_window, size.height, size.width);
  }
  void MoveWindow(const Point &origin) {
    const bool moving_window = origin != GetParentOrigin();
    if (m_is_subwin && moving_window) {
      // Can't move subwindows, must delete and re-create
      Size size = GetSize();
      Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y,
                     origin.x),
            true);
    } else {
      ::mvwin(m_window, origin.y, origin.x);
    }
  }

  void SetBounds(const Rect &bounds) {
    const bool moving_window = bounds.origin != GetParentOrigin();
    if (m_is_subwin && moving_window) {
      // Can't move subwindows, must delete and re-create
      Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width,
                     bounds.origin.y, bounds.origin.x),
            true);
    } else {
      if (moving_window)
        MoveWindow(bounds.origin);
      Resize(bounds.size);
    }
  }

  void Touch() {
    ::touchwin(m_window);
    if (m_parent)
      m_parent->Touch();
  }

  WindowSP CreateSubWindow(const char *name, const Rect &bounds,
                           bool make_active) {
    auto get_window = [this, &bounds]() {
      return m_window
                 ? ::subwin(m_window, bounds.size.height, bounds.size.width,
                            bounds.origin.y, bounds.origin.x)
                 : ::newwin(bounds.size.height, bounds.size.width,
                            bounds.origin.y, bounds.origin.x);
    };
    WindowSP subwindow_sp = std::make_shared<Window>(name, get_window(), true);
    subwindow_sp->m_is_subwin = subwindow_sp.operator bool();
    subwindow_sp->m_parent = this;
    if (make_active) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      m_curr_active_window_idx = m_subwindows.size();
    }
    m_subwindows.push_back(subwindow_sp);
    ::top_panel(subwindow_sp->m_panel);
    m_needs_update = true;
    return subwindow_sp;
  }

  bool RemoveSubWindow(Window *window) {
    Windows::iterator pos, end = m_subwindows.end();
    size_t i = 0;
    for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
      if ((*pos).get() == window) {
        if (m_prev_active_window_idx == i)
          m_prev_active_window_idx = UINT32_MAX;
        else if (m_prev_active_window_idx != UINT32_MAX &&
                 m_prev_active_window_idx > i)
          --m_prev_active_window_idx;

        if (m_curr_active_window_idx == i)
          m_curr_active_window_idx = UINT32_MAX;
        else if (m_curr_active_window_idx != UINT32_MAX &&
                 m_curr_active_window_idx > i)
          --m_curr_active_window_idx;
        window->Erase();
        m_subwindows.erase(pos);
        m_needs_update = true;
        if (m_parent)
          m_parent->Touch();
        else
          ::touchwin(stdscr);
        return true;
      }
    }
    return false;
  }

  WindowSP FindSubWindow(const char *name) {
    Windows::iterator pos, end = m_subwindows.end();
    size_t i = 0;
    for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
      if ((*pos)->m_name == name)
        return *pos;
    }
    return WindowSP();
  }

  void RemoveSubWindows() {
    m_curr_active_window_idx = UINT32_MAX;
    m_prev_active_window_idx = UINT32_MAX;
    for (Windows::iterator pos = m_subwindows.begin();
         pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) {
      (*pos)->Erase();
    }
    if (m_parent)
      m_parent->Touch();
    else
      ::touchwin(stdscr);
  }

  // Window drawing utilities
  void DrawTitleBox(const char *title, const char *bottom_message = nullptr) {
    attr_t attr = 0;
    if (IsActive())
      attr = A_BOLD | COLOR_PAIR(BlackOnWhite);
    else
      attr = 0;
    if (attr)
      AttributeOn(attr);

    Box();
    MoveCursor(3, 0);

    if (title && title[0]) {
      PutChar('<');
      PutCString(title);
      PutChar('>');
    }

    if (bottom_message && bottom_message[0]) {
      int bottom_message_length = strlen(bottom_message);
      int x = GetWidth() - 3 - (bottom_message_length + 2);

      if (x > 0) {
        MoveCursor(x, GetHeight() - 1);
        PutChar('[');
        PutCString(bottom_message);
        PutChar(']');
      } else {
        MoveCursor(1, GetHeight() - 1);
        PutChar('[');
        PutCStringTruncated(1, bottom_message);
      }
    }
    if (attr)
      AttributeOff(attr);
  }

  virtual void Draw(bool force) {
    if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force))
      return;

    for (auto &subwindow_sp : m_subwindows)
      subwindow_sp->Draw(force);
  }

  bool CreateHelpSubwindow() {
    if (m_delegate_sp) {
      const char *text = m_delegate_sp->WindowDelegateGetHelpText();
      KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp();
      if ((text && text[0]) || key_help) {
        std::unique_ptr<HelpDialogDelegate> help_delegate_up(
            new HelpDialogDelegate(text, key_help));
        const size_t num_lines = help_delegate_up->GetNumLines();
        const size_t max_length = help_delegate_up->GetMaxLineLength();
        Rect bounds = GetBounds();
        bounds.Inset(1, 1);
        if (max_length + 4 < static_cast<size_t>(bounds.size.width)) {
          bounds.origin.x += (bounds.size.width - max_length + 4) / 2;
          bounds.size.width = max_length + 4;
        } else {
          if (bounds.size.width > 100) {
            const int inset_w = bounds.size.width / 4;
            bounds.origin.x += inset_w;
            bounds.size.width -= 2 * inset_w;
          }
        }

        if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) {
          bounds.origin.y += (bounds.size.height - num_lines + 2) / 2;
          bounds.size.height = num_lines + 2;
        } else {
          if (bounds.size.height > 100) {
            const int inset_h = bounds.size.height / 4;
            bounds.origin.y += inset_h;
            bounds.size.height -= 2 * inset_h;
          }
        }
        WindowSP help_window_sp;
        Window *parent_window = GetParent();
        if (parent_window)
          help_window_sp = parent_window->CreateSubWindow("Help", bounds, true);
        else
          help_window_sp = CreateSubWindow("Help", bounds, true);
        help_window_sp->SetDelegate(
            WindowDelegateSP(help_delegate_up.release()));
        return true;
      }
    }
    return false;
  }

  virtual HandleCharResult HandleChar(int key) {
    // Always check the active window first
    HandleCharResult result = eKeyNotHandled;
    WindowSP active_window_sp = GetActiveWindow();
    if (active_window_sp) {
      result = active_window_sp->HandleChar(key);
      if (result != eKeyNotHandled)
        return result;
    }

    if (m_delegate_sp) {
      result = m_delegate_sp->WindowDelegateHandleChar(*this, key);
      if (result != eKeyNotHandled)
        return result;
    }

    // Then check for any windows that want any keys that weren't handled. This
    // is typically only for a menubar. Make a copy of the subwindows in case
    // any HandleChar() functions muck with the subwindows. If we don't do
    // this, we can crash when iterating over the subwindows.
    Windows subwindows(m_subwindows);
    for (auto subwindow_sp : subwindows) {
      if (!subwindow_sp->m_can_activate) {
        HandleCharResult result = subwindow_sp->HandleChar(key);
        if (result != eKeyNotHandled)
          return result;
      }
    }

    return eKeyNotHandled;
  }

  WindowSP GetActiveWindow() {
    if (!m_subwindows.empty()) {
      if (m_curr_active_window_idx >= m_subwindows.size()) {
        if (m_prev_active_window_idx < m_subwindows.size()) {
          m_curr_active_window_idx = m_prev_active_window_idx;
          m_prev_active_window_idx = UINT32_MAX;
        } else if (IsActive()) {
          m_prev_active_window_idx = UINT32_MAX;
          m_curr_active_window_idx = UINT32_MAX;

          // Find first window that wants to be active if this window is active
          const size_t num_subwindows = m_subwindows.size();
          for (size_t i = 0; i < num_subwindows; ++i) {
            if (m_subwindows[i]->GetCanBeActive()) {
              m_curr_active_window_idx = i;
              break;
            }
          }
        }
      }

      if (m_curr_active_window_idx < m_subwindows.size())
        return m_subwindows[m_curr_active_window_idx];
    }
    return WindowSP();
  }

  bool GetCanBeActive() const { return m_can_activate; }

  void SetCanBeActive(bool b) { m_can_activate = b; }

  void SetDelegate(const WindowDelegateSP &delegate_sp) {
    m_delegate_sp = delegate_sp;
  }

  Window *GetParent() const { return m_parent; }

  bool IsActive() const {
    if (m_parent)
      return m_parent->GetActiveWindow().get() == this;
    else
      return true; // Top level window is always active
  }

  void SelectNextWindowAsActive() {
    // Move active focus to next window
    const int num_subwindows = m_subwindows.size();
    int start_idx = 0;
    if (m_curr_active_window_idx != UINT32_MAX) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      start_idx = m_curr_active_window_idx + 1;
    }
    for (int idx = start_idx; idx < num_subwindows; ++idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        return;
      }
    }
    for (int idx = 0; idx < start_idx; ++idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        break;
      }
    }
  }

  void SelectPreviousWindowAsActive() {
    // Move active focus to previous window
    const int num_subwindows = m_subwindows.size();
    int start_idx = num_subwindows - 1;
    if (m_curr_active_window_idx != UINT32_MAX) {
      m_prev_active_window_idx = m_curr_active_window_idx;
      start_idx = m_curr_active_window_idx - 1;
    }
    for (int idx = start_idx; idx >= 0; --idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        return;
      }
    }
    for (int idx = num_subwindows - 1; idx > start_idx; --idx) {
      if (m_subwindows[idx]->GetCanBeActive()) {
        m_curr_active_window_idx = idx;
        break;
      }
    }
  }

  const char *GetName() const { return m_name.c_str(); }

protected:
  std::string m_name;
  PANEL *m_panel;
  Window *m_parent;
  Windows m_subwindows;
  WindowDelegateSP m_delegate_sp;
  uint32_t m_curr_active_window_idx;
  uint32_t m_prev_active_window_idx;
  bool m_delete;
  bool m_needs_update;
  bool m_can_activate;
  bool m_is_subwin;

private:
  Window(const Window &) = delete;
  const Window &operator=(const Window &) = delete;
};

/////////
// Forms
/////////

// A scroll context defines a vertical region that needs to be visible in a
// scrolling area. The region is defined by the index of the start and end lines
// of the region. The start and end lines may be equal, in which case, the
// region is a single line.
struct ScrollContext {
  int start;
  int end;

  ScrollContext(int line) : start(line), end(line) {}
  ScrollContext(int _start, int _end) : start(_start), end(_end) {}

  void Offset(int offset) {
    start += offset;
    end += offset;
  }
};

class FieldDelegate {
public:
  virtual ~FieldDelegate() = default;

  // Returns the number of lines needed to draw the field. The draw method will
  // be given a surface that have exactly this number of lines.
  virtual int FieldDelegateGetHeight() = 0;

  // Returns the scroll context in the local coordinates of the field. By
  // default, the scroll context spans the whole field. Bigger fields with
  // internal navigation should override this method to provide a finer context.
  // Typical override methods would first get the scroll context of the internal
  // element then add the offset of the element in the field.
  virtual ScrollContext FieldDelegateGetScrollContext() {
    return ScrollContext(0, FieldDelegateGetHeight() - 1);
  }

  // Draw the field in the given subpad surface. The surface have a height that
  // is equal to the height returned by FieldDelegateGetHeight(). If the field
  // is selected in the form window, then is_selected will be true.
  virtual void FieldDelegateDraw(Surface &surface, bool is_selected) = 0;

  // Handle the key that wasn't handled by the form window or a container field.
  virtual HandleCharResult FieldDelegateHandleChar(int key) {
    return eKeyNotHandled;
  }

  // This is executed once the user exists the field, that is, once the user
  // navigates to the next or the previous field. This is particularly useful to
  // do in-field validation and error setting. Fields with internal navigation
  // should call this method on their fields.
  virtual void FieldDelegateExitCallback() {}

  // Fields may have internal navigation, for instance, a List Field have
  // multiple internal elements, which needs to be navigated. To allow for this
  // mechanism, the window shouldn't handle the navigation keys all the time,
  // and instead call the key handing method of the selected field. It should
  // only handle the navigation keys when the field contains a single element or
  // have the last or first element selected depending on if the user is
  // navigating forward or backward. Additionally, once a field is selected in
  // the forward or backward direction, its first or last internal element
  // should be selected. The following methods implements those mechanisms.

  // Returns true if the first element in the field is selected or if the field
  // contains a single element.
  virtual bool FieldDelegateOnFirstOrOnlyElement() { return true; }

  // Returns true if the last element in the field is selected or if the field
  // contains a single element.
  virtual bool FieldDelegateOnLastOrOnlyElement() { return true; }

  // Select the first element in the field if multiple elements exists.
  virtual void FieldDelegateSelectFirstElement() {}

  // Select the last element in the field if multiple elements exists.
  virtual void FieldDelegateSelectLastElement() {}

  // Returns true if the field has an error, false otherwise.
  virtual bool FieldDelegateHasError() { return false; }

  bool FieldDelegateIsVisible() { return m_is_visible; }

  void FieldDelegateHide() { m_is_visible = false; }

  void FieldDelegateShow() { m_is_visible = true; }

protected:
  bool m_is_visible = true;
};

typedef std::unique_ptr<FieldDelegate> FieldDelegateUP;

class TextFieldDelegate : public FieldDelegate {
public:
  TextFieldDelegate(const char *label, const char *content, bool required)
      : m_label(label), m_required(required) {
    if (content)
      m_content = content;
  }

  // Text fields are drawn as titled boxes of a single line, with a possible
  // error messages at the end.
  //
  // __[Label]___________
  // |                  |
  // |__________________|
  // - Error message if it exists.

  // The text field has a height of 3 lines. 2 lines for borders and 1 line for
  // the content.
  int GetFieldHeight() { return 3; }

  // The text field has a full height of 3 or 4 lines. 3 lines for the actual
  // field and an optional line for an error if it exists.
  int FieldDelegateGetHeight() override {
    int height = GetFieldHeight();
    if (FieldDelegateHasError())
      height++;
    return height;
  }

  // Get the cursor X position in the surface coordinate.
  int GetCursorXPosition() { return m_cursor_position - m_first_visibile_char; }

  int GetContentLength() { return m_content.length(); }

  void DrawContent(Surface &surface, bool is_selected) {
    UpdateScrolling(surface.GetWidth());

    surface.MoveCursor(0, 0);
    const char *text = m_content.c_str() + m_first_visibile_char;
    surface.PutCString(text, surface.GetWidth());

    // Highlight the cursor.
    surface.MoveCursor(GetCursorXPosition(), 0);
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    if (m_cursor_position == GetContentLength())
      // Cursor is past the last character. Highlight an empty space.
      surface.PutChar(' ');
    else
      surface.PutChar(m_content[m_cursor_position]);
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
  }

  void DrawField(Surface &surface, bool is_selected) {
    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Surface content_surface = surface.SubSurface(content_bounds);

    DrawContent(content_surface, is_selected);
  }

  void DrawError(Surface &surface) {
    if (!FieldDelegateHasError())
      return;
    surface.MoveCursor(0, 0);
    surface.AttributeOn(COLOR_PAIR(RedOnBlack));
    surface.PutChar(ACS_DIAMOND);
    surface.PutChar(' ');
    surface.PutCStringTruncated(1, GetError().c_str());
    surface.AttributeOff(COLOR_PAIR(RedOnBlack));
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    Rect frame = surface.GetFrame();
    Rect field_bounds, error_bounds;
    frame.HorizontalSplit(GetFieldHeight(), field_bounds, error_bounds);
    Surface field_surface = surface.SubSurface(field_bounds);
    Surface error_surface = surface.SubSurface(error_bounds);

    DrawField(field_surface, is_selected);
    DrawError(error_surface);
  }

  // Get the position of the last visible character.
  int GetLastVisibleCharPosition(int width) {
    int position = m_first_visibile_char + width - 1;
    return std::min(position, GetContentLength());
  }

  void UpdateScrolling(int width) {
    if (m_cursor_position < m_first_visibile_char) {
      m_first_visibile_char = m_cursor_position;
      return;
    }

    if (m_cursor_position > GetLastVisibleCharPosition(width))
      m_first_visibile_char = m_cursor_position - (width - 1);
  }

  // The cursor is allowed to move one character past the string.
  // m_cursor_position is in range [0, GetContentLength()].
  void MoveCursorRight() {
    if (m_cursor_position < GetContentLength())
      m_cursor_position++;
  }

  void MoveCursorLeft() {
    if (m_cursor_position > 0)
      m_cursor_position--;
  }

  void MoveCursorToStart() { m_cursor_position = 0; }

  void MoveCursorToEnd() { m_cursor_position = GetContentLength(); }

  void ScrollLeft() {
    if (m_first_visibile_char > 0)
      m_first_visibile_char--;
  }

  // Insert a character at the current cursor position and advance the cursor
  // position.
  void InsertChar(char character) {
    m_content.insert(m_cursor_position, 1, character);
    m_cursor_position++;
    ClearError();
  }

  // Remove the character before the cursor position, retreat the cursor
  // position, and scroll left.
  void RemovePreviousChar() {
    if (m_cursor_position == 0)
      return;

    m_content.erase(m_cursor_position - 1, 1);
    m_cursor_position--;
    ScrollLeft();
    ClearError();
  }

  // Remove the character after the cursor position.
  void RemoveNextChar() {
    if (m_cursor_position == GetContentLength())
      return;

    m_content.erase(m_cursor_position, 1);
    ClearError();
  }

  // Clear characters from the current cursor position to the end.
  void ClearToEnd() {
    m_content.erase(m_cursor_position);
    ClearError();
  }

  void Clear() {
    m_content.clear();
    m_cursor_position = 0;
    ClearError();
  }

  // True if the key represents a char that can be inserted in the field
  // content, false otherwise.
  virtual bool IsAcceptableChar(int key) {
    // The behavior of isprint is undefined when the value is not representable
    // as an unsigned char. So explicitly check for non-ascii key codes.
    if (key > 127)
      return false;
    return isprint(key);
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    if (IsAcceptableChar(key)) {
      ClearError();
      InsertChar((char)key);
      return eKeyHandled;
    }

    switch (key) {
    case KEY_HOME:
    case KEY_CTRL_A:
      MoveCursorToStart();
      return eKeyHandled;
    case KEY_END:
    case KEY_CTRL_E:
      MoveCursorToEnd();
      return eKeyHandled;
    case KEY_RIGHT:
    case KEY_SF:
      MoveCursorRight();
      return eKeyHandled;
    case KEY_LEFT:
    case KEY_SR:
      MoveCursorLeft();
      return eKeyHandled;
    case KEY_BACKSPACE:
    case KEY_DELETE:
      RemovePreviousChar();
      return eKeyHandled;
    case KEY_DC:
      RemoveNextChar();
      return eKeyHandled;
    case KEY_EOL:
    case KEY_CTRL_K:
      ClearToEnd();
      return eKeyHandled;
    case KEY_DL:
    case KEY_CLEAR:
      Clear();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  bool FieldDelegateHasError() override { return !m_error.empty(); }

  void FieldDelegateExitCallback() override {
    if (!IsSpecified() && m_required)
      SetError("This field is required!");
  }

  bool IsSpecified() { return !m_content.empty(); }

  void ClearError() { m_error.clear(); }

  const std::string &GetError() { return m_error; }

  void SetError(const char *error) { m_error = error; }

  const std::string &GetText() { return m_content; }

  void SetText(const char *text) {
    if (text == nullptr) {
      m_content.clear();
      return;
    }
    m_content = text;
  }

protected:
  std::string m_label;
  bool m_required;
  // The position of the top left corner character of the border.
  std::string m_content;
  // The cursor position in the content string itself. Can be in the range
  // [0, GetContentLength()].
  int m_cursor_position = 0;
  // The index of the first visible character in the content.
  int m_first_visibile_char = 0;
  // Optional error message. If empty, field is considered to have no error.
  std::string m_error;
};

class IntegerFieldDelegate : public TextFieldDelegate {
public:
  IntegerFieldDelegate(const char *label, int content, bool required)
      : TextFieldDelegate(label, std::to_string(content).c_str(), required) {}

  // Only accept digits.
  bool IsAcceptableChar(int key) override { return isdigit(key); }

  // Returns the integer content of the field.
  int GetInteger() { return std::stoi(m_content); }
};

class FileFieldDelegate : public TextFieldDelegate {
public:
  FileFieldDelegate(const char *label, const char *content, bool need_to_exist,
                    bool required)
      : TextFieldDelegate(label, content, required),
        m_need_to_exist(need_to_exist) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!m_need_to_exist)
      return;

    FileSpec file = GetResolvedFileSpec();
    if (!FileSystem::Instance().Exists(file)) {
      SetError("File doesn't exist!");
      return;
    }
    if (FileSystem::Instance().IsDirectory(file)) {
      SetError("Not a file!");
      return;
    }
  }

  FileSpec GetFileSpec() {
    FileSpec file_spec(GetPath());
    return file_spec;
  }

  FileSpec GetResolvedFileSpec() {
    FileSpec file_spec(GetPath());
    FileSystem::Instance().Resolve(file_spec);
    return file_spec;
  }

  const std::string &GetPath() { return m_content; }

protected:
  bool m_need_to_exist;
};

class DirectoryFieldDelegate : public TextFieldDelegate {
public:
  DirectoryFieldDelegate(const char *label, const char *content,
                         bool need_to_exist, bool required)
      : TextFieldDelegate(label, content, required),
        m_need_to_exist(need_to_exist) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!m_need_to_exist)
      return;

    FileSpec file = GetResolvedFileSpec();
    if (!FileSystem::Instance().Exists(file)) {
      SetError("Directory doesn't exist!");
      return;
    }
    if (!FileSystem::Instance().IsDirectory(file)) {
      SetError("Not a directory!");
      return;
    }
  }

  FileSpec GetFileSpec() {
    FileSpec file_spec(GetPath());
    return file_spec;
  }

  FileSpec GetResolvedFileSpec() {
    FileSpec file_spec(GetPath());
    FileSystem::Instance().Resolve(file_spec);
    return file_spec;
  }

  const std::string &GetPath() { return m_content; }

protected:
  bool m_need_to_exist;
};

class ArchFieldDelegate : public TextFieldDelegate {
public:
  ArchFieldDelegate(const char *label, const char *content, bool required)
      : TextFieldDelegate(label, content, required) {}

  void FieldDelegateExitCallback() override {
    TextFieldDelegate::FieldDelegateExitCallback();
    if (!IsSpecified())
      return;

    if (!GetArchSpec().IsValid())
      SetError("Not a valid arch!");
  }

  const std::string &GetArchString() { return m_content; }

  ArchSpec GetArchSpec() { return ArchSpec(GetArchString()); }
};

class BooleanFieldDelegate : public FieldDelegate {
public:
  BooleanFieldDelegate(const char *label, bool content)
      : m_label(label), m_content(content) {}

  // Boolean fields are drawn as checkboxes.
  //
  // [X] Label  or [ ] Label

  // Boolean fields are have a single line.
  int FieldDelegateGetHeight() override { return 1; }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    surface.MoveCursor(0, 0);
    surface.PutChar('[');
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    surface.PutChar(m_content ? ACS_DIAMOND : ' ');
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
    surface.PutChar(']');
    surface.PutChar(' ');
    surface.PutCString(m_label.c_str());
  }

  void ToggleContent() { m_content = !m_content; }

  void SetContentToTrue() { m_content = true; }

  void SetContentToFalse() { m_content = false; }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case 't':
    case '1':
      SetContentToTrue();
      return eKeyHandled;
    case 'f':
    case '0':
      SetContentToFalse();
      return eKeyHandled;
    case ' ':
    case '\r':
    case '\n':
    case KEY_ENTER:
      ToggleContent();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  // Returns the boolean content of the field.
  bool GetBoolean() { return m_content; }

protected:
  std::string m_label;
  bool m_content;
};

class ChoicesFieldDelegate : public FieldDelegate {
public:
  ChoicesFieldDelegate(const char *label, int number_of_visible_choices,
                       std::vector<std::string> choices)
      : m_label(label), m_number_of_visible_choices(number_of_visible_choices),
        m_choices(choices) {}

  // Choices fields are drawn as titles boxses of a number of visible choices.
  // The rest of the choices become visible as the user scroll. The selected
  // choice is denoted by a diamond as the first character.
  //
  // __[Label]___________
  // |-Choice 1         |
  // | Choice 2         |
  // | Choice 3         |
  // |__________________|

  // Choices field have two border characters plus the number of visible
  // choices.
  int FieldDelegateGetHeight() override {
    return m_number_of_visible_choices + 2;
  }

  int GetNumberOfChoices() { return m_choices.size(); }

  // Get the index of the last visible choice.
  int GetLastVisibleChoice() {
    int index = m_first_visibile_choice + m_number_of_visible_choices;
    return std::min(index, GetNumberOfChoices()) - 1;
  }

  void DrawContent(Surface &surface, bool is_selected) {
    int choices_to_draw = GetLastVisibleChoice() - m_first_visibile_choice + 1;
    for (int i = 0; i < choices_to_draw; i++) {
      surface.MoveCursor(0, i);
      int current_choice = m_first_visibile_choice + i;
      const char *text = m_choices[current_choice].c_str();
      bool highlight = is_selected && current_choice == m_choice;
      if (highlight)
        surface.AttributeOn(A_REVERSE);
      surface.PutChar(current_choice == m_choice ? ACS_DIAMOND : ' ');
      surface.PutCString(text);
      if (highlight)
        surface.AttributeOff(A_REVERSE);
    }
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    UpdateScrolling();

    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Surface content_surface = surface.SubSurface(content_bounds);

    DrawContent(content_surface, is_selected);
  }

  void SelectPrevious() {
    if (m_choice > 0)
      m_choice--;
  }

  void SelectNext() {
    if (m_choice < GetNumberOfChoices() - 1)
      m_choice++;
  }

  void UpdateScrolling() {
    if (m_choice > GetLastVisibleChoice()) {
      m_first_visibile_choice = m_choice - (m_number_of_visible_choices - 1);
      return;
    }

    if (m_choice < m_first_visibile_choice)
      m_first_visibile_choice = m_choice;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case KEY_UP:
      SelectPrevious();
      return eKeyHandled;
    case KEY_DOWN:
      SelectNext();
      return eKeyHandled;
    default:
      break;
    }
    return eKeyNotHandled;
  }

  // Returns the content of the choice as a string.
  std::string GetChoiceContent() { return m_choices[m_choice]; }

  // Returns the index of the choice.
  int GetChoice() { return m_choice; }

  void SetChoice(llvm::StringRef choice) {
    for (int i = 0; i < GetNumberOfChoices(); i++) {
      if (choice == m_choices[i]) {
        m_choice = i;
        return;
      }
    }
  }

protected:
  std::string m_label;
  int m_number_of_visible_choices;
  std::vector<std::string> m_choices;
  // The index of the selected choice.
  int m_choice = 0;
  // The index of the first visible choice in the field.
  int m_first_visibile_choice = 0;
};

class PlatformPluginFieldDelegate : public ChoicesFieldDelegate {
public:
  PlatformPluginFieldDelegate(Debugger &debugger)
      : ChoicesFieldDelegate("Platform Plugin", 3, GetPossiblePluginNames()) {
    PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
    if (platform_sp)
      SetChoice(platform_sp->GetPluginName());
  }

  std::vector<std::string> GetPossiblePluginNames() {
    std::vector<std::string> names;
    size_t i = 0;
    for (llvm::StringRef name =
             PluginManager::GetPlatformPluginNameAtIndex(i++);
         !name.empty(); name = PluginManager::GetProcessPluginNameAtIndex(i++))
      names.push_back(name.str());
    return names;
  }

  std::string GetPluginName() {
    std::string plugin_name = GetChoiceContent();
    return plugin_name;
  }
};

class ProcessPluginFieldDelegate : public ChoicesFieldDelegate {
public:
  ProcessPluginFieldDelegate()
      : ChoicesFieldDelegate("Process Plugin", 3, GetPossiblePluginNames()) {}

  std::vector<std::string> GetPossiblePluginNames() {
    std::vector<std::string> names;
    names.push_back("<default>");

    size_t i = 0;
    for (llvm::StringRef name = PluginManager::GetProcessPluginNameAtIndex(i++);
         !name.empty(); name = PluginManager::GetProcessPluginNameAtIndex(i++))
      names.push_back(name.str());
    return names;
  }

  std::string GetPluginName() {
    std::string plugin_name = GetChoiceContent();
    if (plugin_name == "<default>")
      return "";
    return plugin_name;
  }
};

class LazyBooleanFieldDelegate : public ChoicesFieldDelegate {
public:
  LazyBooleanFieldDelegate(const char *label, const char *calculate_label)
      : ChoicesFieldDelegate(label, 3, GetPossibleOptions(calculate_label)) {}

  static constexpr const char *kNo = "No";
  static constexpr const char *kYes = "Yes";

  std::vector<std::string> GetPossibleOptions(const char *calculate_label) {
    std::vector<std::string> options;
    options.push_back(calculate_label);
    options.push_back(kYes);
    options.push_back(kNo);
    return options;
  }

  LazyBool GetLazyBoolean() {
    std::string choice = GetChoiceContent();
    if (choice == kNo)
      return eLazyBoolNo;
    else if (choice == kYes)
      return eLazyBoolYes;
    else
      return eLazyBoolCalculate;
  }
};

template <class T> class ListFieldDelegate : public FieldDelegate {
public:
  ListFieldDelegate(const char *label, T default_field)
      : m_label(label), m_default_field(default_field),
        m_selection_type(SelectionType::NewButton) {}

  // Signify which element is selected. If a field or a remove button is
  // selected, then m_selection_index signifies the particular field that
  // is selected or the field that the remove button belongs to.
  enum class SelectionType { Field, RemoveButton, NewButton };

  // A List field is drawn as a titled box of a number of other fields of the
  // same type. Each field has a Remove button next to it that removes the
  // corresponding field. Finally, the last line contains a New button to add a
  // new field.
  //
  // __[Label]___________
  // | Field 0 [Remove] |
  // | Field 1 [Remove] |
  // | Field 2 [Remove] |
  // |      [New]       |
  // |__________________|

  // List fields have two lines for border characters, 1 line for the New
  // button, and the total height of the available fields.
  int FieldDelegateGetHeight() override {
    // 2 border characters.
    int height = 2;
    // Total height of the fields.
    for (int i = 0; i < GetNumberOfFields(); i++) {
      height += m_fields[i].FieldDelegateGetHeight();
    }
    // A line for the New button.
    height++;
    return height;
  }

  ScrollContext FieldDelegateGetScrollContext() override {
    int height = FieldDelegateGetHeight();
    if (m_selection_type == SelectionType::NewButton)
      return ScrollContext(height - 2, height - 1);

    FieldDelegate &field = m_fields[m_selection_index];
    ScrollContext context = field.FieldDelegateGetScrollContext();

    // Start at 1 because of the top border.
    int offset = 1;
    for (int i = 0; i < m_selection_index; i++) {
      offset += m_fields[i].FieldDelegateGetHeight();
    }
    context.Offset(offset);

    // If the scroll context is touching the top border, include it in the
    // context to show the label.
    if (context.start == 1)
      context.start--;

    // If the scroll context is touching the new button, include it as well as
    // the bottom border in the context.
    if (context.end == height - 3)
      context.end += 2;

    return context;
  }

  void DrawRemoveButton(Surface &surface, int highlight) {
    surface.MoveCursor(1, surface.GetHeight() / 2);
    if (highlight)
      surface.AttributeOn(A_REVERSE);
    surface.PutCString("[Remove]");
    if (highlight)
      surface.AttributeOff(A_REVERSE);
  }

  void DrawFields(Surface &surface, bool is_selected) {
    int line = 0;
    int width = surface.GetWidth();
    for (int i = 0; i < GetNumberOfFields(); i++) {
      int height = m_fields[i].FieldDelegateGetHeight();
      Rect bounds = Rect(Point(0, line), Size(width, height));
      Rect field_bounds, remove_button_bounds;
      bounds.VerticalSplit(bounds.size.width - sizeof(" [Remove]"),
                           field_bounds, remove_button_bounds);
      Surface field_surface = surface.SubSurface(field_bounds);
      Surface remove_button_surface = surface.SubSurface(remove_button_bounds);

      bool is_element_selected = m_selection_index == i && is_selected;
      bool is_field_selected =
          is_element_selected && m_selection_type == SelectionType::Field;
      bool is_remove_button_selected =
          is_element_selected &&
          m_selection_type == SelectionType::RemoveButton;
      m_fields[i].FieldDelegateDraw(field_surface, is_field_selected);
      DrawRemoveButton(remove_button_surface, is_remove_button_selected);

      line += height;
    }
  }

  void DrawNewButton(Surface &surface, bool is_selected) {
    const char *button_text = "[New]";
    int x = (surface.GetWidth() - sizeof(button_text) - 1) / 2;
    surface.MoveCursor(x, 0);
    bool highlight =
        is_selected && m_selection_type == SelectionType::NewButton;
    if (highlight)
      surface.AttributeOn(A_REVERSE);
    surface.PutCString(button_text);
    if (highlight)
      surface.AttributeOff(A_REVERSE);
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    surface.TitledBox(m_label.c_str());

    Rect content_bounds = surface.GetFrame();
    content_bounds.Inset(1, 1);
    Rect fields_bounds, new_button_bounds;
    content_bounds.HorizontalSplit(content_bounds.size.height - 1,
                                   fields_bounds, new_button_bounds);
    Surface fields_surface = surface.SubSurface(fields_bounds);
    Surface new_button_surface = surface.SubSurface(new_button_bounds);

    DrawFields(fields_surface, is_selected);
    DrawNewButton(new_button_surface, is_selected);
  }

  void AddNewField() {
    m_fields.push_back(m_default_field);
    m_selection_index = GetNumberOfFields() - 1;
    m_selection_type = SelectionType::Field;
    FieldDelegate &field = m_fields[m_selection_index];
    field.FieldDelegateSelectFirstElement();
  }

  void RemoveField() {
    m_fields.erase(m_fields.begin() + m_selection_index);
    if (m_selection_index != 0)
      m_selection_index--;

    if (GetNumberOfFields() > 0) {
      m_selection_type = SelectionType::Field;
      FieldDelegate &field = m_fields[m_selection_index];
      field.FieldDelegateSelectFirstElement();
    } else
      m_selection_type = SelectionType::NewButton;
  }

  HandleCharResult SelectNext(int key) {
    if (m_selection_type == SelectionType::NewButton)
      return eKeyNotHandled;

    if (m_selection_type == SelectionType::RemoveButton) {
      if (m_selection_index == GetNumberOfFields() - 1) {
        m_selection_type = SelectionType::NewButton;
        return eKeyHandled;
      }
      m_selection_index++;
      m_selection_type = SelectionType::Field;
      FieldDelegate &next_field = m_fields[m_selection_index];
      next_field.FieldDelegateSelectFirstElement();
      return eKeyHandled;
    }

    FieldDelegate &field = m_fields[m_selection_index];
    if (!field.FieldDelegateOnLastOrOnlyElement()) {
      return field.FieldDelegateHandleChar(key);
    }

    field.FieldDelegateExitCallback();

    m_selection_type = SelectionType::RemoveButton;
    return eKeyHandled;
  }

  HandleCharResult SelectPrevious(int key) {
    if (FieldDelegateOnFirstOrOnlyElement())
      return eKeyNotHandled;

    if (m_selection_type == SelectionType::RemoveButton) {
      m_selection_type = SelectionType::Field;
      FieldDelegate &field = m_fields[m_selection_index];
      field.FieldDelegateSelectLastElement();
      return eKeyHandled;
    }

    if (m_selection_type == SelectionType::NewButton) {
      m_selection_type = SelectionType::RemoveButton;
      m_selection_index = GetNumberOfFields() - 1;
      return eKeyHandled;
    }

    FieldDelegate &field = m_fields[m_selection_index];
    if (!field.FieldDelegateOnFirstOrOnlyElement()) {
      return field.FieldDelegateHandleChar(key);
    }

    field.FieldDelegateExitCallback();

    m_selection_type = SelectionType::RemoveButton;
    m_selection_index--;
    return eKeyHandled;
  }

  // If the last element of the field is selected and it didn't handle the key.
  // Select the next field or new button if the selected field is the last one.
  HandleCharResult SelectNextInList(int key) {
    assert(m_selection_type == SelectionType::Field);

    FieldDelegate &field = m_fields[m_selection_index];
    if (field.FieldDelegateHandleChar(key) == eKeyHandled)
      return eKeyHandled;

    if (!field.FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    field.FieldDelegateExitCallback();

    if (m_selection_index == GetNumberOfFields() - 1) {
      m_selection_type = SelectionType::NewButton;
      return eKeyHandled;
    }

    m_selection_index++;
    FieldDelegate &next_field = m_fields[m_selection_index];
    next_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      switch (m_selection_type) {
      case SelectionType::NewButton:
        AddNewField();
        return eKeyHandled;
      case SelectionType::RemoveButton:
        RemoveField();
        return eKeyHandled;
      case SelectionType::Field:
        return SelectNextInList(key);
      }
      break;
    case '\t':
      return SelectNext(key);
    case KEY_SHIFT_TAB:
      return SelectPrevious(key);
    default:
      break;
    }

    // If the key wasn't handled and one of the fields is selected, pass the key
    // to that field.
    if (m_selection_type == SelectionType::Field) {
      return m_fields[m_selection_index].FieldDelegateHandleChar(key);
    }

    return eKeyNotHandled;
  }

  bool FieldDelegateOnLastOrOnlyElement() override {
    if (m_selection_type == SelectionType::NewButton) {
      return true;
    }
    return false;
  }

  bool FieldDelegateOnFirstOrOnlyElement() override {
    if (m_selection_type == SelectionType::NewButton &&
        GetNumberOfFields() == 0)
      return true;

    if (m_selection_type == SelectionType::Field && m_selection_index == 0) {
      FieldDelegate &field = m_fields[m_selection_index];
      return field.FieldDelegateOnFirstOrOnlyElement();
    }

    return false;
  }

  void FieldDelegateSelectFirstElement() override {
    if (GetNumberOfFields() == 0) {
      m_selection_type = SelectionType::NewButton;
      return;
    }

    m_selection_type = SelectionType::Field;
    m_selection_index = 0;
  }

  void FieldDelegateSelectLastElement() override {
    m_selection_type = SelectionType::NewButton;
  }

  int GetNumberOfFields() { return m_fields.size(); }

  // Returns the form delegate at the current index.
  T &GetField(int index) { return m_fields[index]; }

protected:
  std::string m_label;
  // The default field delegate instance from which new field delegates will be
  // created though a copy.
  T m_default_field;
  std::vector<T> m_fields;
  int m_selection_index = 0;
  // See SelectionType class enum.
  SelectionType m_selection_type;
};

class ArgumentsFieldDelegate : public ListFieldDelegate<TextFieldDelegate> {
public:
  ArgumentsFieldDelegate()
      : ListFieldDelegate("Arguments",
                          TextFieldDelegate("Argument", "", false)) {}

  Args GetArguments() {
    Args arguments;
    for (int i = 0; i < GetNumberOfFields(); i++) {
      arguments.AppendArgument(GetField(i).GetText());
    }
    return arguments;
  }

  void AddArguments(const Args &arguments) {
    for (size_t i = 0; i < arguments.GetArgumentCount(); i++) {
      AddNewField();
      TextFieldDelegate &field = GetField(GetNumberOfFields() - 1);
      field.SetText(arguments.GetArgumentAtIndex(i));
    }
  }
};

template <class KeyFieldDelegateType, class ValueFieldDelegateType>
class MappingFieldDelegate : public FieldDelegate {
public:
  MappingFieldDelegate(KeyFieldDelegateType key_field,
                       ValueFieldDelegateType value_field)
      : m_key_field(key_field), m_value_field(value_field),
        m_selection_type(SelectionType::Key) {}

  // Signify which element is selected. The key field or its value field.
  enum class SelectionType { Key, Value };

  // A mapping field is drawn as two text fields with a right arrow in between.
  // The first field stores the key of the mapping and the second stores the
  // value if the mapping.
  //
  // __[Key]_____________   __[Value]___________
  // |                  | > |                  |
  // |__________________|   |__________________|
  // - Error message if it exists.

  // The mapping field has a height that is equal to the maximum height between
  // the key and value fields.
  int FieldDelegateGetHeight() override {
    return std::max(m_key_field.FieldDelegateGetHeight(),
                    m_value_field.FieldDelegateGetHeight());
  }

  void DrawArrow(Surface &surface) {
    surface.MoveCursor(0, 1);
    surface.PutChar(ACS_RARROW);
  }

  void FieldDelegateDraw(Surface &surface, bool is_selected) override {
    Rect bounds = surface.GetFrame();
    Rect key_field_bounds, arrow_and_value_field_bounds;
    bounds.VerticalSplit(bounds.size.width / 2, key_field_bounds,
                         arrow_and_value_field_bounds);
    Rect arrow_bounds, value_field_bounds;
    arrow_and_value_field_bounds.VerticalSplit(1, arrow_bounds,
                                               value_field_bounds);

    Surface key_field_surface = surface.SubSurface(key_field_bounds);
    Surface arrow_surface = surface.SubSurface(arrow_bounds);
    Surface value_field_surface = surface.SubSurface(value_field_bounds);

    bool key_is_selected =
        m_selection_type == SelectionType::Key && is_selected;
    m_key_field.FieldDelegateDraw(key_field_surface, key_is_selected);
    DrawArrow(arrow_surface);
    bool value_is_selected =
        m_selection_type == SelectionType::Value && is_selected;
    m_value_field.FieldDelegateDraw(value_field_surface, value_is_selected);
  }

  HandleCharResult SelectNext(int key) {
    if (FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    if (!m_key_field.FieldDelegateOnLastOrOnlyElement()) {
      return m_key_field.FieldDelegateHandleChar(key);
    }

    m_key_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Value;
    m_value_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult SelectPrevious(int key) {
    if (FieldDelegateOnFirstOrOnlyElement())
      return eKeyNotHandled;

    if (!m_value_field.FieldDelegateOnFirstOrOnlyElement()) {
      return m_value_field.FieldDelegateHandleChar(key);
    }

    m_value_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Key;
    m_key_field.FieldDelegateSelectLastElement();
    return eKeyHandled;
  }

  // If the value field is selected, pass the key to it. If the key field is
  // selected, its last element is selected, and it didn't handle the key, then
  // select its corresponding value field.
  HandleCharResult SelectNextField(int key) {
    if (m_selection_type == SelectionType::Value) {
      return m_value_field.FieldDelegateHandleChar(key);
    }

    if (m_key_field.FieldDelegateHandleChar(key) == eKeyHandled)
      return eKeyHandled;

    if (!m_key_field.FieldDelegateOnLastOrOnlyElement())
      return eKeyNotHandled;

    m_key_field.FieldDelegateExitCallback();
    m_selection_type = SelectionType::Value;
    m_value_field.FieldDelegateSelectFirstElement();
    return eKeyHandled;
  }

  HandleCharResult FieldDelegateHandleChar(int key) override {
    switch (key) {
    case KEY_RETURN:
      return SelectNextField(key);
    case '\t':
      return SelectNext(key);
    case KEY_SHIFT_TAB:
      return SelectPrevious(key);
    default:
      break;
    }

    // If the key wasn't handled, pass the key to the selected field.
    if (m_selection_type == SelectionType::Key)
      return m_key_field.FieldDelegateHandleChar(key);
    else
      return m_value_field.FieldDelegateHandleChar(key);

    return eKeyNotHandled;
  }

  bool FieldDelegateOnFirstOrOnlyElement() override {
    return m_selection_type == SelectionType::Key;
  }

  bool FieldDelegateOnLastOrOnlyElement() override {
    return m_selection_type == SelectionType::Value;
  }

  void FieldDelegateSelectFirstElement() override {
    m_selection_type = SelectionType::Key;
  }

  void FieldDelegateSelectLastElement() override {
    m_selection_type = SelectionType::Value;
  }

  bool FieldDelegateHasError() override {
    return m_key_field.FieldDelegateHasError() ||
           m_value_field.FieldDelegateHasError();
  }

  KeyFieldDelegateType &GetKeyField() { return m_key_field; }

  ValueFieldDelegateType &GetValueField() { return m_value_field; }

protected:
  KeyFieldDelegateType m_key_field;
  ValueFieldDelegateType m_value_field;
  // See SelectionType class enum.
  SelectionType m_selection_type;
};

class EnvironmentVariableNameFieldDelegate : public TextFieldDelegate {
public:
  EnvironmentVariableNameFieldDelegate(const char *content)
      : TextFieldDelegate("Name", content, true) {}

  // Environment variable names can't contain an equal sign.
  bool IsAcceptableChar(int key) override {
    return TextFieldDelegate::IsAcceptableChar(key) && key != '=';
  }

  const std::string &GetName() { return m_content; }
};

class EnvironmentVariableFieldDelegate
    : public MappingFieldDelegate<EnvironmentVariableNameFieldDelegate,
                                  TextFieldDelegate> {
public:
  EnvironmentVariableFieldDelegate()
      : MappingFieldDelegate(
            EnvironmentVariableNameFieldDelegate(""),
            TextFieldDelegate("Value", "", /*required=*/false)) {}

  const std::string &GetName() { return GetKeyField().GetName(); }

  const std::string &GetValue() { return GetValueField().GetText(); }

  void SetName(const char *name) { return GetKeyField().SetText(name); }

  void SetValue(const char *value) { return GetValueField().SetText(value); }
};

class EnvironmentVariableListFieldDelegate
    : public ListFieldDelegate<EnvironmentVariableFieldDelegate> {
public:
  EnvironmentVariableListFieldDelegate(const char *label)
      : ListFieldDelegate(label, EnvironmentVariableFieldDelegate()) {}

  Environment GetEnvironment() {
    Environment environment;
    for (int i = 0; i < GetNumberOfFields(); i++) {
      environment.insert(
          std::make_pair(GetField(i).GetName(), GetField(i).GetValue()));
    }
    return environment;
  }

  void AddEnvironmentVariables(const Environment &environment) {
    for (auto &variable : environment) {
      AddNewField();
      EnvironmentVariableFieldDelegate &field =
          GetField(GetNumberOfFields() - 1);
      field.SetName(variable.getKey().str().c_str());
      field.SetValue(variable.getValue().c_str());
    }
  }
};

class FormAction {
public:
  FormAction(const char *label, std::function<void(Window &)> action)
      : m_action(action) {
    if (label)
      m_label = label;
  }

  // Draw a centered [Label].
  void Draw(Surface &surface, bool is_selected) {
    int x = (surface.GetWidth() - m_label.length()) / 2;
    surface.MoveCursor(x, 0);
    if (is_selected)
      surface.AttributeOn(A_REVERSE);
    surface.PutChar('[');
    surface.PutCString(m_label.c_str());
    surface.PutChar(']');
    if (is_selected)
      surface.AttributeOff(A_REVERSE);
  }

  void Execute(Window &window) { m_action(window); }

  const std::string &GetLabel() { return m_label; }

protected:
  std::string m_label;
  std::function<void(Window &)> m_action;
};

class FormDelegate {
public:
  FormDelegate() = default;

  virtual ~FormDelegate() = default;

  virtual std::string GetName() = 0;

  virtual void UpdateFieldsVisibility() {}

  FieldDelegate *GetField(uint32_t field_index) {
    if (field_index < m_fields.size())
      return m_fields[field_index].get();
    return nullptr;
  }

  FormAction &GetAction(int action_index) { return m_actions[action_index]; }

  int GetNumberOfFields() { return m_fields.size(); }

  int GetNumberOfActions() { return m_actions.size(); }

  bool HasError() { return !m_error.empty(); }

  void ClearError() { m_error.clear(); }

  const std::string &GetError() { return m_error; }

  void SetError(const char *error) { m_error = error; }

  // If all fields are valid, true is returned. Otherwise, an error message is
  // set and false is returned. This method is usually called at the start of an
  // action that requires valid fields.
  bool CheckFieldsValidity() {
    for (int i = 0; i < GetNumberOfFields(); i++) {
      GetField(i)->FieldDelegateExitCallback();
      if (GetField(i)->FieldDelegateHasError()) {
        SetError("Some fields are invalid!");
        return false;
      }
    }
    return true;
  }

  // Factory methods to create and add fields of specific types.

  TextFieldDelegate *AddTextField(const char *label, const char *content,
                                  bool required) {
    TextFieldDelegate *delegate =
        new TextFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  FileFieldDelegate *AddFileField(const char *label, const char *content,
                                  bool need_to_exist, bool required) {
    FileFieldDelegate *delegate =
        new FileFieldDelegate(label, content, need_to_exist, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  DirectoryFieldDelegate *AddDirectoryField(const char *label,
                                            const char *content,
                                            bool need_to_exist, bool required) {
    DirectoryFieldDelegate *delegate =
        new DirectoryFieldDelegate(label, content, need_to_exist, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ArchFieldDelegate *AddArchField(const char *label, const char *content,
                                  bool required) {
    ArchFieldDelegate *delegate =
        new ArchFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  IntegerFieldDelegate *AddIntegerField(const char *label, int content,
                                        bool required) {
    IntegerFieldDelegate *delegate =
        new IntegerFieldDelegate(label, content, required);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  BooleanFieldDelegate *AddBooleanField(const char *label, bool content) {
    BooleanFieldDelegate *delegate = new BooleanFieldDelegate(label, content);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  LazyBooleanFieldDelegate *AddLazyBooleanField(const char *label,
                                                const char *calculate_label) {
    LazyBooleanFieldDelegate *delegate =
        new LazyBooleanFieldDelegate(label, calculate_label);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ChoicesFieldDelegate *AddChoicesField(const char *label, int height,
                                        std::vector<std::string> choices) {
    ChoicesFieldDelegate *delegate =
        new ChoicesFieldDelegate(label, height, choices);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  PlatformPluginFieldDelegate *AddPlatformPluginField(Debugger &debugger) {
    PlatformPluginFieldDelegate *delegate =
        new PlatformPluginFieldDelegate(debugger);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ProcessPluginFieldDelegate *AddProcessPluginField() {
    ProcessPluginFieldDelegate *delegate = new ProcessPluginFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  template <class T>
  ListFieldDelegate<T> *AddListField(const char *label, T default_field) {
    ListFieldDelegate<T> *delegate =
        new ListFieldDelegate<T>(label, default_field);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  ArgumentsFieldDelegate *AddArgumentsField() {
    ArgumentsFieldDelegate *delegate = new ArgumentsFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  template <class K, class V>
  MappingFieldDelegate<K, V> *AddMappingField(K key_field, V value_field) {
    MappingFieldDelegate<K, V> *delegate =
        new MappingFieldDelegate<K, V>(key_field, value_field);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableNameFieldDelegate *
  AddEnvironmentVariableNameField(const char *content) {
    EnvironmentVariableNameFieldDelegate *delegate =
        new EnvironmentVariableNameFieldDelegate(content);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableFieldDelegate *AddEnvironmentVariableField() {
    EnvironmentVariableFieldDelegate *delegate =
        new EnvironmentVariableFieldDelegate();
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  EnvironmentVariableListFieldDelegate *
  AddEnvironmentVariableListField(const char *label) {
    EnvironmentVariableListFieldDelegate *delegate =
        new EnvironmentVariableListFieldDelegate(label);
    m_fields.push_back(FieldDelegateUP(delegate));
    return delegate;
  }

  // Factory methods for adding actions.

  void AddAction(const char *label, std::function<void(Window &)> action) {
    m_actions.push_back(FormAction(label, action));
  }

protected:
  std::vector<FieldDelegateUP> m_fields;
  std::vector<FormAction> m_actions;
  // Optional error message. If empty, form is considered to have no error.
  std::string m_error;
};

typedef std::shared_ptr<FormDelegate> FormDelegateSP;

class FormWindowDelegate : public WindowDelegate {
public:
  FormWindowDelegate(FormDelegateSP &delegate_sp) : m_delegate_sp(delegate_sp) {
    assert(m_delegate_sp->GetNumberOfActions() > 0);
    if (m_delegate_sp->GetNumberOfFields() > 0)
      m_selection_type = SelectionType::Field;
    else
      m_selection_type = SelectionType::Action;
  }

  // Signify which element is selected. If a field or an action is selected,
  // then m_selection_index signifies the particular field or action that is
  // selected.
  enum class SelectionType { Field, Action };

  // A form window is padded by one character from all sides. First, if an error
  // message exists, it is drawn followed by a separator. Then one or more
  // fields are drawn. Finally, all available actions are drawn on a single
  // line.
  //
  // ___<Form Name>_________________________________________________
  // |                                                             |
  // | - Error message if it exists.                               |
  // |-------------------------------------------------------------|
  // | Form elements here.                                         |
  // |                       Form actions here.                    |
  // |                                                             |
  // |______________________________________[Press Esc to cancel]__|
  //

  // One line for the error and another for the horizontal line.
  int GetErrorHeight() {
    if (m_delegate_sp->HasError())
      return 2;
    return 0;
  }

  // Actions span a single line.
  int GetActionsHeight() {
    if (m_delegate_sp->GetNumberOfActions() > 0)
      return 1;
    return 0;
  }

  // Get the total number of needed lines to draw the contents.
  int GetContentHeight() {
    int height = 0;
    height += GetErrorHeight();
    for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
      if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
        continue;
      height += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
    }
    height += GetActionsHeight();
    return height;
  }

  ScrollContext GetScrollContext() {
    if (m_selection_type == SelectionType::Action)
      return ScrollContext(GetContentHeight() - 1);

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    ScrollContext context = field->FieldDelegateGetScrollContext();

    int offset = GetErrorHeight();
    for (int i = 0; i < m_selection_index; i++) {
      if (!m_delegate_sp->GetField(i)->FieldDelegateIsVisible())
        continue;
      offset += m_delegate_sp->GetField(i)->FieldDelegateGetHeight();
    }
    context.Offset(offset);

    // If the context is touching the error, include the error in the context as
    // well.
    if (context.start == GetErrorHeight())
      context.start = 0;

    return context;
  }

  void UpdateScrolling(Surface &surface) {
    ScrollContext context = GetScrollContext();
    int content_height = GetContentHeight();
    int surface_height = surface.GetHeight();
    int visible_height = std::min(content_height, surface_height);
    int last_visible_line = m_first_visible_line + visible_height - 1;

    // If the last visible line is bigger than the content, then it is invalid
    // and needs to be set to the last line in the content. This can happen when
    // a field has shrunk in height.
    if (last_visible_line > content_height - 1) {
      m_first_visible_line = content_height - visible_height;
    }

    if (context.start < m_first_visible_line) {
      m_first_visible_line = context.start;
      return;
    }

    if (context.end > last_visible_line) {
      m_first_visible_line = context.end - visible_height + 1;
    }
  }

  void DrawError(Surface &surface) {
    if (!m_delegate_sp->HasError())
      return;
    surface.MoveCursor(0, 0);
    surface.AttributeOn(COLOR_PAIR(RedOnBlack));
    surface.PutChar(ACS_DIAMOND);
    surface.PutChar(' ');
    surface.PutCStringTruncated(1, m_delegate_sp->GetError().c_str());
    surface.AttributeOff(COLOR_PAIR(RedOnBlack));

    surface.MoveCursor(0, 1);
    surface.HorizontalLine(surface.GetWidth());
  }

  void DrawFields(Surface &surface) {
    int line = 0;
    int width = surface.GetWidth();
    bool a_field_is_selected = m_selection_type == SelectionType::Field;
    for (int i = 0; i < m_delegate_sp->GetNumberOfFields(); i++) {
      FieldDelegate *field = m_delegate_sp->GetField(i);
      if (!field->FieldDelegateIsVisible())
        continue;
      bool is_field_selected = a_field_is_selected && m_selection_index == i;
      int height = field->FieldDelegateGetHeight();
      Rect bounds = Rect(Point(0, line), Size(width, height));
      Surface field_surface = surface.SubSurface(bounds);
      field->FieldDelegateDraw(field_surface, is_field_selected);
      line += height;
    }
  }

  void DrawActions(Surface &surface) {
    int number_of_actions = m_delegate_sp->GetNumberOfActions();
    int width = surface.GetWidth() / number_of_actions;
    bool an_action_is_selected = m_selection_type == SelectionType::Action;
    int x = 0;
    for (int i = 0; i < number_of_actions; i++) {
      bool is_action_selected = an_action_is_selected && m_selection_index == i;
      FormAction &action = m_delegate_sp->GetAction(i);
      Rect bounds = Rect(Point(x, 0), Size(width, 1));
      Surface action_surface = surface.SubSurface(bounds);
      action.Draw(action_surface, is_action_selected);
      x += width;
    }
  }

  void DrawElements(Surface &surface) {
    Rect frame = surface.GetFrame();
    Rect fields_bounds, actions_bounds;
    frame.HorizontalSplit(surface.GetHeight() - GetActionsHeight(),
                          fields_bounds, actions_bounds);
    Surface fields_surface = surface.SubSurface(fields_bounds);
    Surface actions_surface = surface.SubSurface(actions_bounds);

    DrawFields(fields_surface);
    DrawActions(actions_surface);
  }

  // Contents are first drawn on a pad. Then a subset of that pad is copied to
  // the derived window starting at the first visible line. This essentially
  // provides scrolling functionality.
  void DrawContent(Surface &surface) {
    UpdateScrolling(surface);

    int width = surface.GetWidth();
    int height = GetContentHeight();
    Pad pad = Pad(Size(width, height));

    Rect frame = pad.GetFrame();
    Rect error_bounds, elements_bounds;
    frame.HorizontalSplit(GetErrorHeight(), error_bounds, elements_bounds);
    Surface error_surface = pad.SubSurface(error_bounds);
    Surface elements_surface = pad.SubSurface(elements_bounds);

    DrawError(error_surface);
    DrawElements(elements_surface);

    int copy_height = std::min(surface.GetHeight(), pad.GetHeight());
    pad.CopyToSurface(surface, Point(0, m_first_visible_line), Point(),
                      Size(width, copy_height));
  }

  void DrawSubmitHint(Surface &surface, bool is_active) {
    surface.MoveCursor(2, surface.GetHeight() - 1);
    if (is_active)
      surface.AttributeOn(A_BOLD | COLOR_PAIR(BlackOnWhite));
    surface.Printf("[Press Alt+Enter to %s]",
                   m_delegate_sp->GetAction(0).GetLabel().c_str());
    if (is_active)
      surface.AttributeOff(A_BOLD | COLOR_PAIR(BlackOnWhite));
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_delegate_sp->UpdateFieldsVisibility();

    window.Erase();

    window.DrawTitleBox(m_delegate_sp->GetName().c_str(),
                        "Press Esc to Cancel");
    DrawSubmitHint(window, window.IsActive());

    Rect content_bounds = window.GetFrame();
    content_bounds.Inset(2, 2);
    Surface content_surface = window.SubSurface(content_bounds);

    DrawContent(content_surface);
    return true;
  }

  void SkipNextHiddenFields() {
    while (true) {
      if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
        return;

      if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
        m_selection_type = SelectionType::Action;
        m_selection_index = 0;
        return;
      }

      m_selection_index++;
    }
  }

  HandleCharResult SelectNext(int key) {
    if (m_selection_type == SelectionType::Action) {
      if (m_selection_index < m_delegate_sp->GetNumberOfActions() - 1) {
        m_selection_index++;
        return eKeyHandled;
      }

      m_selection_index = 0;
      m_selection_type = SelectionType::Field;
      SkipNextHiddenFields();
      if (m_selection_type == SelectionType::Field) {
        FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
        next_field->FieldDelegateSelectFirstElement();
      }
      return eKeyHandled;
    }

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    if (!field->FieldDelegateOnLastOrOnlyElement()) {
      return field->FieldDelegateHandleChar(key);
    }

    field->FieldDelegateExitCallback();

    if (m_selection_index == m_delegate_sp->GetNumberOfFields() - 1) {
      m_selection_type = SelectionType::Action;
      m_selection_index = 0;
      return eKeyHandled;
    }

    m_selection_index++;
    SkipNextHiddenFields();

    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *next_field = m_delegate_sp->GetField(m_selection_index);
      next_field->FieldDelegateSelectFirstElement();
    }

    return eKeyHandled;
  }

  void SkipPreviousHiddenFields() {
    while (true) {
      if (m_delegate_sp->GetField(m_selection_index)->FieldDelegateIsVisible())
        return;

      if (m_selection_index == 0) {
        m_selection_type = SelectionType::Action;
        m_selection_index = 0;
        return;
      }

      m_selection_index--;
    }
  }

  HandleCharResult SelectPrevious(int key) {
    if (m_selection_type == SelectionType::Action) {
      if (m_selection_index > 0) {
        m_selection_index--;
        return eKeyHandled;
      }
      m_selection_index = m_delegate_sp->GetNumberOfFields() - 1;
      m_selection_type = SelectionType::Field;
      SkipPreviousHiddenFields();
      if (m_selection_type == SelectionType::Field) {
        FieldDelegate *previous_field =
            m_delegate_sp->GetField(m_selection_index);
        previous_field->FieldDelegateSelectLastElement();
      }
      return eKeyHandled;
    }

    FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
    if (!field->FieldDelegateOnFirstOrOnlyElement()) {
      return field->FieldDelegateHandleChar(key);
    }

    field->FieldDelegateExitCallback();

    if (m_selection_index == 0) {
      m_selection_type = SelectionType::Action;
      m_selection_index = m_delegate_sp->GetNumberOfActions() - 1;
      return eKeyHandled;
    }

    m_selection_index--;
    SkipPreviousHiddenFields();

    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *previous_field =
          m_delegate_sp->GetField(m_selection_index);
      previous_field->FieldDelegateSelectLastElement();
    }

    return eKeyHandled;
  }

  void ExecuteAction(Window &window, int index) {
    FormAction &action = m_delegate_sp->GetAction(index);
    action.Execute(window);
    if (m_delegate_sp->HasError()) {
      m_first_visible_line = 0;
      m_selection_index = 0;
      m_selection_type = SelectionType::Field;
    }
  }

  // Always return eKeyHandled to absorb all events since forms are always
  // added as pop-ups that should take full control until canceled or submitted.
  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      if (m_selection_type == SelectionType::Action) {
        ExecuteAction(window, m_selection_index);
        return eKeyHandled;
      }
      break;
    case KEY_ALT_ENTER:
      ExecuteAction(window, 0);
      return eKeyHandled;
    case '\t':
      SelectNext(key);
      return eKeyHandled;
    case KEY_SHIFT_TAB:
      SelectPrevious(key);
      return eKeyHandled;
    case KEY_ESCAPE:
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;
    default:
      break;
    }

    // If the key wasn't handled and one of the fields is selected, pass the key
    // to that field.
    if (m_selection_type == SelectionType::Field) {
      FieldDelegate *field = m_delegate_sp->GetField(m_selection_index);
      if (field->FieldDelegateHandleChar(key) == eKeyHandled)
        return eKeyHandled;
    }

    // If the key wasn't handled by the possibly selected field, handle some
    // extra keys for navigation.
    switch (key) {
    case KEY_DOWN:
      SelectNext(key);
      return eKeyHandled;
    case KEY_UP:
      SelectPrevious(key);
      return eKeyHandled;
    default:
      break;
    }

    return eKeyHandled;
  }

protected:
  FormDelegateSP m_delegate_sp;
  // The index of the currently selected SelectionType.
  int m_selection_index = 0;
  // See SelectionType class enum.
  SelectionType m_selection_type;
  // The first visible line from the pad.
  int m_first_visible_line = 0;
};

///////////////////////////
// Form Delegate Instances
///////////////////////////

class DetachOrKillProcessFormDelegate : public FormDelegate {
public:
  DetachOrKillProcessFormDelegate(Process *process) : m_process(process) {
    SetError("There is a running process, either detach or kill it.");

    m_keep_stopped_field =
        AddBooleanField("Keep process stopped when detaching.", false);

    AddAction("Detach", [this](Window &window) { Detach(window); });
    AddAction("Kill", [this](Window &window) { Kill(window); });
  }

  std::string GetName() override { return "Detach/Kill Process"; }

  void Kill(Window &window) {
    Status destroy_status(m_process->Destroy(false));
    if (destroy_status.Fail()) {
      SetError("Failed to kill process.");
      return;
    }
    window.GetParent()->RemoveSubWindow(&window);
  }

  void Detach(Window &window) {
    Status detach_status(m_process->Detach(m_keep_stopped_field->GetBoolean()));
    if (detach_status.Fail()) {
      SetError("Failed to detach from process.");
      return;
    }
    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Process *m_process;
  BooleanFieldDelegate *m_keep_stopped_field;
};

class ProcessAttachFormDelegate : public FormDelegate {
public:
  ProcessAttachFormDelegate(Debugger &debugger, WindowSP main_window_sp)
      : m_debugger(debugger), m_main_window_sp(main_window_sp) {
    std::vector<std::string> types;
    types.push_back(std::string("Name"));
    types.push_back(std::string("PID"));
    m_type_field = AddChoicesField("Attach By", 2, types);
    m_pid_field = AddIntegerField("PID", 0, true);
    m_name_field =
        AddTextField("Process Name", GetDefaultProcessName().c_str(), true);
    m_continue_field = AddBooleanField("Continue once attached.", false);
    m_wait_for_field = AddBooleanField("Wait for process to launch.", false);
    m_include_existing_field =
        AddBooleanField("Include existing processes.", false);
    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
    m_plugin_field = AddProcessPluginField();

    AddAction("Attach", [this](Window &window) { Attach(window); });
  }

  std::string GetName() override { return "Attach Process"; }

  void UpdateFieldsVisibility() override {
    if (m_type_field->GetChoiceContent() == "Name") {
      m_pid_field->FieldDelegateHide();
      m_name_field->FieldDelegateShow();
      m_wait_for_field->FieldDelegateShow();
      if (m_wait_for_field->GetBoolean())
        m_include_existing_field->FieldDelegateShow();
      else
        m_include_existing_field->FieldDelegateHide();
    } else {
      m_pid_field->FieldDelegateShow();
      m_name_field->FieldDelegateHide();
      m_wait_for_field->FieldDelegateHide();
      m_include_existing_field->FieldDelegateHide();
    }
    if (m_show_advanced_field->GetBoolean())
      m_plugin_field->FieldDelegateShow();
    else
      m_plugin_field->FieldDelegateHide();
  }

  // Get the basename of the target's main executable if available, empty string
  // otherwise.
  std::string GetDefaultProcessName() {
    Target *target = m_debugger.GetSelectedTarget().get();
    if (target == nullptr)
      return "";

    ModuleSP module_sp = target->GetExecutableModule();
    if (!module_sp->IsExecutable())
      return "";

    return module_sp->GetFileSpec().GetFilename().AsCString();
  }

  bool StopRunningProcess() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();

    if (!exe_ctx.HasProcessScope())
      return false;

    Process *process = exe_ctx.GetProcessPtr();
    if (!(process && process->IsAlive()))
      return false;

    FormDelegateSP form_delegate_sp =
        FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
    Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
    WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
        form_delegate_sp->GetName().c_str(), bounds, true);
    WindowDelegateSP window_delegate_sp =
        WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
    form_window_sp->SetDelegate(window_delegate_sp);

    return true;
  }

  Target *GetTarget() {
    Target *target = m_debugger.GetSelectedTarget().get();

    if (target != nullptr)
      return target;

    TargetSP new_target_sp;
    m_debugger.GetTargetList().CreateTarget(
        m_debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);

    target = new_target_sp.get();

    if (target == nullptr)
      SetError("Failed to create target.");

    m_debugger.GetTargetList().SetSelectedTarget(new_target_sp);

    return target;
  }

  ProcessAttachInfo GetAttachInfo() {
    ProcessAttachInfo attach_info;
    attach_info.SetContinueOnceAttached(m_continue_field->GetBoolean());
    if (m_type_field->GetChoiceContent() == "Name") {
      attach_info.GetExecutableFile().SetFile(m_name_field->GetText(),
                                              FileSpec::Style::native);
      attach_info.SetWaitForLaunch(m_wait_for_field->GetBoolean());
      if (m_wait_for_field->GetBoolean())
        attach_info.SetIgnoreExisting(!m_include_existing_field->GetBoolean());
    } else {
      attach_info.SetProcessID(m_pid_field->GetInteger());
    }
    attach_info.SetProcessPluginName(m_plugin_field->GetPluginName());

    return attach_info;
  }

  void Attach(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    bool process_is_running = StopRunningProcess();
    if (process_is_running)
      return;

    Target *target = GetTarget();
    if (HasError())
      return;

    StreamString stream;
    ProcessAttachInfo attach_info = GetAttachInfo();
    Status status = target->Attach(attach_info, &stream);

    if (status.Fail()) {
      SetError(status.AsCString());
      return;
    }

    ProcessSP process_sp(target->GetProcessSP());
    if (!process_sp) {
      SetError("Attached sucessfully but target has no process.");
      return;
    }

    if (attach_info.GetContinueOnceAttached())
      process_sp->Resume();

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;
  WindowSP m_main_window_sp;

  ChoicesFieldDelegate *m_type_field;
  IntegerFieldDelegate *m_pid_field;
  TextFieldDelegate *m_name_field;
  BooleanFieldDelegate *m_continue_field;
  BooleanFieldDelegate *m_wait_for_field;
  BooleanFieldDelegate *m_include_existing_field;
  BooleanFieldDelegate *m_show_advanced_field;
  ProcessPluginFieldDelegate *m_plugin_field;
};

class TargetCreateFormDelegate : public FormDelegate {
public:
  TargetCreateFormDelegate(Debugger &debugger) : m_debugger(debugger) {
    m_executable_field = AddFileField("Executable", "", /*need_to_exist=*/true,
                                      /*required=*/true);
    m_core_file_field = AddFileField("Core File", "", /*need_to_exist=*/true,
                                     /*required=*/false);
    m_symbol_file_field = AddFileField(
        "Symbol File", "", /*need_to_exist=*/true, /*required=*/false);
    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);
    m_remote_file_field = AddFileField(
        "Remote File", "", /*need_to_exist=*/false, /*required=*/false);
    m_arch_field = AddArchField("Architecture", "", /*required=*/false);
    m_platform_field = AddPlatformPluginField(debugger);
    m_load_dependent_files_field =
        AddChoicesField("Load Dependents", 3, GetLoadDependentFilesChoices());

    AddAction("Create", [this](Window &window) { CreateTarget(window); });
  }

  std::string GetName() override { return "Create Target"; }

  void UpdateFieldsVisibility() override {
    if (m_show_advanced_field->GetBoolean()) {
      m_remote_file_field->FieldDelegateShow();
      m_arch_field->FieldDelegateShow();
      m_platform_field->FieldDelegateShow();
      m_load_dependent_files_field->FieldDelegateShow();
    } else {
      m_remote_file_field->FieldDelegateHide();
      m_arch_field->FieldDelegateHide();
      m_platform_field->FieldDelegateHide();
      m_load_dependent_files_field->FieldDelegateHide();
    }
  }

  static constexpr const char *kLoadDependentFilesNo = "No";
  static constexpr const char *kLoadDependentFilesYes = "Yes";
  static constexpr const char *kLoadDependentFilesExecOnly = "Executable only";

  std::vector<std::string> GetLoadDependentFilesChoices() {
    std::vector<std::string> load_dependents_options;
    load_dependents_options.push_back(kLoadDependentFilesExecOnly);
    load_dependents_options.push_back(kLoadDependentFilesYes);
    load_dependents_options.push_back(kLoadDependentFilesNo);
    return load_dependents_options;
  }

  LoadDependentFiles GetLoadDependentFiles() {
    std::string choice = m_load_dependent_files_field->GetChoiceContent();
    if (choice == kLoadDependentFilesNo)
      return eLoadDependentsNo;
    if (choice == kLoadDependentFilesYes)
      return eLoadDependentsYes;
    return eLoadDependentsDefault;
  }

  OptionGroupPlatform GetPlatformOptions() {
    OptionGroupPlatform platform_options(false);
    platform_options.SetPlatformName(m_platform_field->GetPluginName().c_str());
    return platform_options;
  }

  TargetSP GetTarget() {
    OptionGroupPlatform platform_options = GetPlatformOptions();
    TargetSP target_sp;
    Status status = m_debugger.GetTargetList().CreateTarget(
        m_debugger, m_executable_field->GetPath(),
        m_arch_field->GetArchString(), GetLoadDependentFiles(),
        &platform_options, target_sp);

    if (status.Fail()) {
      SetError(status.AsCString());
      return nullptr;
    }

    m_debugger.GetTargetList().SetSelectedTarget(target_sp);

    return target_sp;
  }

  void SetSymbolFile(TargetSP target_sp) {
    if (!m_symbol_file_field->IsSpecified())
      return;

    ModuleSP module_sp(target_sp->GetExecutableModule());
    if (!module_sp)
      return;

    module_sp->SetSymbolFileFileSpec(
        m_symbol_file_field->GetResolvedFileSpec());
  }

  void SetCoreFile(TargetSP target_sp) {
    if (!m_core_file_field->IsSpecified())
      return;

    FileSpec core_file_spec = m_core_file_field->GetResolvedFileSpec();

    FileSpec core_file_directory_spec;
    core_file_directory_spec.SetDirectory(core_file_spec.GetDirectory());
    target_sp->AppendExecutableSearchPaths(core_file_directory_spec);

    ProcessSP process_sp(target_sp->CreateProcess(
        m_debugger.GetListener(), llvm::StringRef(), &core_file_spec, false));

    if (!process_sp) {
      SetError("Unknown core file format!");
      return;
    }

    Status status = process_sp->LoadCore();
    if (status.Fail()) {
      SetError("Unknown core file format!");
      return;
    }
  }

  void SetRemoteFile(TargetSP target_sp) {
    if (!m_remote_file_field->IsSpecified())
      return;

    ModuleSP module_sp(target_sp->GetExecutableModule());
    if (!module_sp)
      return;

    FileSpec remote_file_spec = m_remote_file_field->GetFileSpec();
    module_sp->SetPlatformFileSpec(remote_file_spec);
  }

  void RemoveTarget(TargetSP target_sp) {
    m_debugger.GetTargetList().DeleteTarget(target_sp);
  }

  void CreateTarget(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    TargetSP target_sp = GetTarget();
    if (HasError())
      return;

    SetSymbolFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    SetCoreFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    SetRemoteFile(target_sp);
    if (HasError()) {
      RemoveTarget(target_sp);
      return;
    }

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;

  FileFieldDelegate *m_executable_field;
  FileFieldDelegate *m_core_file_field;
  FileFieldDelegate *m_symbol_file_field;
  BooleanFieldDelegate *m_show_advanced_field;
  FileFieldDelegate *m_remote_file_field;
  ArchFieldDelegate *m_arch_field;
  PlatformPluginFieldDelegate *m_platform_field;
  ChoicesFieldDelegate *m_load_dependent_files_field;
};

class ProcessLaunchFormDelegate : public FormDelegate {
public:
  ProcessLaunchFormDelegate(Debugger &debugger, WindowSP main_window_sp)
      : m_debugger(debugger), m_main_window_sp(main_window_sp) {

    m_arguments_field = AddArgumentsField();
    SetArgumentsFieldDefaultValue();
    m_target_environment_field =
        AddEnvironmentVariableListField("Target Environment Variables");
    SetTargetEnvironmentFieldDefaultValue();
    m_working_directory_field = AddDirectoryField(
        "Working Directory", GetDefaultWorkingDirectory().c_str(), true, false);

    m_show_advanced_field = AddBooleanField("Show advanced settings.", false);

    m_stop_at_entry_field = AddBooleanField("Stop at entry point.", false);
    m_detach_on_error_field =
        AddBooleanField("Detach on error.", GetDefaultDetachOnError());
    m_disable_aslr_field =
        AddBooleanField("Disable ASLR", GetDefaultDisableASLR());
    m_plugin_field = AddProcessPluginField();
    m_arch_field = AddArchField("Architecture", "", false);
    m_shell_field = AddFileField("Shell", "", true, false);
    m_expand_shell_arguments_field =
        AddBooleanField("Expand shell arguments.", false);

    m_disable_standard_io_field =
        AddBooleanField("Disable Standard IO", GetDefaultDisableStandardIO());
    m_standard_output_field =
        AddFileField("Standard Output File", "", /*need_to_exist=*/false,
                     /*required=*/false);
    m_standard_error_field =
        AddFileField("Standard Error File", "", /*need_to_exist=*/false,
                     /*required=*/false);
    m_standard_input_field =
        AddFileField("Standard Input File", "", /*need_to_exist=*/false,
                     /*required=*/false);

    m_show_inherited_environment_field =
        AddBooleanField("Show inherited environment variables.", false);
    m_inherited_environment_field =
        AddEnvironmentVariableListField("Inherited Environment Variables");
    SetInheritedEnvironmentFieldDefaultValue();

    AddAction("Launch", [this](Window &window) { Launch(window); });
  }

  std::string GetName() override { return "Launch Process"; }

  void UpdateFieldsVisibility() override {
    if (m_show_advanced_field->GetBoolean()) {
      m_stop_at_entry_field->FieldDelegateShow();
      m_detach_on_error_field->FieldDelegateShow();
      m_disable_aslr_field->FieldDelegateShow();
      m_plugin_field->FieldDelegateShow();
      m_arch_field->FieldDelegateShow();
      m_shell_field->FieldDelegateShow();
      m_expand_shell_arguments_field->FieldDelegateShow();
      m_disable_standard_io_field->FieldDelegateShow();
      if (m_disable_standard_io_field->GetBoolean()) {
        m_standard_input_field->FieldDelegateHide();
        m_standard_output_field->FieldDelegateHide();
        m_standard_error_field->FieldDelegateHide();
      } else {
        m_standard_input_field->FieldDelegateShow();
        m_standard_output_field->FieldDelegateShow();
        m_standard_error_field->FieldDelegateShow();
      }
      m_show_inherited_environment_field->FieldDelegateShow();
      if (m_show_inherited_environment_field->GetBoolean())
        m_inherited_environment_field->FieldDelegateShow();
      else
        m_inherited_environment_field->FieldDelegateHide();
    } else {
      m_stop_at_entry_field->FieldDelegateHide();
      m_detach_on_error_field->FieldDelegateHide();
      m_disable_aslr_field->FieldDelegateHide();
      m_plugin_field->FieldDelegateHide();
      m_arch_field->FieldDelegateHide();
      m_shell_field->FieldDelegateHide();
      m_expand_shell_arguments_field->FieldDelegateHide();
      m_disable_standard_io_field->FieldDelegateHide();
      m_standard_input_field->FieldDelegateHide();
      m_standard_output_field->FieldDelegateHide();
      m_standard_error_field->FieldDelegateHide();
      m_show_inherited_environment_field->FieldDelegateHide();
      m_inherited_environment_field->FieldDelegateHide();
    }
  }

  // Methods for setting the default value of the fields.

  void SetArgumentsFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Args &target_arguments =
        target->GetProcessLaunchInfo().GetArguments();
    m_arguments_field->AddArguments(target_arguments);
  }

  void SetTargetEnvironmentFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Environment &target_environment = target->GetTargetEnvironment();
    m_target_environment_field->AddEnvironmentVariables(target_environment);
  }

  void SetInheritedEnvironmentFieldDefaultValue() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return;

    const Environment &inherited_environment =
        target->GetInheritedEnvironment();
    m_inherited_environment_field->AddEnvironmentVariables(
        inherited_environment);
  }

  std::string GetDefaultWorkingDirectory() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return "";

    PlatformSP platform = target->GetPlatform();
    return platform->GetWorkingDirectory().GetPath();
  }

  bool GetDefaultDisableASLR() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return false;

    return target->GetDisableASLR();
  }

  bool GetDefaultDisableStandardIO() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return true;

    return target->GetDisableSTDIO();
  }

  bool GetDefaultDetachOnError() {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (target == nullptr)
      return true;

    return target->GetDetachOnError();
  }

  // Methods for getting the necessary information and setting them to the
  // ProcessLaunchInfo.

  void GetExecutableSettings(ProcessLaunchInfo &launch_info) {
    TargetSP target = m_debugger.GetSelectedTarget();
    ModuleSP executable_module = target->GetExecutableModule();
    llvm::StringRef target_settings_argv0 = target->GetArg0();

    if (!target_settings_argv0.empty()) {
      launch_info.GetArguments().AppendArgument(target_settings_argv0);
      launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
                                    false);
      return;
    }

    launch_info.SetExecutableFile(executable_module->GetPlatformFileSpec(),
                                  true);
  }

  void GetArguments(ProcessLaunchInfo &launch_info) {
    TargetSP target = m_debugger.GetSelectedTarget();
    Args arguments = m_arguments_field->GetArguments();
    launch_info.GetArguments().AppendArguments(arguments);
  }

  void GetEnvironment(ProcessLaunchInfo &launch_info) {
    Environment target_environment =
        m_target_environment_field->GetEnvironment();
    Environment inherited_environment =
        m_inherited_environment_field->GetEnvironment();
    launch_info.GetEnvironment().insert(target_environment.begin(),
                                        target_environment.end());
    launch_info.GetEnvironment().insert(inherited_environment.begin(),
                                        inherited_environment.end());
  }

  void GetWorkingDirectory(ProcessLaunchInfo &launch_info) {
    if (m_working_directory_field->IsSpecified())
      launch_info.SetWorkingDirectory(
          m_working_directory_field->GetResolvedFileSpec());
  }

  void GetStopAtEntry(ProcessLaunchInfo &launch_info) {
    if (m_stop_at_entry_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagStopAtEntry);
    else
      launch_info.GetFlags().Clear(eLaunchFlagStopAtEntry);
  }

  void GetDetachOnError(ProcessLaunchInfo &launch_info) {
    if (m_detach_on_error_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
    else
      launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
  }

  void GetDisableASLR(ProcessLaunchInfo &launch_info) {
    if (m_disable_aslr_field->GetBoolean())
      launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
    else
      launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
  }

  void GetPlugin(ProcessLaunchInfo &launch_info) {
    launch_info.SetProcessPluginName(m_plugin_field->GetPluginName());
  }

  void GetArch(ProcessLaunchInfo &launch_info) {
    if (!m_arch_field->IsSpecified())
      return;

    TargetSP target_sp = m_debugger.GetSelectedTarget();
    PlatformSP platform_sp =
        target_sp ? target_sp->GetPlatform() : PlatformSP();
    launch_info.GetArchitecture() = Platform::GetAugmentedArchSpec(
        platform_sp.get(), m_arch_field->GetArchString());
  }

  void GetShell(ProcessLaunchInfo &launch_info) {
    if (!m_shell_field->IsSpecified())
      return;

    launch_info.SetShell(m_shell_field->GetResolvedFileSpec());
    launch_info.SetShellExpandArguments(
        m_expand_shell_arguments_field->GetBoolean());
  }

  void GetStandardIO(ProcessLaunchInfo &launch_info) {
    if (m_disable_standard_io_field->GetBoolean()) {
      launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
      return;
    }

    FileAction action;
    if (m_standard_input_field->IsSpecified()) {
      if (action.Open(STDIN_FILENO, m_standard_input_field->GetFileSpec(), true,
                      false))
        launch_info.AppendFileAction(action);
    }
    if (m_standard_output_field->IsSpecified()) {
      if (action.Open(STDOUT_FILENO, m_standard_output_field->GetFileSpec(),
                      false, true))
        launch_info.AppendFileAction(action);
    }
    if (m_standard_error_field->IsSpecified()) {
      if (action.Open(STDERR_FILENO, m_standard_error_field->GetFileSpec(),
                      false, true))
        launch_info.AppendFileAction(action);
    }
  }

  void GetInheritTCC(ProcessLaunchInfo &launch_info) {
    if (m_debugger.GetSelectedTarget()->GetInheritTCC())
      launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
  }

  ProcessLaunchInfo GetLaunchInfo() {
    ProcessLaunchInfo launch_info;

    GetExecutableSettings(launch_info);
    GetArguments(launch_info);
    GetEnvironment(launch_info);
    GetWorkingDirectory(launch_info);
    GetStopAtEntry(launch_info);
    GetDetachOnError(launch_info);
    GetDisableASLR(launch_info);
    GetPlugin(launch_info);
    GetArch(launch_info);
    GetShell(launch_info);
    GetStandardIO(launch_info);
    GetInheritTCC(launch_info);

    return launch_info;
  }

  bool StopRunningProcess() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();

    if (!exe_ctx.HasProcessScope())
      return false;

    Process *process = exe_ctx.GetProcessPtr();
    if (!(process && process->IsAlive()))
      return false;

    FormDelegateSP form_delegate_sp =
        FormDelegateSP(new DetachOrKillProcessFormDelegate(process));
    Rect bounds = m_main_window_sp->GetCenteredRect(85, 8);
    WindowSP form_window_sp = m_main_window_sp->CreateSubWindow(
        form_delegate_sp->GetName().c_str(), bounds, true);
    WindowDelegateSP window_delegate_sp =
        WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
    form_window_sp->SetDelegate(window_delegate_sp);

    return true;
  }

  Target *GetTarget() {
    Target *target = m_debugger.GetSelectedTarget().get();

    if (target == nullptr) {
      SetError("No target exists!");
      return nullptr;
    }

    ModuleSP exe_module_sp = target->GetExecutableModule();

    if (exe_module_sp == nullptr) {
      SetError("No executable in target!");
      return nullptr;
    }

    return target;
  }

  void Launch(Window &window) {
    ClearError();

    bool all_fields_are_valid = CheckFieldsValidity();
    if (!all_fields_are_valid)
      return;

    bool process_is_running = StopRunningProcess();
    if (process_is_running)
      return;

    Target *target = GetTarget();
    if (HasError())
      return;

    StreamString stream;
    ProcessLaunchInfo launch_info = GetLaunchInfo();
    Status status = target->Launch(launch_info, &stream);

    if (status.Fail()) {
      SetError(status.AsCString());
      return;
    }

    ProcessSP process_sp(target->GetProcessSP());
    if (!process_sp) {
      SetError("Launched successfully but target has no process!");
      return;
    }

    window.GetParent()->RemoveSubWindow(&window);
  }

protected:
  Debugger &m_debugger;
  WindowSP m_main_window_sp;

  ArgumentsFieldDelegate *m_arguments_field;
  EnvironmentVariableListFieldDelegate *m_target_environment_field;
  DirectoryFieldDelegate *m_working_directory_field;

  BooleanFieldDelegate *m_show_advanced_field;

  BooleanFieldDelegate *m_stop_at_entry_field;
  BooleanFieldDelegate *m_detach_on_error_field;
  BooleanFieldDelegate *m_disable_aslr_field;
  ProcessPluginFieldDelegate *m_plugin_field;
  ArchFieldDelegate *m_arch_field;
  FileFieldDelegate *m_shell_field;
  BooleanFieldDelegate *m_expand_shell_arguments_field;
  BooleanFieldDelegate *m_disable_standard_io_field;
  FileFieldDelegate *m_standard_input_field;
  FileFieldDelegate *m_standard_output_field;
  FileFieldDelegate *m_standard_error_field;

  BooleanFieldDelegate *m_show_inherited_environment_field;
  EnvironmentVariableListFieldDelegate *m_inherited_environment_field;
};

////////////
// Searchers
////////////

class SearcherDelegate {
public:
  SearcherDelegate() = default;

  virtual ~SearcherDelegate() = default;

  virtual int GetNumberOfMatches() = 0;

  // Get the string that will be displayed for the match at the input index.
  virtual const std::string &GetMatchTextAtIndex(int index) = 0;

  // Update the matches of the search. This is executed every time the text
  // field handles an event.
  virtual void UpdateMatches(const std::string &text) = 0;

  // Execute the user callback given the index of some match. This is executed
  // once the user selects a match.
  virtual void ExecuteCallback(int match_index) = 0;
};

typedef std::shared_ptr<SearcherDelegate> SearcherDelegateSP;

class SearcherWindowDelegate : public WindowDelegate {
public:
  SearcherWindowDelegate(SearcherDelegateSP &delegate_sp)
      : m_delegate_sp(delegate_sp), m_text_field("Search", "", false) {
    ;
  }

  // A completion window is padded by one character from all sides. A text field
  // is first drawn for inputting the searcher request, then a list of matches
  // are displayed in a scrollable list.
  //
  // ___<Searcher Window Name>____________________________
  // |                                                   |
  // | __[Search]_______________________________________ |
  // | |                                               | |
  // | |_______________________________________________| |
  // | - Match 1.                                        |
  // | - Match 2.                                        |
  // | - ...                                             |
  // |                                                   |
  // |____________________________[Press Esc to Cancel]__|
  //

  // Get the index of the last visible match. Assuming at least one match
  // exists.
  int GetLastVisibleMatch(int height) {
    int index = m_first_visible_match + height;
    return std::min(index, m_delegate_sp->GetNumberOfMatches()) - 1;
  }

  int GetNumberOfVisibleMatches(int height) {
    return GetLastVisibleMatch(height) - m_first_visible_match + 1;
  }

  void UpdateScrolling(Surface &surface) {
    if (m_selected_match < m_first_visible_match) {
      m_first_visible_match = m_selected_match;
      return;
    }

    int height = surface.GetHeight();
    int last_visible_match = GetLastVisibleMatch(height);
    if (m_selected_match > last_visible_match) {
      m_first_visible_match = m_selected_match - height + 1;
    }
  }

  void DrawMatches(Surface &surface) {
    if (m_delegate_sp->GetNumberOfMatches() == 0)
      return;

    UpdateScrolling(surface);

    int count = GetNumberOfVisibleMatches(surface.GetHeight());
    for (int i = 0; i < count; i++) {
      surface.MoveCursor(1, i);
      int current_match = m_first_visible_match + i;
      if (current_match == m_selected_match)
        surface.AttributeOn(A_REVERSE);
      surface.PutCString(
          m_delegate_sp->GetMatchTextAtIndex(current_match).c_str());
      if (current_match == m_selected_match)
        surface.AttributeOff(A_REVERSE);
    }
  }

  void DrawContent(Surface &surface) {
    Rect content_bounds = surface.GetFrame();
    Rect text_field_bounds, matchs_bounds;
    content_bounds.HorizontalSplit(m_text_field.FieldDelegateGetHeight(),
                                   text_field_bounds, matchs_bounds);
    Surface text_field_surface = surface.SubSurface(text_field_bounds);
    Surface matches_surface = surface.SubSurface(matchs_bounds);

    m_text_field.FieldDelegateDraw(text_field_surface, true);
    DrawMatches(matches_surface);
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    window.Erase();

    window.DrawTitleBox(window.GetName(), "Press Esc to Cancel");

    Rect content_bounds = window.GetFrame();
    content_bounds.Inset(2, 2);
    Surface content_surface = window.SubSurface(content_bounds);

    DrawContent(content_surface);
    return true;
  }

  void SelectNext() {
    if (m_selected_match != m_delegate_sp->GetNumberOfMatches() - 1)
      m_selected_match++;
  }

  void SelectPrevious() {
    if (m_selected_match != 0)
      m_selected_match--;
  }

  void ExecuteCallback(Window &window) {
    m_delegate_sp->ExecuteCallback(m_selected_match);
    window.GetParent()->RemoveSubWindow(&window);
  }

  void UpdateMatches() {
    m_delegate_sp->UpdateMatches(m_text_field.GetText());
    m_selected_match = 0;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\r':
    case '\n':
    case KEY_ENTER:
      ExecuteCallback(window);
      return eKeyHandled;
    case '\t':
    case KEY_DOWN:
      SelectNext();
      return eKeyHandled;
    case KEY_SHIFT_TAB:
    case KEY_UP:
      SelectPrevious();
      return eKeyHandled;
    case KEY_ESCAPE:
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;
    default:
      break;
    }

    if (m_text_field.FieldDelegateHandleChar(key) == eKeyHandled)
      UpdateMatches();

    return eKeyHandled;
  }

protected:
  SearcherDelegateSP m_delegate_sp;
  TextFieldDelegate m_text_field;
  // The index of the currently selected match.
  int m_selected_match = 0;
  // The index of the first visible match.
  int m_first_visible_match = 0;
};

//////////////////////////////
// Searcher Delegate Instances
//////////////////////////////

// This is a searcher delegate wrapper around CommandCompletions common
// callbacks. The callbacks are only given the match string. The completion_mask
// can be a combination of lldb::CompletionType.
class CommonCompletionSearcherDelegate : public SearcherDelegate {
public:
  typedef std::function<void(const std::string &)> CallbackType;

  CommonCompletionSearcherDelegate(Debugger &debugger, uint32_t completion_mask,
                                   CallbackType callback)
      : m_debugger(debugger), m_completion_mask(completion_mask),
        m_callback(callback) {}

  int GetNumberOfMatches() override { return m_matches.GetSize(); }

  const std::string &GetMatchTextAtIndex(int index) override {
    return m_matches[index];
  }

  void UpdateMatches(const std::string &text) override {
    CompletionResult result;
    CompletionRequest request(text.c_str(), text.size(), result);
    lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
        m_debugger.GetCommandInterpreter(), m_completion_mask, request,
        nullptr);
    result.GetMatches(m_matches);
  }

  void ExecuteCallback(int match_index) override {
    m_callback(m_matches[match_index]);
  }

protected:
  Debugger &m_debugger;
  // A compound mask from lldb::CompletionType.
  uint32_t m_completion_mask;
  // A callback to execute once the user selects a match. The match is passed to
  // the callback as a string.
  CallbackType m_callback;
  StringList m_matches;
};

////////
// Menus
////////

class MenuDelegate {
public:
  virtual ~MenuDelegate() = default;

  virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0;
};

class Menu : public WindowDelegate {
public:
  enum class Type { Invalid, Bar, Item, Separator };

  // Menubar or separator constructor
  Menu(Type type);

  // Menuitem constructor
  Menu(const char *name, const char *key_name, int key_value,
       uint64_t identifier);

  ~Menu() override = default;

  const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; }

  void SetDelegate(const MenuDelegateSP &delegate_sp) {
    m_delegate_sp = delegate_sp;
  }

  void RecalculateNameLengths();

  void AddSubmenu(const MenuSP &menu_sp);

  int DrawAndRunMenu(Window &window);

  void DrawMenuTitle(Window &window, bool highlight);

  bool WindowDelegateDraw(Window &window, bool force) override;

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override;

  MenuActionResult ActionPrivate(Menu &menu) {
    MenuActionResult result = MenuActionResult::NotHandled;
    if (m_delegate_sp) {
      result = m_delegate_sp->MenuDelegateAction(menu);
      if (result != MenuActionResult::NotHandled)
        return result;
    } else if (m_parent) {
      result = m_parent->ActionPrivate(menu);
      if (result != MenuActionResult::NotHandled)
        return result;
    }
    return m_canned_result;
  }

  MenuActionResult Action() {
    // Call the recursive action so it can try to handle it with the menu
    // delegate, and if not, try our parent menu
    return ActionPrivate(*this);
  }

  void SetCannedResult(MenuActionResult result) { m_canned_result = result; }

  Menus &GetSubmenus() { return m_submenus; }

  const Menus &GetSubmenus() const { return m_submenus; }

  int GetSelectedSubmenuIndex() const { return m_selected; }

  void SetSelectedSubmenuIndex(int idx) { m_selected = idx; }

  Type GetType() const { return m_type; }

  int GetStartingColumn() const { return m_start_col; }

  void SetStartingColumn(int col) { m_start_col = col; }

  int GetKeyValue() const { return m_key_value; }

  std::string &GetName() { return m_name; }

  int GetDrawWidth() const {
    return m_max_submenu_name_length + m_max_submenu_key_name_length + 8;
  }

  uint64_t GetIdentifier() const { return m_identifier; }

  void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }

protected:
  std::string m_name;
  std::string m_key_name;
  uint64_t m_identifier;
  Type m_type;
  int m_key_value;
  int m_start_col;
  int m_max_submenu_name_length;
  int m_max_submenu_key_name_length;
  int m_selected;
  Menu *m_parent;
  Menus m_submenus;
  WindowSP m_menu_window_sp;
  MenuActionResult m_canned_result;
  MenuDelegateSP m_delegate_sp;
};

// Menubar or separator constructor
Menu::Menu(Type type)
    : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0),
      m_start_col(0), m_max_submenu_name_length(0),
      m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
      m_submenus(), m_canned_result(MenuActionResult::NotHandled),
      m_delegate_sp() {}

// Menuitem constructor
Menu::Menu(const char *name, const char *key_name, int key_value,
           uint64_t identifier)
    : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid),
      m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0),
      m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr),
      m_submenus(), m_canned_result(MenuActionResult::NotHandled),
      m_delegate_sp() {
  if (name && name[0]) {
    m_name = name;
    m_type = Type::Item;
    if (key_name && key_name[0])
      m_key_name = key_name;
  } else {
    m_type = Type::Separator;
  }
}

void Menu::RecalculateNameLengths() {
  m_max_submenu_name_length = 0;
  m_max_submenu_key_name_length = 0;
  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  for (size_t i = 0; i < num_submenus; ++i) {
    Menu *submenu = submenus[i].get();
    if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size())
      m_max_submenu_name_length = submenu->m_name.size();
    if (static_cast<size_t>(m_max_submenu_key_name_length) <
        submenu->m_key_name.size())
      m_max_submenu_key_name_length = submenu->m_key_name.size();
  }
}

void Menu::AddSubmenu(const MenuSP &menu_sp) {
  menu_sp->m_parent = this;
  if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size())
    m_max_submenu_name_length = menu_sp->m_name.size();
  if (static_cast<size_t>(m_max_submenu_key_name_length) <
      menu_sp->m_key_name.size())
    m_max_submenu_key_name_length = menu_sp->m_key_name.size();
  m_submenus.push_back(menu_sp);
}

void Menu::DrawMenuTitle(Window &window, bool highlight) {
  if (m_type == Type::Separator) {
    window.MoveCursor(0, window.GetCursorY());
    window.PutChar(ACS_LTEE);
    int width = window.GetWidth();
    if (width > 2) {
      width -= 2;
      for (int i = 0; i < width; ++i)
        window.PutChar(ACS_HLINE);
    }
    window.PutChar(ACS_RTEE);
  } else {
    const int shortcut_key = m_key_value;
    bool underlined_shortcut = false;
    const attr_t highlight_attr = A_REVERSE;
    if (highlight)
      window.AttributeOn(highlight_attr);
    if (llvm::isPrint(shortcut_key)) {
      size_t lower_pos = m_name.find(tolower(shortcut_key));
      size_t upper_pos = m_name.find(toupper(shortcut_key));
      const char *name = m_name.c_str();
      size_t pos = std::min<size_t>(lower_pos, upper_pos);
      if (pos != std::string::npos) {
        underlined_shortcut = true;
        if (pos > 0) {
          window.PutCString(name, pos);
          name += pos;
        }
        const attr_t shortcut_attr = A_UNDERLINE | A_BOLD;
        window.AttributeOn(shortcut_attr);
        window.PutChar(name[0]);
        window.AttributeOff(shortcut_attr);
        name++;
        if (name[0])
          window.PutCString(name);
      }
    }

    if (!underlined_shortcut) {
      window.PutCString(m_name.c_str());
    }

    if (highlight)
      window.AttributeOff(highlight_attr);

    if (m_key_name.empty()) {
      if (!underlined_shortcut && llvm::isPrint(m_key_value)) {
        window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
        window.Printf(" (%c)", m_key_value);
        window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
      }
    } else {
      window.AttributeOn(COLOR_PAIR(MagentaOnWhite));
      window.Printf(" (%s)", m_key_name.c_str());
      window.AttributeOff(COLOR_PAIR(MagentaOnWhite));
    }
  }
}

bool Menu::WindowDelegateDraw(Window &window, bool force) {
  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  const int selected_idx = GetSelectedSubmenuIndex();
  Menu::Type menu_type = GetType();
  switch (menu_type) {
  case Menu::Type::Bar: {
    window.SetBackground(BlackOnWhite);
    window.MoveCursor(0, 0);
    for (size_t i = 0; i < num_submenus; ++i) {
      Menu *menu = submenus[i].get();
      if (i > 0)
        window.PutChar(' ');
      menu->SetStartingColumn(window.GetCursorX());
      window.PutCString("| ");
      menu->DrawMenuTitle(window, false);
    }
    window.PutCString(" |");
  } break;

  case Menu::Type::Item: {
    int y = 1;
    int x = 3;
    // Draw the menu
    int cursor_x = 0;
    int cursor_y = 0;
    window.Erase();
    window.SetBackground(BlackOnWhite);
    window.Box();
    for (size_t i = 0; i < num_submenus; ++i) {
      const bool is_selected = (i == static_cast<size_t>(selected_idx));
      window.MoveCursor(x, y + i);
      if (is_selected) {
        // Remember where we want the cursor to be
        cursor_x = x - 1;
        cursor_y = y + i;
      }
      submenus[i]->DrawMenuTitle(window, is_selected);
    }
    window.MoveCursor(cursor_x, cursor_y);
  } break;

  default:
  case Menu::Type::Separator:
    break;
  }
  return true; // Drawing handled...
}

HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) {
  HandleCharResult result = eKeyNotHandled;

  Menus &submenus = GetSubmenus();
  const size_t num_submenus = submenus.size();
  const int selected_idx = GetSelectedSubmenuIndex();
  Menu::Type menu_type = GetType();
  if (menu_type == Menu::Type::Bar) {
    MenuSP run_menu_sp;
    switch (key) {
    case KEY_DOWN:
    case KEY_UP:
      // Show last menu or first menu
      if (selected_idx < static_cast<int>(num_submenus))
        run_menu_sp = submenus[selected_idx];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    case KEY_RIGHT:
      ++m_selected;
      if (m_selected >= static_cast<int>(num_submenus))
        m_selected = 0;
      if (m_selected < static_cast<int>(num_submenus))
        run_menu_sp = submenus[m_selected];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    case KEY_LEFT:
      --m_selected;
      if (m_selected < 0)
        m_selected = num_submenus - 1;
      if (m_selected < static_cast<int>(num_submenus))
        run_menu_sp = submenus[m_selected];
      else if (!submenus.empty())
        run_menu_sp = submenus.front();
      result = eKeyHandled;
      break;

    default:
      for (size_t i = 0; i < num_submenus; ++i) {
        if (submenus[i]->GetKeyValue() == key) {
          SetSelectedSubmenuIndex(i);
          run_menu_sp = submenus[i];
          result = eKeyHandled;
          break;
        }
      }
      break;
    }

    if (run_menu_sp) {
      // Run the action on this menu in case we need to populate the menu with
      // dynamic content and also in case check marks, and any other menu
      // decorations need to be calculated
      if (run_menu_sp->Action() == MenuActionResult::Quit)
        return eQuitApplication;

      Rect menu_bounds;
      menu_bounds.origin.x = run_menu_sp->GetStartingColumn();
      menu_bounds.origin.y = 1;
      menu_bounds.size.width = run_menu_sp->GetDrawWidth();
      menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2;
      if (m_menu_window_sp)
        window.GetParent()->RemoveSubWindow(m_menu_window_sp.get());

      m_menu_window_sp = window.GetParent()->CreateSubWindow(
          run_menu_sp->GetName().c_str(), menu_bounds, true);
      m_menu_window_sp->SetDelegate(run_menu_sp);
    }
  } else if (menu_type == Menu::Type::Item) {
    switch (key) {
    case KEY_DOWN:
      if (m_submenus.size() > 1) {
        const int start_select = m_selected;
        while (++m_selected != start_select) {
          if (static_cast<size_t>(m_selected) >= num_submenus)
            m_selected = 0;
          if (m_submenus[m_selected]->GetType() == Type::Separator)
            continue;
          else
            break;
        }
        return eKeyHandled;
      }
      break;

    case KEY_UP:
      if (m_submenus.size() > 1) {
        const int start_select = m_selected;
        while (--m_selected != start_select) {
          if (m_selected < static_cast<int>(0))
            m_selected = num_submenus - 1;
          if (m_submenus[m_selected]->GetType() == Type::Separator)
            continue;
          else
            break;
        }
        return eKeyHandled;
      }
      break;

    case KEY_RETURN:
      if (static_cast<size_t>(selected_idx) < num_submenus) {
        if (submenus[selected_idx]->Action() == MenuActionResult::Quit)
          return eQuitApplication;
        window.GetParent()->RemoveSubWindow(&window);
        return eKeyHandled;
      }
      break;

    case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in
                     // case other chars are entered for escaped sequences
      window.GetParent()->RemoveSubWindow(&window);
      return eKeyHandled;

    default:
      for (size_t i = 0; i < num_submenus; ++i) {
        Menu *menu = submenus[i].get();
        if (menu->GetKeyValue() == key) {
          SetSelectedSubmenuIndex(i);
          window.GetParent()->RemoveSubWindow(&window);
          if (menu->Action() == MenuActionResult::Quit)
            return eQuitApplication;
          return eKeyHandled;
        }
      }
      break;
    }
  } else if (menu_type == Menu::Type::Separator) {
  }
  return result;
}

class Application {
public:
  Application(FILE *in, FILE *out) : m_window_sp(), m_in(in), m_out(out) {}

  ~Application() {
    m_window_delegates.clear();
    m_window_sp.reset();
    if (m_screen) {
      ::delscreen(m_screen);
      m_screen = nullptr;
    }
  }

  void Initialize() {
    m_screen = ::newterm(nullptr, m_out, m_in);
    ::start_color();
    ::curs_set(0);
    ::noecho();
    ::keypad(stdscr, TRUE);
  }

  void Terminate() { ::endwin(); }

  void Run(Debugger &debugger) {
    bool done = false;
    int delay_in_tenths_of_a_second = 1;

    // Alas the threading model in curses is a bit lame so we need to resort
    // to polling every 0.5 seconds. We could poll for stdin ourselves and
    // then pass the keys down but then we need to translate all of the escape
    // sequences ourselves. So we resort to polling for input because we need
    // to receive async process events while in this loop.

    halfdelay(delay_in_tenths_of_a_second); // Poll using some number of
                                            // tenths of seconds seconds when
                                            // calling Window::GetChar()

    ListenerSP listener_sp(
        Listener::MakeListener("lldb.IOHandler.curses.Application"));
    ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
    debugger.EnableForwardEvents(listener_sp);

    m_update_screen = true;
#if defined(__APPLE__)
    std::deque<int> escape_chars;
#endif

    while (!done) {
      if (m_update_screen) {
        m_window_sp->Draw(false);
        // All windows should be calling Window::DeferredRefresh() instead of
        // Window::Refresh() so we can do a single update and avoid any screen
        // blinking
        update_panels();

        // Cursor hiding isn't working on MacOSX, so hide it in the top left
        // corner
        m_window_sp->MoveCursor(0, 0);

        doupdate();
        m_update_screen = false;
      }

#if defined(__APPLE__)
      // Terminal.app doesn't map its function keys correctly, F1-F4 default
      // to: \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if
      // possible
      int ch;
      if (escape_chars.empty())
        ch = m_window_sp->GetChar();
      else {
        ch = escape_chars.front();
        escape_chars.pop_front();
      }
      if (ch == KEY_ESCAPE) {
        int ch2 = m_window_sp->GetChar();
        if (ch2 == 'O') {
          int ch3 = m_window_sp->GetChar();
          switch (ch3) {
          case 'P':
            ch = KEY_F(1);
            break;
          case 'Q':
            ch = KEY_F(2);
            break;
          case 'R':
            ch = KEY_F(3);
            break;
          case 'S':
            ch = KEY_F(4);
            break;
          default:
            escape_chars.push_back(ch2);
            if (ch3 != -1)
              escape_chars.push_back(ch3);
            break;
          }
        } else if (ch2 != -1)
          escape_chars.push_back(ch2);
      }
#else
      int ch = m_window_sp->GetChar();

#endif
      if (ch == -1) {
        if (feof(m_in) || ferror(m_in)) {
          done = true;
        } else {
          // Just a timeout from using halfdelay(), check for events
          EventSP event_sp;
          while (listener_sp->PeekAtNextEvent()) {
            listener_sp->GetEvent(event_sp, std::chrono::seconds(0));

            if (event_sp) {
              Broadcaster *broadcaster = event_sp->GetBroadcaster();
              if (broadcaster) {
                // uint32_t event_type = event_sp->GetType();
                ConstString broadcaster_class(
                    broadcaster->GetBroadcasterClass());
                if (broadcaster_class == broadcaster_class_process) {
                  m_update_screen = true;
                  continue; // Don't get any key, just update our view
                }
              }
            }
          }
        }
      } else {
        HandleCharResult key_result = m_window_sp->HandleChar(ch);
        switch (key_result) {
        case eKeyHandled:
          m_update_screen = true;
          break;
        case eKeyNotHandled:
          if (ch == 12) { // Ctrl+L, force full redraw
            redrawwin(m_window_sp->get());
            m_update_screen = true;
          }
          break;
        case eQuitApplication:
          done = true;
          break;
        }
      }
    }

    debugger.CancelForwardEvents(listener_sp);
  }

  WindowSP &GetMainWindow() {
    if (!m_window_sp)
      m_window_sp = std::make_shared<Window>("main", stdscr, false);
    return m_window_sp;
  }

  void TerminalSizeChanged() {
    ::endwin();
    ::refresh();
    Rect content_bounds = m_window_sp->GetFrame();
    m_window_sp->SetBounds(content_bounds);
    if (WindowSP menubar_window_sp = m_window_sp->FindSubWindow("Menubar"))
      menubar_window_sp->SetBounds(content_bounds.MakeMenuBar());
    if (WindowSP status_window_sp = m_window_sp->FindSubWindow("Status"))
      status_window_sp->SetBounds(content_bounds.MakeStatusBar());

    WindowSP source_window_sp = m_window_sp->FindSubWindow("Source");
    WindowSP variables_window_sp = m_window_sp->FindSubWindow("Variables");
    WindowSP registers_window_sp = m_window_sp->FindSubWindow("Registers");
    WindowSP threads_window_sp = m_window_sp->FindSubWindow("Threads");

    Rect threads_bounds;
    Rect source_variables_bounds;
    content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
                                           threads_bounds);
    if (threads_window_sp)
      threads_window_sp->SetBounds(threads_bounds);
    else
      source_variables_bounds = content_bounds;

    Rect source_bounds;
    Rect variables_registers_bounds;
    source_variables_bounds.HorizontalSplitPercentage(
        0.70, source_bounds, variables_registers_bounds);
    if (variables_window_sp || registers_window_sp) {
      if (variables_window_sp && registers_window_sp) {
        Rect variables_bounds;
        Rect registers_bounds;
        variables_registers_bounds.VerticalSplitPercentage(
            0.50, variables_bounds, registers_bounds);
        variables_window_sp->SetBounds(variables_bounds);
        registers_window_sp->SetBounds(registers_bounds);
      } else if (variables_window_sp) {
        variables_window_sp->SetBounds(variables_registers_bounds);
      } else {
        registers_window_sp->SetBounds(variables_registers_bounds);
      }
    } else {
      source_bounds = source_variables_bounds;
    }

    source_window_sp->SetBounds(source_bounds);

    touchwin(stdscr);
    redrawwin(m_window_sp->get());
    m_update_screen = true;
  }

protected:
  WindowSP m_window_sp;
  WindowDelegates m_window_delegates;
  SCREEN *m_screen = nullptr;
  FILE *m_in;
  FILE *m_out;
  bool m_update_screen = false;
};

} // namespace curses
} // namespace lldb_private

using namespace lldb_private::curses;

struct Row {
  ValueObjectUpdater value;
  Row *parent;
  // The process stop ID when the children were calculated.
  uint32_t children_stop_id = 0;
  int row_idx = 0;
  int x = 1;
  int y = 1;
  bool might_have_children;
  bool expanded = false;
  bool calculated_children = false;
  std::vector<Row> children;

  Row(const ValueObjectSP &v, Row *p)
      : value(v), parent(p),
        might_have_children(v ? v->MightHaveChildren() : false) {}

  size_t GetDepth() const {
    if (parent)
      return 1 + parent->GetDepth();
    return 0;
  }

  void Expand() { expanded = true; }

  std::vector<Row> &GetChildren() {
    ProcessSP process_sp = value.GetProcessSP();
    auto stop_id = process_sp->GetStopID();
    if (process_sp && stop_id != children_stop_id) {
      children_stop_id = stop_id;
      calculated_children = false;
    }
    if (!calculated_children) {
      children.clear();
      calculated_children = true;
      ValueObjectSP valobj = value.GetSP();
      if (valobj) {
        const uint32_t num_children = valobj->GetNumChildrenIgnoringErrors();
        for (size_t i = 0; i < num_children; ++i) {
          children.push_back(Row(valobj->GetChildAtIndex(i), this));
        }
      }
    }
    return children;
  }

  void Unexpand() {
    expanded = false;
    calculated_children = false;
    children.clear();
  }

  void DrawTree(Window &window) {
    if (parent)
      parent->DrawTreeForChild(window, this, 0);

    if (might_have_children &&
        (!calculated_children || !GetChildren().empty())) {
      // It we can get UTF8 characters to work we should try to use the
      // "symbol" UTF8 string below
      //            const char *symbol = "";
      //            if (row.expanded)
      //                symbol = "\xe2\x96\xbd ";
      //            else
      //                symbol = "\xe2\x96\xb7 ";
      //            window.PutCString (symbol);

      // The ACS_DARROW and ACS_RARROW don't look very nice they are just a 'v'
      // or '>' character...
      //            if (expanded)
      //                window.PutChar (ACS_DARROW);
      //            else
      //                window.PutChar (ACS_RARROW);
      // Since we can't find any good looking right arrow/down arrow symbols,
      // just use a diamond...
      window.PutChar(ACS_DIAMOND);
      window.PutChar(ACS_HLINE);
    }
  }

  void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) {
    if (parent)
      parent->DrawTreeForChild(window, this, reverse_depth + 1);

    if (&GetChildren().back() == child) {
      // Last child
      if (reverse_depth == 0) {
        window.PutChar(ACS_LLCORNER);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(' ');
        window.PutChar(' ');
      }
    } else {
      if (reverse_depth == 0) {
        window.PutChar(ACS_LTEE);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(ACS_VLINE);
        window.PutChar(' ');
      }
    }
  }
};

struct DisplayOptions {
  bool show_types;
};

class TreeItem;

class TreeDelegate {
public:
  TreeDelegate() = default;
  virtual ~TreeDelegate() = default;

  virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0;
  virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0;
  virtual void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
                                           TreeItem *&selected_item) {}
  // This is invoked when a tree item is selected. If true is returned, the
  // views are updated.
  virtual bool TreeDelegateItemSelected(TreeItem &item) = 0;
  virtual bool TreeDelegateExpandRootByDefault() { return false; }
  // This is mostly useful for root tree delegates. If false is returned,
  // drawing will be skipped completely. This is needed, for instance, in
  // skipping drawing of the threads tree if there is no running process.
  virtual bool TreeDelegateShouldDraw() { return true; }
};

typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;

struct TreeItemData {
  TreeItemData(TreeItem *parent, TreeDelegate &delegate,
               bool might_have_children, bool is_expanded)
      : m_parent(parent), m_delegate(&delegate),
        m_might_have_children(might_have_children), m_is_expanded(is_expanded) {
  }

protected:
  TreeItem *m_parent;
  TreeDelegate *m_delegate;
  void *m_user_data = nullptr;
  uint64_t m_identifier = 0;
  std::string m_text;
  int m_row_idx = -1; // Zero based visible row index, -1 if not visible or for
                      // the root item
  bool m_might_have_children;
  bool m_is_expanded = false;
};

class TreeItem : public TreeItemData {
public:
  TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children)
      : TreeItemData(parent, delegate, might_have_children,
                     parent == nullptr
                         ? delegate.TreeDelegateExpandRootByDefault()
                         : false),
        m_children() {}

  TreeItem(const TreeItem &) = delete;
  TreeItem &operator=(const TreeItem &rhs) = delete;

  TreeItem &operator=(TreeItem &&rhs) {
    if (this != &rhs) {
      TreeItemData::operator=(std::move(rhs));
      AdoptChildren(rhs.m_children);
    }
    return *this;
  }

  TreeItem(TreeItem &&rhs) : TreeItemData(std::move(rhs)) {
    AdoptChildren(rhs.m_children);
  }

  size_t GetDepth() const {
    if (m_parent)
      return 1 + m_parent->GetDepth();
    return 0;
  }

  int GetRowIndex() const { return m_row_idx; }

  void ClearChildren() { m_children.clear(); }

  void Resize(size_t n, TreeDelegate &delegate, bool might_have_children) {
    if (m_children.size() >= n) {
      m_children.erase(m_children.begin() + n, m_children.end());
      return;
    }
    m_children.reserve(n);
    std::generate_n(std::back_inserter(m_children), n - m_children.size(),
                    [&, parent = this]() {
                      return TreeItem(parent, delegate, might_have_children);
                    });
  }

  TreeItem &operator[](size_t i) { return m_children[i]; }

  void SetRowIndex(int row_idx) { m_row_idx = row_idx; }

  size_t GetNumChildren() {
    m_delegate->TreeDelegateGenerateChildren(*this);
    return m_children.size();
  }

  void ItemWasSelected() { m_delegate->TreeDelegateItemSelected(*this); }

  void CalculateRowIndexes(int &row_idx) {
    SetRowIndex(row_idx);
    ++row_idx;

    const bool expanded = IsExpanded();

    // The root item must calculate its children, or we must calculate the
    // number of children if the item is expanded
    if (m_parent == nullptr || expanded)
      GetNumChildren();

    for (auto &item : m_children) {
      if (expanded)
        item.CalculateRowIndexes(row_idx);
      else
        item.SetRowIndex(-1);
    }
  }

  TreeItem *GetParent() { return m_parent; }

  bool IsExpanded() const { return m_is_expanded; }

  void Expand() { m_is_expanded = true; }

  void Unexpand() { m_is_expanded = false; }

  bool Draw(Window &window, const int first_visible_row,
            const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) {
    if (num_rows_left <= 0)
      return false;

    if (m_row_idx >= first_visible_row) {
      window.MoveCursor(2, row_idx + 1);

      if (m_parent)
        m_parent->DrawTreeForChild(window, this, 0);

      if (m_might_have_children) {
        // It we can get UTF8 characters to work we should try to use the
        // "symbol" UTF8 string below
        //            const char *symbol = "";
        //            if (row.expanded)
        //                symbol = "\xe2\x96\xbd ";
        //            else
        //                symbol = "\xe2\x96\xb7 ";
        //            window.PutCString (symbol);

        // The ACS_DARROW and ACS_RARROW don't look very nice they are just a
        // 'v' or '>' character...
        //            if (expanded)
        //                window.PutChar (ACS_DARROW);
        //            else
        //                window.PutChar (ACS_RARROW);
        // Since we can't find any good looking right arrow/down arrow symbols,
        // just use a diamond...
        window.PutChar(ACS_DIAMOND);
        window.PutChar(ACS_HLINE);
      }
      bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) &&
                       window.IsActive();

      if (highlight)
        window.AttributeOn(A_REVERSE);

      m_delegate->TreeDelegateDrawTreeItem(*this, window);

      if (highlight)
        window.AttributeOff(A_REVERSE);
      ++row_idx;
      --num_rows_left;
    }

    if (num_rows_left <= 0)
      return false; // We are done drawing...

    if (IsExpanded()) {
      for (auto &item : m_children) {
        // If we displayed all the rows and item.Draw() returns false we are
        // done drawing and can exit this for loop
        if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx,
                       num_rows_left))
          break;
      }
    }
    return num_rows_left >= 0; // Return true if not done drawing yet
  }

  void DrawTreeForChild(Window &window, TreeItem *child,
                        uint32_t reverse_depth) {
    if (m_parent)
      m_parent->DrawTreeForChild(window, this, reverse_depth + 1);

    if (&m_children.back() == child) {
      // Last child
      if (reverse_depth == 0) {
        window.PutChar(ACS_LLCORNER);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(' ');
        window.PutChar(' ');
      }
    } else {
      if (reverse_depth == 0) {
        window.PutChar(ACS_LTEE);
        window.PutChar(ACS_HLINE);
      } else {
        window.PutChar(ACS_VLINE);
        window.PutChar(' ');
      }
    }
  }

  TreeItem *GetItemForRowIndex(uint32_t row_idx) {
    if (static_cast<uint32_t>(m_row_idx) == row_idx)
      return this;
    if (m_children.empty())
      return nullptr;
    if (IsExpanded()) {
      for (auto &item : m_children) {
        TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
        if (selected_item_ptr)
          return selected_item_ptr;
      }
    }
    return nullptr;
  }

  void *GetUserData() const { return m_user_data; }

  void SetUserData(void *user_data) { m_user_data = user_data; }

  uint64_t GetIdentifier() const { return m_identifier; }

  void SetIdentifier(uint64_t identifier) { m_identifier = identifier; }

  const std::string &GetText() const { return m_text; }

  void SetText(const char *text) {
    if (text == nullptr) {
      m_text.clear();
      return;
    }
    m_text = text;
  }

  void SetMightHaveChildren(bool b) { m_might_have_children = b; }

protected:
  void AdoptChildren(std::vector<TreeItem> &children) {
    m_children = std::move(children);
    for (auto &child : m_children)
      child.m_parent = this;
  }

  std::vector<TreeItem> m_children;
};

class TreeWindowDelegate : public WindowDelegate {
public:
  TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp)
      : m_debugger(debugger), m_delegate_sp(delegate_sp),
        m_root(nullptr, *delegate_sp, true) {}

  int NumVisibleRows() const { return m_max_y - m_min_y; }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_min_x = 2;
    m_min_y = 1;
    m_max_x = window.GetWidth() - 1;
    m_max_y = window.GetHeight() - 1;

    window.Erase();
    window.DrawTitleBox(window.GetName());

    if (!m_delegate_sp->TreeDelegateShouldDraw()) {
      m_selected_item = nullptr;
      return true;
    }

    const int num_visible_rows = NumVisibleRows();
    m_num_rows = 0;
    m_root.CalculateRowIndexes(m_num_rows);
    m_delegate_sp->TreeDelegateUpdateSelection(m_root, m_selected_row_idx,
                                               m_selected_item);

    // If we unexpanded while having something selected our total number of
    // rows is less than the num visible rows, then make sure we show all the
    // rows by setting the first visible row accordingly.
    if (m_first_visible_row > 0 && m_num_rows < num_visible_rows)
      m_first_visible_row = 0;

    // Make sure the selected row is always visible
    if (m_selected_row_idx < m_first_visible_row)
      m_first_visible_row = m_selected_row_idx;
    else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
      m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;

    int row_idx = 0;
    int num_rows_left = num_visible_rows;
    m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx,
                num_rows_left);
    // Get the selected row
    m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);

    return true; // Drawing handled
  }

  const char *WindowDelegateGetHelpText() override {
    return "Thread window keyboard shortcuts:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_UP, "Select previous item"},
        {KEY_DOWN, "Select next item"},
        {KEY_RIGHT, "Expand the selected item"},
        {KEY_LEFT,
         "Unexpand the selected item or select parent if not expanded"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'h', "Show help dialog"},
        {' ', "Toggle item expansion"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    switch (c) {
    case ',':
    case KEY_PPAGE:
      // Page up key
      if (m_first_visible_row > 0) {
        if (m_first_visible_row > m_max_y)
          m_first_visible_row -= m_max_y;
        else
          m_first_visible_row = 0;
        m_selected_row_idx = m_first_visible_row;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      if (m_num_rows > m_max_y) {
        if (m_first_visible_row + m_max_y < m_num_rows) {
          m_first_visible_row += m_max_y;
          m_selected_row_idx = m_first_visible_row;
          m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
          if (m_selected_item)
            m_selected_item->ItemWasSelected();
        }
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_row_idx > 0) {
        --m_selected_row_idx;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_row_idx + 1 < m_num_rows) {
        ++m_selected_row_idx;
        m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
        if (m_selected_item)
          m_selected_item->ItemWasSelected();
      }
      return eKeyHandled;

    case KEY_RIGHT:
      if (m_selected_item) {
        if (!m_selected_item->IsExpanded())
          m_selected_item->Expand();
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_selected_item) {
        if (m_selected_item->IsExpanded())
          m_selected_item->Unexpand();
        else if (m_selected_item->GetParent()) {
          m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex();
          m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx);
          if (m_selected_item)
            m_selected_item->ItemWasSelected();
        }
      }
      return eKeyHandled;

    case ' ':
      // Toggle expansion state when SPACE is pressed
      if (m_selected_item) {
        if (m_selected_item->IsExpanded())
          m_selected_item->Unexpand();
        else
          m_selected_item->Expand();
      }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

protected:
  Debugger &m_debugger;
  TreeDelegateSP m_delegate_sp;
  TreeItem m_root;
  TreeItem *m_selected_item = nullptr;
  int m_num_rows = 0;
  int m_selected_row_idx = 0;
  int m_first_visible_row = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;
};

// A tree delegate that just draws the text member of the tree item, it doesn't
// have any children or actions.
class TextTreeDelegate : public TreeDelegate {
public:
  TextTreeDelegate() : TreeDelegate() {}

  ~TextTreeDelegate() override = default;

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    window.PutCStringTruncated(1, item.GetText().c_str());
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {}

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }
};

class FrameTreeDelegate : public TreeDelegate {
public:
  FrameTreeDelegate() : TreeDelegate() {
    FormatEntity::Parse(
        "#${frame.index}: {${function.name}${function.pc-offset}}}", m_format);
  }

  ~FrameTreeDelegate() override = default;

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    Thread *thread = (Thread *)item.GetUserData();
    if (thread) {
      const uint64_t frame_idx = item.GetIdentifier();
      StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx);
      if (frame_sp) {
        StreamString strm;
        const SymbolContext &sc =
            frame_sp->GetSymbolContext(eSymbolContextEverything);
        ExecutionContext exe_ctx(frame_sp);
        if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr,
                                 nullptr, false, false)) {
          int right_pad = 1;
          window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
        }
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    // No children for frames yet...
  }

  bool TreeDelegateItemSelected(TreeItem &item) override {
    Thread *thread = (Thread *)item.GetUserData();
    if (thread) {
      thread->GetProcess()->GetThreadList().SetSelectedThreadByID(
          thread->GetID());
      const uint64_t frame_idx = item.GetIdentifier();
      thread->SetSelectedFrameByIndex(frame_idx);
      return true;
    }
    return false;
  }

protected:
  FormatEntity::Entry m_format;
};

class ThreadTreeDelegate : public TreeDelegate {
public:
  ThreadTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger) {
    FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop "
                        "reason = ${thread.stop-reason}}",
                        m_format);
  }

  ~ThreadTreeDelegate() override = default;

  ProcessSP GetProcess() {
    return m_debugger.GetCommandInterpreter()
        .GetExecutionContext()
        .GetProcessSP();
  }

  ThreadSP GetThread(const TreeItem &item) {
    ProcessSP process_sp = GetProcess();
    if (process_sp)
      return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier());
    return ThreadSP();
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    ThreadSP thread_sp = GetThread(item);
    if (thread_sp) {
      StreamString strm;
      ExecutionContext exe_ctx(thread_sp);
      if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
                               nullptr, false, false)) {
        int right_pad = 1;
        window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        ThreadSP thread_sp = GetThread(item);
        if (thread_sp) {
          if (m_stop_id == process_sp->GetStopID() &&
              thread_sp->GetID() == m_tid)
            return; // Children are already up to date
          if (!m_frame_delegate_sp) {
            // Always expand the thread item the first time we show it
            m_frame_delegate_sp = std::make_shared<FrameTreeDelegate>();
          }

          m_stop_id = process_sp->GetStopID();
          m_tid = thread_sp->GetID();

          size_t num_frames = thread_sp->GetStackFrameCount();
          item.Resize(num_frames, *m_frame_delegate_sp, false);
          for (size_t i = 0; i < num_frames; ++i) {
            item[i].SetUserData(thread_sp.get());
            item[i].SetIdentifier(i);
          }
        }
        return;
      }
    }
    item.ClearChildren();
  }

  bool TreeDelegateItemSelected(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        ThreadSP thread_sp = GetThread(item);
        if (thread_sp) {
          ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList();
          std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex());
          ThreadSP selected_thread_sp = thread_list.GetSelectedThread();
          if (selected_thread_sp->GetID() != thread_sp->GetID()) {
            thread_list.SetSelectedThreadByID(thread_sp->GetID());
            return true;
          }
        }
      }
    }
    return false;
  }

protected:
  Debugger &m_debugger;
  std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp;
  lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
  uint32_t m_stop_id = UINT32_MAX;
  FormatEntity::Entry m_format;
};

class ThreadsTreeDelegate : public TreeDelegate {
public:
  ThreadsTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger) {
    FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
                        m_format);
  }

  ~ThreadsTreeDelegate() override = default;

  ProcessSP GetProcess() {
    return m_debugger.GetCommandInterpreter()
        .GetExecutionContext()
        .GetProcessSP();
  }

  bool TreeDelegateShouldDraw() override {
    ProcessSP process = GetProcess();
    if (!process)
      return false;

    if (StateIsRunningState(process->GetState()))
      return false;

    return true;
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    ProcessSP process_sp = GetProcess();
    if (process_sp && process_sp->IsAlive()) {
      StreamString strm;
      ExecutionContext exe_ctx(process_sp);
      if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr,
                               nullptr, false, false)) {
        int right_pad = 1;
        window.PutCStringTruncated(right_pad, strm.GetString().str().c_str());
      }
    }
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    ProcessSP process_sp = GetProcess();
    m_update_selection = false;
    if (process_sp && process_sp->IsAlive()) {
      StateType state = process_sp->GetState();
      if (StateIsStoppedState(state, true)) {
        const uint32_t stop_id = process_sp->GetStopID();
        if (m_stop_id == stop_id)
          return; // Children are already up to date

        m_stop_id = stop_id;
        m_update_selection = true;

        if (!m_thread_delegate_sp) {
          // Always expand the thread item the first time we show it
          // item.Expand();
          m_thread_delegate_sp =
              std::make_shared<ThreadTreeDelegate>(m_debugger);
        }

        ThreadList &threads = process_sp->GetThreadList();
        std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
        ThreadSP selected_thread = threads.GetSelectedThread();
        size_t num_threads = threads.GetSize();
        item.Resize(num_threads, *m_thread_delegate_sp, false);
        for (size_t i = 0; i < num_threads; ++i) {
          ThreadSP thread = threads.GetThreadAtIndex(i);
          item[i].SetIdentifier(thread->GetID());
          item[i].SetMightHaveChildren(true);
          if (selected_thread->GetID() == thread->GetID())
            item[i].Expand();
        }
        return;
      }
    }
    item.ClearChildren();
  }

  void TreeDelegateUpdateSelection(TreeItem &root, int &selection_index,
                                   TreeItem *&selected_item) override {
    if (!m_update_selection)
      return;

    ProcessSP process_sp = GetProcess();
    if (!(process_sp && process_sp->IsAlive()))
      return;

    StateType state = process_sp->GetState();
    if (!StateIsStoppedState(state, true))
      return;

    ThreadList &threads = process_sp->GetThreadList();
    std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
    ThreadSP selected_thread = threads.GetSelectedThread();
    size_t num_threads = threads.GetSize();
    for (size_t i = 0; i < num_threads; ++i) {
      ThreadSP thread = threads.GetThreadAtIndex(i);
      if (selected_thread->GetID() == thread->GetID()) {
        selected_item =
            &root[i][thread->GetSelectedFrameIndex(SelectMostRelevantFrame)];
        selection_index = selected_item->GetRowIndex();
        return;
      }
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

  bool TreeDelegateExpandRootByDefault() override { return true; }

protected:
  std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
  Debugger &m_debugger;
  uint32_t m_stop_id = UINT32_MAX;
  bool m_update_selection = false;
  FormatEntity::Entry m_format;
};

class BreakpointLocationTreeDelegate : public TreeDelegate {
public:
  BreakpointLocationTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger) {}

  ~BreakpointLocationTreeDelegate() override = default;

  Process *GetProcess() {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    return exe_ctx.GetProcessPtr();
  }

  BreakpointLocationSP GetBreakpointLocation(const TreeItem &item) {
    Breakpoint *breakpoint = (Breakpoint *)item.GetUserData();
    return breakpoint->GetLocationAtIndex(item.GetIdentifier());
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    BreakpointLocationSP breakpoint_location = GetBreakpointLocation(item);
    Process *process = GetProcess();
    StreamString stream;
    stream.Printf("%i.%i: ", breakpoint_location->GetBreakpoint().GetID(),
                  breakpoint_location->GetID());
    Address address = breakpoint_location->GetAddress();
    address.Dump(&stream, process, Address::DumpStyleResolvedDescription,
                 Address::DumpStyleInvalid);
    window.PutCStringTruncated(1, stream.GetString().str().c_str());
  }

  StringList ComputeDetailsList(BreakpointLocationSP breakpoint_location) {
    StringList details;

    Address address = breakpoint_location->GetAddress();
    SymbolContext symbol_context;
    address.CalculateSymbolContext(&symbol_context);

    if (symbol_context.module_sp) {
      StreamString module_stream;
      module_stream.PutCString("module = ");
      symbol_context.module_sp->GetFileSpec().Dump(
          module_stream.AsRawOstream());
      details.AppendString(module_stream.GetString());
    }

    if (symbol_context.comp_unit != nullptr) {
      StreamString compile_unit_stream;
      compile_unit_stream.PutCString("compile unit = ");
      symbol_context.comp_unit->GetPrimaryFile().GetFilename().Dump(
          &compile_unit_stream);
      details.AppendString(compile_unit_stream.GetString());

      if (symbol_context.function != nullptr) {
        StreamString function_stream;
        function_stream.PutCString("function = ");
        function_stream.PutCString(
            symbol_context.function->GetName().AsCString("<unknown>"));
        details.AppendString(function_stream.GetString());
      }

      if (symbol_context.line_entry.line > 0) {
        StreamString location_stream;
        location_stream.PutCString("location = ");
        symbol_context.line_entry.DumpStopContext(&location_stream, true);
        details.AppendString(location_stream.GetString());
      }

    } else {
      if (symbol_context.symbol) {
        StreamString symbol_stream;
        if (breakpoint_location->IsReExported())
          symbol_stream.PutCString("re-exported target = ");
        else
          symbol_stream.PutCString("symbol = ");
        symbol_stream.PutCString(
            symbol_context.symbol->GetName().AsCString("<unknown>"));
        details.AppendString(symbol_stream.GetString());
      }
    }

    Process *process = GetProcess();

    StreamString address_stream;
    address.Dump(&address_stream, process, Address::DumpStyleLoadAddress,
                 Address::DumpStyleModuleWithFileAddress);
    details.AppendString(address_stream.GetString());

    BreakpointSiteSP breakpoint_site = breakpoint_location->GetBreakpointSite();
    if (breakpoint_location->IsIndirect() && breakpoint_site) {
      Address resolved_address;
      resolved_address.SetLoadAddress(breakpoint_site->GetLoadAddress(),
                                      &breakpoint_location->GetTarget());
      Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
      if (resolved_symbol) {
        StreamString indirect_target_stream;
        indirect_target_stream.PutCString("indirect target = ");
        indirect_target_stream.PutCString(
            resolved_symbol->GetName().GetCString());
        details.AppendString(indirect_target_stream.GetString());
      }
    }

    bool is_resolved = breakpoint_location->IsResolved();
    StreamString resolved_stream;
    resolved_stream.Printf("resolved = %s", is_resolved ? "true" : "false");
    details.AppendString(resolved_stream.GetString());

    bool is_hardware = is_resolved && breakpoint_site->IsHardware();
    StreamString hardware_stream;
    hardware_stream.Printf("hardware = %s", is_hardware ? "true" : "false");
    details.AppendString(hardware_stream.GetString());

    StreamString hit_count_stream;
    hit_count_stream.Printf("hit count = %-4u",
                            breakpoint_location->GetHitCount());
    details.AppendString(hit_count_stream.GetString());

    return details;
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    BreakpointLocationSP breakpoint_location = GetBreakpointLocation(item);
    StringList details = ComputeDetailsList(breakpoint_location);

    if (!m_string_delegate_sp)
      m_string_delegate_sp = std::make_shared<TextTreeDelegate>();

    item.Resize(details.GetSize(), *m_string_delegate_sp, false);
    for (size_t i = 0; i < details.GetSize(); i++) {
      item[i].SetText(details.GetStringAtIndex(i));
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<TextTreeDelegate> m_string_delegate_sp;
};

class BreakpointTreeDelegate : public TreeDelegate {
public:
  BreakpointTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger),
        m_breakpoint_location_delegate_sp() {}

  ~BreakpointTreeDelegate() override = default;

  BreakpointSP GetBreakpoint(const TreeItem &item) {
    TargetSP target = m_debugger.GetSelectedTarget();
    BreakpointList &breakpoints = target->GetBreakpointList(false);
    return breakpoints.GetBreakpointAtIndex(item.GetIdentifier());
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    BreakpointSP breakpoint = GetBreakpoint(item);
    StreamString stream;
    stream.Format("{0}: ", breakpoint->GetID());
    breakpoint->GetResolverDescription(&stream);
    breakpoint->GetFilterDescription(&stream);
    window.PutCStringTruncated(1, stream.GetString().str().c_str());
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    BreakpointSP breakpoint = GetBreakpoint(item);

    if (!m_breakpoint_location_delegate_sp)
      m_breakpoint_location_delegate_sp =
          std::make_shared<BreakpointLocationTreeDelegate>(m_debugger);

    item.Resize(breakpoint->GetNumLocations(),
                *m_breakpoint_location_delegate_sp, true);
    for (size_t i = 0; i < breakpoint->GetNumLocations(); i++) {
      item[i].SetIdentifier(i);
      item[i].SetUserData(breakpoint.get());
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<BreakpointLocationTreeDelegate>
      m_breakpoint_location_delegate_sp;
};

class BreakpointsTreeDelegate : public TreeDelegate {
public:
  BreakpointsTreeDelegate(Debugger &debugger)
      : TreeDelegate(), m_debugger(debugger), m_breakpoint_delegate_sp() {}

  ~BreakpointsTreeDelegate() override = default;

  bool TreeDelegateShouldDraw() override {
    TargetSP target = m_debugger.GetSelectedTarget();
    if (!target)
      return false;

    return true;
  }

  void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override {
    window.PutCString("Breakpoints");
  }

  void TreeDelegateGenerateChildren(TreeItem &item) override {
    TargetSP target = m_debugger.GetSelectedTarget();

    BreakpointList &breakpoints = target->GetBreakpointList(false);
    std::unique_lock<std::recursive_mutex> lock;
    breakpoints.GetListMutex(lock);

    if (!m_breakpoint_delegate_sp)
      m_breakpoint_delegate_sp =
          std::make_shared<BreakpointTreeDelegate>(m_debugger);

    item.Resize(breakpoints.GetSize(), *m_breakpoint_delegate_sp, true);
    for (size_t i = 0; i < breakpoints.GetSize(); i++) {
      item[i].SetIdentifier(i);
    }
  }

  bool TreeDelegateItemSelected(TreeItem &item) override { return false; }

  bool TreeDelegateExpandRootByDefault() override { return true; }

protected:
  Debugger &m_debugger;
  std::shared_ptr<BreakpointTreeDelegate> m_breakpoint_delegate_sp;
};

class ValueObjectListDelegate : public WindowDelegate {
public:
  ValueObjectListDelegate() : m_rows() {}

  ValueObjectListDelegate(ValueObjectList &valobj_list) : m_rows() {
    SetValues(valobj_list);
  }

  ~ValueObjectListDelegate() override = default;

  void SetValues(ValueObjectList &valobj_list) {
    m_selected_row = nullptr;
    m_selected_row_idx = 0;
    m_first_visible_row = 0;
    m_num_rows = 0;
    m_rows.clear();
    for (auto &valobj_sp : valobj_list.GetObjects())
      m_rows.push_back(Row(valobj_sp, nullptr));
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    m_num_rows = 0;
    m_min_x = 2;
    m_min_y = 1;
    m_max_x = window.GetWidth() - 1;
    m_max_y = window.GetHeight() - 1;

    window.Erase();
    window.DrawTitleBox(window.GetName());

    const int num_visible_rows = NumVisibleRows();
    const int num_rows = CalculateTotalNumberRows(m_rows);

    // If we unexpanded while having something selected our total number of
    // rows is less than the num visible rows, then make sure we show all the
    // rows by setting the first visible row accordingly.
    if (m_first_visible_row > 0 && num_rows < num_visible_rows)
      m_first_visible_row = 0;

    // Make sure the selected row is always visible
    if (m_selected_row_idx < m_first_visible_row)
      m_first_visible_row = m_selected_row_idx;
    else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx)
      m_first_visible_row = m_selected_row_idx - num_visible_rows + 1;

    DisplayRows(window, m_rows, g_options);

    // Get the selected row
    m_selected_row = GetRowForRowIndex(m_selected_row_idx);
    // Keep the cursor on the selected row so the highlight and the cursor are
    // always on the same line
    if (m_selected_row)
      window.MoveCursor(m_selected_row->x, m_selected_row->y);

    return true; // Drawing handled
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_UP, "Select previous item"},
        {KEY_DOWN, "Select next item"},
        {KEY_RIGHT, "Expand selected item"},
        {KEY_LEFT, "Unexpand selected item or select parent if not expanded"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'A', "Format as annotated address"},
        {'b', "Format as binary"},
        {'B', "Format as hex bytes with ASCII"},
        {'c', "Format as character"},
        {'d', "Format as a signed integer"},
        {'D', "Format selected value using the default format for the type"},
        {'f', "Format as float"},
        {'h', "Show help dialog"},
        {'i', "Format as instructions"},
        {'o', "Format as octal"},
        {'p', "Format as pointer"},
        {'s', "Format as C string"},
        {'t', "Toggle showing/hiding type names"},
        {'u', "Format as an unsigned integer"},
        {'x', "Format as hex"},
        {'X', "Format as uppercase hex"},
        {' ', "Toggle item expansion"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    switch (c) {
    case 'x':
    case 'X':
    case 'o':
    case 's':
    case 'u':
    case 'd':
    case 'D':
    case 'i':
    case 'A':
    case 'p':
    case 'c':
    case 'b':
    case 'B':
    case 'f':
      // Change the format for the currently selected item
      if (m_selected_row) {
        auto valobj_sp = m_selected_row->value.GetSP();
        if (valobj_sp)
          valobj_sp->SetFormat(FormatForChar(c));
      }
      return eKeyHandled;

    case 't':
      // Toggle showing type names
      g_options.show_types = !g_options.show_types;
      return eKeyHandled;

    case ',':
    case KEY_PPAGE:
      // Page up key
      if (m_first_visible_row > 0) {
        if (static_cast<int>(m_first_visible_row) > m_max_y)
          m_first_visible_row -= m_max_y;
        else
          m_first_visible_row = 0;
        m_selected_row_idx = m_first_visible_row;
      }
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      if (m_num_rows > static_cast<size_t>(m_max_y)) {
        if (m_first_visible_row + m_max_y < m_num_rows) {
          m_first_visible_row += m_max_y;
          m_selected_row_idx = m_first_visible_row;
        }
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_row_idx > 0)
        --m_selected_row_idx;
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_row_idx + 1 < m_num_rows)
        ++m_selected_row_idx;
      return eKeyHandled;

    case KEY_RIGHT:
      if (m_selected_row) {
        if (!m_selected_row->expanded)
          m_selected_row->Expand();
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_selected_row) {
        if (m_selected_row->expanded)
          m_selected_row->Unexpand();
        else if (m_selected_row->parent)
          m_selected_row_idx = m_selected_row->parent->row_idx;
      }
      return eKeyHandled;

    case ' ':
      // Toggle expansion state when SPACE is pressed
      if (m_selected_row) {
        if (m_selected_row->expanded)
          m_selected_row->Unexpand();
        else
          m_selected_row->Expand();
      }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

protected:
  std::vector<Row> m_rows;
  Row *m_selected_row = nullptr;
  uint32_t m_selected_row_idx = 0;
  uint32_t m_first_visible_row = 0;
  uint32_t m_num_rows = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;

  static Format FormatForChar(int c) {
    switch (c) {
    case 'x':
      return eFormatHex;
    case 'X':
      return eFormatHexUppercase;
    case 'o':
      return eFormatOctal;
    case 's':
      return eFormatCString;
    case 'u':
      return eFormatUnsigned;
    case 'd':
      return eFormatDecimal;
    case 'D':
      return eFormatDefault;
    case 'i':
      return eFormatInstruction;
    case 'A':
      return eFormatAddressInfo;
    case 'p':
      return eFormatPointer;
    case 'c':
      return eFormatChar;
    case 'b':
      return eFormatBinary;
    case 'B':
      return eFormatBytesWithASCII;
    case 'f':
      return eFormatFloat;
    }
    return eFormatDefault;
  }

  bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options,
                        bool highlight, bool last_child) {
    ValueObject *valobj = row.value.GetSP().get();

    if (valobj == nullptr)
      return false;

    const char *type_name =
        options.show_types ? valobj->GetTypeName().GetCString() : nullptr;
    const char *name = valobj->GetName().GetCString();
    const char *value = valobj->GetValueAsCString();
    const char *summary = valobj->GetSummaryAsCString();

    window.MoveCursor(row.x, row.y);

    row.DrawTree(window);

    if (highlight)
      window.AttributeOn(A_REVERSE);

    if (type_name && type_name[0])
      window.PrintfTruncated(1, "(%s) ", type_name);

    if (name && name[0])
      window.PutCStringTruncated(1, name);

    attr_t changd_attr = 0;
    if (valobj->GetValueDidChange())
      changd_attr = COLOR_PAIR(RedOnBlack) | A_BOLD;

    if (value && value[0]) {
      window.PutCStringTruncated(1, " = ");
      if (changd_attr)
        window.AttributeOn(changd_attr);
      window.PutCStringTruncated(1, value);
      if (changd_attr)
        window.AttributeOff(changd_attr);
    }

    if (summary && summary[0]) {
      window.PutCStringTruncated(1, " ");
      if (changd_attr)
        window.AttributeOn(changd_attr);
      window.PutCStringTruncated(1, summary);
      if (changd_attr)
        window.AttributeOff(changd_attr);
    }

    if (highlight)
      window.AttributeOff(A_REVERSE);

    return true;
  }

  void DisplayRows(Window &window, std::vector<Row> &rows,
                   DisplayOptions &options) {
    // >   0x25B7
    // \/  0x25BD

    bool window_is_active = window.IsActive();
    for (auto &row : rows) {
      const bool last_child = row.parent && &rows[rows.size() - 1] == &row;
      // Save the row index in each Row structure
      row.row_idx = m_num_rows;
      if ((m_num_rows >= m_first_visible_row) &&
          ((m_num_rows - m_first_visible_row) <
           static_cast<size_t>(NumVisibleRows()))) {
        row.x = m_min_x;
        row.y = m_num_rows - m_first_visible_row + 1;
        if (DisplayRowObject(window, row, options,
                             window_is_active &&
                                 m_num_rows == m_selected_row_idx,
                             last_child)) {
          ++m_num_rows;
        } else {
          row.x = 0;
          row.y = 0;
        }
      } else {
        row.x = 0;
        row.y = 0;
        ++m_num_rows;
      }

      if (row.expanded) {
        auto &children = row.GetChildren();
        if (!children.empty()) {
          DisplayRows(window, children, options);
        }
      }
    }
  }

  int CalculateTotalNumberRows(std::vector<Row> &rows) {
    int row_count = 0;
    for (auto &row : rows) {
      ++row_count;
      if (row.expanded)
        row_count += CalculateTotalNumberRows(row.GetChildren());
    }
    return row_count;
  }

  static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) {
    for (auto &row : rows) {
      if (row_index == 0)
        return &row;
      else {
        --row_index;
        if (row.expanded) {
          auto &children = row.GetChildren();
          if (!children.empty()) {
            Row *result = GetRowForRowIndexImpl(children, row_index);
            if (result)
              return result;
          }
        }
      }
    }
    return nullptr;
  }

  Row *GetRowForRowIndex(size_t row_index) {
    return GetRowForRowIndexImpl(m_rows, row_index);
  }

  int NumVisibleRows() const { return m_max_y - m_min_y; }

  static DisplayOptions g_options;
};

class FrameVariablesWindowDelegate : public ValueObjectListDelegate {
public:
  FrameVariablesWindowDelegate(Debugger &debugger)
      : ValueObjectListDelegate(), m_debugger(debugger) {}

  ~FrameVariablesWindowDelegate() override = default;

  const char *WindowDelegateGetHelpText() override {
    return "Frame variable window keyboard shortcuts:";
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    Process *process = exe_ctx.GetProcessPtr();
    Block *frame_block = nullptr;
    StackFrame *frame = nullptr;

    if (process) {
      StateType state = process->GetState();
      if (StateIsStoppedState(state, true)) {
        frame = exe_ctx.GetFramePtr();
        if (frame)
          frame_block = frame->GetFrameBlock();
      } else if (StateIsRunningState(state)) {
        return true; // Don't do any updating when we are running
      }
    }

    ValueObjectList local_values;
    if (frame_block) {
      // Only update the variables if they have changed
      if (m_frame_block != frame_block) {
        m_frame_block = frame_block;

        VariableList *locals = frame->GetVariableList(true, nullptr);
        if (locals) {
          const DynamicValueType use_dynamic = eDynamicDontRunTarget;
          for (const VariableSP &local_sp : *locals) {
            ValueObjectSP value_sp =
                frame->GetValueObjectForFrameVariable(local_sp, use_dynamic);
            if (value_sp) {
              ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue();
              if (synthetic_value_sp)
                local_values.Append(synthetic_value_sp);
              else
                local_values.Append(value_sp);
            }
          }
          // Update the values
          SetValues(local_values);
        }
      }
    } else {
      m_frame_block = nullptr;
      // Update the values with an empty list if there is no frame
      SetValues(local_values);
    }

    return ValueObjectListDelegate::WindowDelegateDraw(window, force);
  }

protected:
  Debugger &m_debugger;
  Block *m_frame_block = nullptr;
};

class RegistersWindowDelegate : public ValueObjectListDelegate {
public:
  RegistersWindowDelegate(Debugger &debugger)
      : ValueObjectListDelegate(), m_debugger(debugger) {}

  ~RegistersWindowDelegate() override = default;

  const char *WindowDelegateGetHelpText() override {
    return "Register window keyboard shortcuts:";
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx(
        m_debugger.GetCommandInterpreter().GetExecutionContext());
    StackFrame *frame = exe_ctx.GetFramePtr();

    ValueObjectList value_list;
    if (frame) {
      if (frame->GetStackID() != m_stack_id) {
        m_stack_id = frame->GetStackID();
        RegisterContextSP reg_ctx(frame->GetRegisterContext());
        if (reg_ctx) {
          const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
          for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
            value_list.Append(
                ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));
          }
        }
        SetValues(value_list);
      }
    } else {
      Process *process = exe_ctx.GetProcessPtr();
      if (process && process->IsAlive())
        return true; // Don't do any updating if we are running
      else {
        // Update the values with an empty list if there is no process or the
        // process isn't alive anymore
        SetValues(value_list);
      }
    }
    return ValueObjectListDelegate::WindowDelegateDraw(window, force);
  }

protected:
  Debugger &m_debugger;
  StackID m_stack_id;
};

static const char *CursesKeyToCString(int ch) {
  static char g_desc[32];
  if (ch >= KEY_F0 && ch < KEY_F0 + 64) {
    snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0);
    return g_desc;
  }
  switch (ch) {
  case KEY_DOWN:
    return "down";
  case KEY_UP:
    return "up";
  case KEY_LEFT:
    return "left";
  case KEY_RIGHT:
    return "right";
  case KEY_HOME:
    return "home";
  case KEY_BACKSPACE:
    return "backspace";
  case KEY_DL:
    return "delete-line";
  case KEY_IL:
    return "insert-line";
  case KEY_DC:
    return "delete-char";
  case KEY_IC:
    return "insert-char";
  case KEY_CLEAR:
    return "clear";
  case KEY_EOS:
    return "clear-to-eos";
  case KEY_EOL:
    return "clear-to-eol";
  case KEY_SF:
    return "scroll-forward";
  case KEY_SR:
    return "scroll-backward";
  case KEY_NPAGE:
    return "page-down";
  case KEY_PPAGE:
    return "page-up";
  case KEY_STAB:
    return "set-tab";
  case KEY_CTAB:
    return "clear-tab";
  case KEY_CATAB:
    return "clear-all-tabs";
  case KEY_ENTER:
    return "enter";
  case KEY_PRINT:
    return "print";
  case KEY_LL:
    return "lower-left key";
  case KEY_A1:
    return "upper left of keypad";
  case KEY_A3:
    return "upper right of keypad";
  case KEY_B2:
    return "center of keypad";
  case KEY_C1:
    return "lower left of keypad";
  case KEY_C3:
    return "lower right of keypad";
  case KEY_BTAB:
    return "back-tab key";
  case KEY_BEG:
    return "begin key";
  case KEY_CANCEL:
    return "cancel key";
  case KEY_CLOSE:
    return "close key";
  case KEY_COMMAND:
    return "command key";
  case KEY_COPY:
    return "copy key";
  case KEY_CREATE:
    return "create key";
  case KEY_END:
    return "end key";
  case KEY_EXIT:
    return "exit key";
  case KEY_FIND:
    return "find key";
  case KEY_HELP:
    return "help key";
  case KEY_MARK:
    return "mark key";
  case KEY_MESSAGE:
    return "message key";
  case KEY_MOVE:
    return "move key";
  case KEY_NEXT:
    return "next key";
  case KEY_OPEN:
    return "open key";
  case KEY_OPTIONS:
    return "options key";
  case KEY_PREVIOUS:
    return "previous key";
  case KEY_REDO:
    return "redo key";
  case KEY_REFERENCE:
    return "reference key";
  case KEY_REFRESH:
    return "refresh key";
  case KEY_REPLACE:
    return "replace key";
  case KEY_RESTART:
    return "restart key";
  case KEY_RESUME:
    return "resume key";
  case KEY_SAVE:
    return "save key";
  case KEY_SBEG:
    return "shifted begin key";
  case KEY_SCANCEL:
    return "shifted cancel key";
  case KEY_SCOMMAND:
    return "shifted command key";
  case KEY_SCOPY:
    return "shifted copy key";
  case KEY_SCREATE:
    return "shifted create key";
  case KEY_SDC:
    return "shifted delete-character key";
  case KEY_SDL:
    return "shifted delete-line key";
  case KEY_SELECT:
    return "select key";
  case KEY_SEND:
    return "shifted end key";
  case KEY_SEOL:
    return "shifted clear-to-end-of-line key";
  case KEY_SEXIT:
    return "shifted exit key";
  case KEY_SFIND:
    return "shifted find key";
  case KEY_SHELP:
    return "shifted help key";
  case KEY_SHOME:
    return "shifted home key";
  case KEY_SIC:
    return "shifted insert-character key";
  case KEY_SLEFT:
    return "shifted left-arrow key";
  case KEY_SMESSAGE:
    return "shifted message key";
  case KEY_SMOVE:
    return "shifted move key";
  case KEY_SNEXT:
    return "shifted next key";
  case KEY_SOPTIONS:
    return "shifted options key";
  case KEY_SPREVIOUS:
    return "shifted previous key";
  case KEY_SPRINT:
    return "shifted print key";
  case KEY_SREDO:
    return "shifted redo key";
  case KEY_SREPLACE:
    return "shifted replace key";
  case KEY_SRIGHT:
    return "shifted right-arrow key";
  case KEY_SRSUME:
    return "shifted resume key";
  case KEY_SSAVE:
    return "shifted save key";
  case KEY_SSUSPEND:
    return "shifted suspend key";
  case KEY_SUNDO:
    return "shifted undo key";
  case KEY_SUSPEND:
    return "suspend key";
  case KEY_UNDO:
    return "undo key";
  case KEY_MOUSE:
    return "Mouse event has occurred";
  case KEY_RESIZE:
    return "Terminal resize event";
#ifdef KEY_EVENT
  case KEY_EVENT:
    return "We were interrupted by an event";
#endif
  case KEY_RETURN:
    return "return";
  case ' ':
    return "space";
  case '\t':
    return "tab";
  case KEY_ESCAPE:
    return "escape";
  default:
    if (llvm::isPrint(ch))
      snprintf(g_desc, sizeof(g_desc), "%c", ch);
    else
      snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch);
    return g_desc;
  }
  return nullptr;
}

HelpDialogDelegate::HelpDialogDelegate(const char *text,
                                       KeyHelp *key_help_array)
    : m_text() {
  if (text && text[0]) {
    m_text.SplitIntoLines(text);
    m_text.AppendString("");
  }
  if (key_help_array) {
    for (KeyHelp *key = key_help_array; key->ch; ++key) {
      StreamString key_description;
      key_description.Printf("%10s - %s", CursesKeyToCString(key->ch),
                             key->description);
      m_text.AppendString(key_description.GetString());
    }
  }
}

HelpDialogDelegate::~HelpDialogDelegate() = default;

bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) {
  window.Erase();
  const int window_height = window.GetHeight();
  int x = 2;
  int y = 1;
  const int min_y = y;
  const int max_y = window_height - 1 - y;
  const size_t num_visible_lines = max_y - min_y + 1;
  const size_t num_lines = m_text.GetSize();
  const char *bottom_message;
  if (num_lines <= num_visible_lines)
    bottom_message = "Press any key to exit";
  else
    bottom_message = "Use arrows to scroll, any other key to exit";
  window.DrawTitleBox(window.GetName(), bottom_message);
  while (y <= max_y) {
    window.MoveCursor(x, y);
    window.PutCStringTruncated(
        1, m_text.GetStringAtIndex(m_first_visible_line + y - min_y));
    ++y;
  }
  return true;
}

HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window,
                                                              int key) {
  bool done = false;
  const size_t num_lines = m_text.GetSize();
  const size_t num_visible_lines = window.GetHeight() - 2;

  if (num_lines <= num_visible_lines) {
    done = true;
    // If we have all lines visible and don't need scrolling, then any key
    // press will cause us to exit
  } else {
    switch (key) {
    case KEY_UP:
      if (m_first_visible_line > 0)
        --m_first_visible_line;
      break;

    case KEY_DOWN:
      if (m_first_visible_line + num_visible_lines < num_lines)
        ++m_first_visible_line;
      break;

    case KEY_PPAGE:
    case ',':
      if (m_first_visible_line > 0) {
        if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines)
          m_first_visible_line -= num_visible_lines;
        else
          m_first_visible_line = 0;
      }
      break;

    case KEY_NPAGE:
    case '.':
      if (m_first_visible_line + num_visible_lines < num_lines) {
        m_first_visible_line += num_visible_lines;
        if (static_cast<size_t>(m_first_visible_line) > num_lines)
          m_first_visible_line = num_lines - num_visible_lines;
      }
      break;

    default:
      done = true;
      break;
    }
  }
  if (done)
    window.GetParent()->RemoveSubWindow(&window);
  return eKeyHandled;
}

class ApplicationDelegate : public WindowDelegate, public MenuDelegate {
public:
  enum {
    eMenuID_LLDB = 1,
    eMenuID_LLDBAbout,
    eMenuID_LLDBExit,

    eMenuID_Target,
    eMenuID_TargetCreate,
    eMenuID_TargetDelete,

    eMenuID_Process,
    eMenuID_ProcessAttach,
    eMenuID_ProcessDetachResume,
    eMenuID_ProcessDetachSuspended,
    eMenuID_ProcessLaunch,
    eMenuID_ProcessContinue,
    eMenuID_ProcessHalt,
    eMenuID_ProcessKill,

    eMenuID_Thread,
    eMenuID_ThreadStepIn,
    eMenuID_ThreadStepOver,
    eMenuID_ThreadStepOut,

    eMenuID_View,
    eMenuID_ViewBacktrace,
    eMenuID_ViewRegisters,
    eMenuID_ViewSource,
    eMenuID_ViewVariables,
    eMenuID_ViewBreakpoints,

    eMenuID_Help,
    eMenuID_HelpGUIHelp
  };

  ApplicationDelegate(Application &app, Debugger &debugger)
      : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {}

  ~ApplicationDelegate() override = default;

  bool WindowDelegateDraw(Window &window, bool force) override {
    return false; // Drawing not handled, let standard window drawing happen
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int key) override {
    switch (key) {
    case '\t':
      window.SelectNextWindowAsActive();
      return eKeyHandled;

    case KEY_SHIFT_TAB:
      window.SelectPreviousWindowAsActive();
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    case KEY_ESCAPE:
      return eQuitApplication;

    default:
      break;
    }
    return eKeyNotHandled;
  }

  const char *WindowDelegateGetHelpText() override {
    return "Welcome to the LLDB curses GUI.\n\n"
           "Press the TAB key to change the selected view.\n"
           "Each view has its own keyboard shortcuts, press 'h' to open a "
           "dialog to display them.\n\n"
           "Common key bindings for all views:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {'\t', "Select next view"},
        {KEY_BTAB, "Select previous view"},
        {'h', "Show help dialog with view specific key bindings"},
        {',', "Page up"},
        {'.', "Page down"},
        {KEY_UP, "Select previous"},
        {KEY_DOWN, "Select next"},
        {KEY_LEFT, "Unexpand or select parent"},
        {KEY_RIGHT, "Expand"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  MenuActionResult MenuDelegateAction(Menu &menu) override {
    switch (menu.GetIdentifier()) {
    case eMenuID_TargetCreate: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp =
          FormDelegateSP(new TargetCreateFormDelegate(m_debugger));
      Rect bounds = main_window_sp->GetCenteredRect(80, 19);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }
    case eMenuID_ThreadStepIn: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          exe_ctx.GetThreadRef().StepIn(true);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ThreadStepOut: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true)) {
          Thread *thread = exe_ctx.GetThreadPtr();
          uint32_t frame_idx =
              thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
          exe_ctx.GetThreadRef().StepOut(frame_idx);
        }
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ThreadStepOver: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          exe_ctx.GetThreadRef().StepOver(true);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessAttach: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp = FormDelegateSP(
          new ProcessAttachFormDelegate(m_debugger, main_window_sp));
      Rect bounds = main_window_sp->GetCenteredRect(80, 22);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }
    case eMenuID_ProcessLaunch: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      FormDelegateSP form_delegate_sp = FormDelegateSP(
          new ProcessLaunchFormDelegate(m_debugger, main_window_sp));
      Rect bounds = main_window_sp->GetCenteredRect(80, 22);
      WindowSP form_window_sp = main_window_sp->CreateSubWindow(
          form_delegate_sp->GetName().c_str(), bounds, true);
      WindowDelegateSP window_delegate_sp =
          WindowDelegateSP(new FormWindowDelegate(form_delegate_sp));
      form_window_sp->SetDelegate(window_delegate_sp);
      return MenuActionResult::Handled;
    }

    case eMenuID_ProcessContinue: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive() &&
            StateIsStoppedState(process->GetState(), true))
          process->Resume();
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessKill: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Destroy(false);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessHalt: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Halt();
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_ProcessDetachResume:
    case eMenuID_ProcessDetachSuspended: {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope()) {
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsAlive())
          process->Detach(menu.GetIdentifier() ==
                          eMenuID_ProcessDetachSuspended);
      }
    }
      return MenuActionResult::Handled;

    case eMenuID_Process: {
      // Populate the menu with all of the threads if the process is stopped
      // when the Process menu gets selected and is about to display its
      // submenu.
      Menus &submenus = menu.GetSubmenus();
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      Process *process = exe_ctx.GetProcessPtr();
      if (process && process->IsAlive() &&
          StateIsStoppedState(process->GetState(), true)) {
        if (submenus.size() == 7)
          menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
        else if (submenus.size() > 8)
          submenus.erase(submenus.begin() + 8, submenus.end());

        ThreadList &threads = process->GetThreadList();
        std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
        size_t num_threads = threads.GetSize();
        for (size_t i = 0; i < num_threads; ++i) {
          ThreadSP thread_sp = threads.GetThreadAtIndex(i);
          char menu_char = '\0';
          if (i < 9)
            menu_char = '1' + i;
          StreamString thread_menu_title;
          thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID());
          const char *thread_name = thread_sp->GetName();
          if (thread_name && thread_name[0])
            thread_menu_title.Printf(" %s", thread_name);
          else {
            const char *queue_name = thread_sp->GetQueueName();
            if (queue_name && queue_name[0])
              thread_menu_title.Printf(" %s", queue_name);
          }
          menu.AddSubmenu(
              MenuSP(new Menu(thread_menu_title.GetString().str().c_str(),
                              nullptr, menu_char, thread_sp->GetID())));
        }
      } else if (submenus.size() > 7) {
        // Remove the separator and any other thread submenu items that were
        // previously added
        submenus.erase(submenus.begin() + 7, submenus.end());
      }
      // Since we are adding and removing items we need to recalculate the
      // name lengths
      menu.RecalculateNameLengths();
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewVariables: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
      WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
      WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
      const Rect source_bounds = source_window_sp->GetBounds();

      if (variables_window_sp) {
        const Rect variables_bounds = variables_window_sp->GetBounds();

        main_window_sp->RemoveSubWindow(variables_window_sp.get());

        if (registers_window_sp) {
          // We have a registers window, so give all the area back to the
          // registers window
          Rect registers_bounds = variables_bounds;
          registers_bounds.size.width = source_bounds.size.width;
          registers_window_sp->SetBounds(registers_bounds);
        } else {
          // We have no registers window showing so give the bottom area back
          // to the source view
          source_window_sp->Resize(source_bounds.size.width,
                                   source_bounds.size.height +
                                       variables_bounds.size.height);
        }
      } else {
        Rect new_variables_rect;
        if (registers_window_sp) {
          // We have a registers window so split the area of the registers
          // window into two columns where the left hand side will be the
          // variables and the right hand side will be the registers
          const Rect variables_bounds = registers_window_sp->GetBounds();
          Rect new_registers_rect;
          variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect,
                                                   new_registers_rect);
          registers_window_sp->SetBounds(new_registers_rect);
        } else {
          // No registers window, grab the bottom part of the source window
          Rect new_source_rect;
          source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
                                                  new_variables_rect);
          source_window_sp->SetBounds(new_source_rect);
        }
        WindowSP new_window_sp = main_window_sp->CreateSubWindow(
            "Variables", new_variables_rect, false);
        new_window_sp->SetDelegate(
            WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
      }
      touchwin(stdscr);
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewRegisters: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP source_window_sp = main_window_sp->FindSubWindow("Source");
      WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables");
      WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers");
      const Rect source_bounds = source_window_sp->GetBounds();

      if (registers_window_sp) {
        if (variables_window_sp) {
          const Rect variables_bounds = variables_window_sp->GetBounds();

          // We have a variables window, so give all the area back to the
          // variables window
          variables_window_sp->Resize(variables_bounds.size.width +
                                          registers_window_sp->GetWidth(),
                                      variables_bounds.size.height);
        } else {
          // We have no variables window showing so give the bottom area back
          // to the source view
          source_window_sp->Resize(source_bounds.size.width,
                                   source_bounds.size.height +
                                       registers_window_sp->GetHeight());
        }
        main_window_sp->RemoveSubWindow(registers_window_sp.get());
      } else {
        Rect new_regs_rect;
        if (variables_window_sp) {
          // We have a variables window, split it into two columns where the
          // left hand side will be the variables and the right hand side will
          // be the registers
          const Rect variables_bounds = variables_window_sp->GetBounds();
          Rect new_vars_rect;
          variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect,
                                                   new_regs_rect);
          variables_window_sp->SetBounds(new_vars_rect);
        } else {
          // No variables window, grab the bottom part of the source window
          Rect new_source_rect;
          source_bounds.HorizontalSplitPercentage(0.70, new_source_rect,
                                                  new_regs_rect);
          source_window_sp->SetBounds(new_source_rect);
        }
        WindowSP new_window_sp =
            main_window_sp->CreateSubWindow("Registers", new_regs_rect, false);
        new_window_sp->SetDelegate(
            WindowDelegateSP(new RegistersWindowDelegate(m_debugger)));
      }
      touchwin(stdscr);
    }
      return MenuActionResult::Handled;

    case eMenuID_ViewBreakpoints: {
      WindowSP main_window_sp = m_app.GetMainWindow();
      WindowSP threads_window_sp = main_window_sp->FindSubWindow("Threads");
      WindowSP breakpoints_window_sp =
          main_window_sp->FindSubWindow("Breakpoints");
      const Rect threads_bounds = threads_window_sp->GetBounds();

      // If a breakpoints window already exists, remove it and give the area
      // it used to occupy to the threads window. If it doesn't exist, split
      // the threads window horizontally into two windows where the top window
      // is the threads window and the bottom window is a newly added
      // breakpoints window.
      if (breakpoints_window_sp) {
        threads_window_sp->Resize(threads_bounds.size.width,
                                  threads_bounds.size.height +
                                      breakpoints_window_sp->GetHeight());
        main_window_sp->RemoveSubWindow(breakpoints_window_sp.get());
      } else {
        Rect new_threads_bounds, breakpoints_bounds;
        threads_bounds.HorizontalSplitPercentage(0.70, new_threads_bounds,
                                                 breakpoints_bounds);
        threads_window_sp->SetBounds(new_threads_bounds);
        breakpoints_window_sp = main_window_sp->CreateSubWindow(
            "Breakpoints", breakpoints_bounds, false);
        TreeDelegateSP breakpoints_delegate_sp(
            new BreakpointsTreeDelegate(m_debugger));
        breakpoints_window_sp->SetDelegate(WindowDelegateSP(
            new TreeWindowDelegate(m_debugger, breakpoints_delegate_sp)));
      }
      touchwin(stdscr);
      return MenuActionResult::Handled;
    }

    case eMenuID_HelpGUIHelp:
      m_app.GetMainWindow()->CreateHelpSubwindow();
      return MenuActionResult::Handled;

    default:
      break;
    }

    return MenuActionResult::NotHandled;
  }

protected:
  Application &m_app;
  Debugger &m_debugger;
};

class StatusBarWindowDelegate : public WindowDelegate {
public:
  StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) {
    FormatEntity::Parse("Thread: ${thread.id%tid}", m_format);
  }

  ~StatusBarWindowDelegate() override = default;

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    Process *process = exe_ctx.GetProcessPtr();
    Thread *thread = exe_ctx.GetThreadPtr();
    StackFrame *frame = exe_ctx.GetFramePtr();
    window.Erase();
    window.SetBackground(BlackOnWhite);
    window.MoveCursor(0, 0);
    if (process) {
      const StateType state = process->GetState();
      window.Printf("Process: %5" PRIu64 " %10s", process->GetID(),
                    StateAsCString(state));

      if (StateIsStoppedState(state, true)) {
        StreamString strm;
        if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx,
                                           nullptr, nullptr, false, false)) {
          window.MoveCursor(40, 0);
          window.PutCStringTruncated(1, strm.GetString().str().c_str());
        }

        window.MoveCursor(60, 0);
        if (frame)
          window.Printf("Frame: %3u  PC = 0x%16.16" PRIx64,
                        frame->GetFrameIndex(),
                        frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
                            exe_ctx.GetTargetPtr()));
      } else if (state == eStateExited) {
        const char *exit_desc = process->GetExitDescription();
        const int exit_status = process->GetExitStatus();
        if (exit_desc && exit_desc[0])
          window.Printf(" with status = %i (%s)", exit_status, exit_desc);
        else
          window.Printf(" with status = %i", exit_status);
      }
    }
    return true;
  }

protected:
  Debugger &m_debugger;
  FormatEntity::Entry m_format;
};

class SourceFileWindowDelegate : public WindowDelegate {
public:
  SourceFileWindowDelegate(Debugger &debugger)
      : WindowDelegate(), m_debugger(debugger) {}

  ~SourceFileWindowDelegate() override = default;

  void Update(const SymbolContext &sc) { m_sc = sc; }

  uint32_t NumVisibleLines() const { return m_max_y - m_min_y; }

  const char *WindowDelegateGetHelpText() override {
    return "Source/Disassembly window keyboard shortcuts:";
  }

  KeyHelp *WindowDelegateGetKeyHelp() override {
    static curses::KeyHelp g_source_view_key_help[] = {
        {KEY_RETURN, "Run to selected line with one shot breakpoint"},
        {KEY_UP, "Select previous source line"},
        {KEY_DOWN, "Select next source line"},
        {KEY_LEFT, "Scroll to the left"},
        {KEY_RIGHT, "Scroll to the right"},
        {KEY_PPAGE, "Page up"},
        {KEY_NPAGE, "Page down"},
        {'b', "Set breakpoint on selected source/disassembly line"},
        {'c', "Continue process"},
        {'D', "Detach with process suspended"},
        {'h', "Show help dialog"},
        {'n', "Step over (source line)"},
        {'N', "Step over (single instruction)"},
        {'f', "Step out (finish)"},
        {'s', "Step in (source line)"},
        {'S', "Step in (single instruction)"},
        {'u', "Frame up"},
        {'d', "Frame down"},
        {',', "Page up"},
        {'.', "Page down"},
        {'\0', nullptr}};
    return g_source_view_key_help;
  }

  bool WindowDelegateDraw(Window &window, bool force) override {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    Process *process = exe_ctx.GetProcessPtr();
    Thread *thread = nullptr;

    bool update_location = false;
    if (process) {
      StateType state = process->GetState();
      if (StateIsStoppedState(state, true)) {
        // We are stopped, so it is ok to
        update_location = true;
      }
    }

    m_min_x = 1;
    m_min_y = 2;
    m_max_x = window.GetMaxX() - 1;
    m_max_y = window.GetMaxY() - 1;

    const uint32_t num_visible_lines = NumVisibleLines();
    StackFrameSP frame_sp;
    bool set_selected_line_to_pc = false;

    if (update_location) {
      const bool process_alive = process->IsAlive();
      bool thread_changed = false;
      if (process_alive) {
        thread = exe_ctx.GetThreadPtr();
        if (thread) {
          frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);
          auto tid = thread->GetID();
          thread_changed = tid != m_tid;
          m_tid = tid;
        } else {
          if (m_tid != LLDB_INVALID_THREAD_ID) {
            thread_changed = true;
            m_tid = LLDB_INVALID_THREAD_ID;
          }
        }
      }
      const uint32_t stop_id = process ? process->GetStopID() : 0;
      const bool stop_id_changed = stop_id != m_stop_id;
      bool frame_changed = false;
      m_stop_id = stop_id;
      m_title.Clear();
      if (frame_sp) {
        m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything);
        if (m_sc.module_sp) {
          m_title.Printf(
              "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString());
          ConstString func_name = m_sc.GetFunctionName();
          if (func_name)
            m_title.Printf("`%s", func_name.GetCString());
        }
        const uint32_t frame_idx = frame_sp->GetFrameIndex();
        frame_changed = frame_idx != m_frame_idx;
        m_frame_idx = frame_idx;
      } else {
        m_sc.Clear(true);
        frame_changed = m_frame_idx != UINT32_MAX;
        m_frame_idx = UINT32_MAX;
      }

      const bool context_changed =
          thread_changed || frame_changed || stop_id_changed;

      if (process_alive) {
        if (m_sc.line_entry.IsValid()) {
          m_pc_line = m_sc.line_entry.line;
          if (m_pc_line != UINT32_MAX)
            --m_pc_line; // Convert to zero based line number...
          // Update the selected line if the stop ID changed...
          if (context_changed)
            m_selected_line = m_pc_line;

          if (m_file_sp && m_file_sp->GetSupportFile()->GetSpecOnly() ==
                               m_sc.line_entry.GetFile()) {
            // Same file, nothing to do, we should either have the lines or
            // not (source file missing)
            if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) {
              if (m_selected_line >= m_first_visible_line + num_visible_lines)
                m_first_visible_line = m_selected_line - 10;
            } else {
              if (m_selected_line > 10)
                m_first_visible_line = m_selected_line - 10;
              else
                m_first_visible_line = 0;
            }
          } else {
            // File changed, set selected line to the line with the PC
            m_selected_line = m_pc_line;
            m_file_sp =
                m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file_sp);
            if (m_file_sp) {
              const size_t num_lines = m_file_sp->GetNumLines();
              m_line_width = 1;
              for (size_t n = num_lines; n >= 10; n = n / 10)
                ++m_line_width;

              if (num_lines < num_visible_lines ||
                  m_selected_line < num_visible_lines)
                m_first_visible_line = 0;
              else
                m_first_visible_line = m_selected_line - 10;
            }
          }
        } else {
          m_file_sp.reset();
        }

        if (!m_file_sp || m_file_sp->GetNumLines() == 0) {
          // Show disassembly
          bool prefer_file_cache = false;
          if (m_sc.function) {
            if (m_disassembly_scope != m_sc.function) {
              m_disassembly_scope = m_sc.function;
              m_disassembly_sp = m_sc.function->GetInstructions(
                  exe_ctx, nullptr, !prefer_file_cache);
              if (m_disassembly_sp)
                set_selected_line_to_pc = true;
            } else {
              set_selected_line_to_pc = context_changed;
            }
          } else if (m_sc.symbol) {
            if (m_disassembly_scope != m_sc.symbol) {
              m_disassembly_scope = m_sc.symbol;
              m_disassembly_sp = m_sc.symbol->GetInstructions(
                  exe_ctx, nullptr, prefer_file_cache);
              if (m_disassembly_sp)
                set_selected_line_to_pc = true;
            } else {
              set_selected_line_to_pc = context_changed;
            }
          }
        }
      } else {
        m_pc_line = UINT32_MAX;
      }
    }

    const int window_width = window.GetWidth();
    window.Erase();
    window.DrawTitleBox("Sources");
    if (!m_title.GetString().empty()) {
      window.AttributeOn(A_REVERSE);
      window.MoveCursor(1, 1);
      window.PutChar(' ');
      window.PutCStringTruncated(1, m_title.GetString().str().c_str());
      int x = window.GetCursorX();
      if (x < window_width - 1) {
        window.Printf("%*s", window_width - x - 1, "");
      }
      window.AttributeOff(A_REVERSE);
    }

    Target *target = exe_ctx.GetTargetPtr();
    const size_t num_source_lines = GetNumSourceLines();
    if (num_source_lines > 0) {
      // Display source
      BreakpointLines bp_lines;
      if (target) {
        BreakpointList &bp_list = target->GetBreakpointList();
        const size_t num_bps = bp_list.GetSize();
        for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
          BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
          const size_t num_bps_locs = bp_sp->GetNumLocations();
          for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
            BreakpointLocationSP bp_loc_sp =
                bp_sp->GetLocationAtIndex(bp_loc_idx);
            LineEntry bp_loc_line_entry;
            if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
                    bp_loc_line_entry)) {
              if (m_file_sp->GetSupportFile()->GetSpecOnly() ==
                  bp_loc_line_entry.GetFile()) {
                bp_lines.insert(bp_loc_line_entry.line);
              }
            }
          }
        }
      }

      for (size_t i = 0; i < num_visible_lines; ++i) {
        const uint32_t curr_line = m_first_visible_line + i;
        if (curr_line < num_source_lines) {
          const int line_y = m_min_y + i;
          window.MoveCursor(1, line_y);
          const bool is_pc_line = curr_line == m_pc_line;
          const bool line_is_selected = m_selected_line == curr_line;
          // Highlight the line as the PC line first (done by passing
          // argument to OutputColoredStringTruncated()), then if the selected
          // line isn't the same as the PC line, highlight it differently.
          attr_t highlight_attr = 0;
          attr_t bp_attr = 0;
          if (line_is_selected && !is_pc_line)
            highlight_attr = A_REVERSE;

          if (bp_lines.find(curr_line + 1) != bp_lines.end())
            bp_attr = COLOR_PAIR(BlackOnWhite);

          if (bp_attr)
            window.AttributeOn(bp_attr);

          window.Printf(" %*u ", m_line_width, curr_line + 1);

          if (bp_attr)
            window.AttributeOff(bp_attr);

          window.PutChar(ACS_VLINE);
          // Mark the line with the PC with a diamond
          if (is_pc_line)
            window.PutChar(ACS_DIAMOND);
          else
            window.PutChar(' ');

          if (highlight_attr)
            window.AttributeOn(highlight_attr);

          StreamString lineStream;

          std::optional<size_t> column;
          if (is_pc_line && m_sc.line_entry.IsValid() && m_sc.line_entry.column)
            column = m_sc.line_entry.column - 1;
          m_file_sp->DisplaySourceLines(curr_line + 1, column, 0, 0,
                                        &lineStream);
          StringRef line = lineStream.GetString();
          if (line.ends_with("\n"))
            line = line.drop_back();
          bool wasWritten = window.OutputColoredStringTruncated(
              1, line, m_first_visible_column, is_pc_line);
          if (!wasWritten && (line_is_selected || is_pc_line)) {
            // Draw an empty space to show the selected/PC line if empty,
            // or draw '<' if nothing is visible because of scrolling too much
            // to the right.
            window.PutCStringTruncated(
                1, line.empty() && m_first_visible_column == 0 ? " " : "<");
          }

          if (is_pc_line && frame_sp &&
              frame_sp->GetConcreteFrameIndex() == 0) {
            StopInfoSP stop_info_sp;
            if (thread)
              stop_info_sp = thread->GetStopInfo();
            if (stop_info_sp) {
              const char *stop_description = stop_info_sp->GetDescription();
              if (stop_description && stop_description[0]) {
                size_t stop_description_len = strlen(stop_description);
                int desc_x = window_width - stop_description_len - 16;
                if (desc_x - window.GetCursorX() > 0)
                  window.Printf("%*s", desc_x - window.GetCursorX(), "");
                window.MoveCursor(window_width - stop_description_len - 16,
                                  line_y);
                const attr_t stop_reason_attr = COLOR_PAIR(WhiteOnBlue);
                window.AttributeOn(stop_reason_attr);
                window.PrintfTruncated(1, " <<< Thread %u: %s ",
                                       thread->GetIndexID(), stop_description);
                window.AttributeOff(stop_reason_attr);
              }
            } else {
              window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
            }
          }
          if (highlight_attr)
            window.AttributeOff(highlight_attr);
        } else {
          break;
        }
      }
    } else {
      size_t num_disassembly_lines = GetNumDisassemblyLines();
      if (num_disassembly_lines > 0) {
        // Display disassembly
        BreakpointAddrs bp_file_addrs;
        Target *target = exe_ctx.GetTargetPtr();
        if (target) {
          BreakpointList &bp_list = target->GetBreakpointList();
          const size_t num_bps = bp_list.GetSize();
          for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
            BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
            const size_t num_bps_locs = bp_sp->GetNumLocations();
            for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs;
                 ++bp_loc_idx) {
              BreakpointLocationSP bp_loc_sp =
                  bp_sp->GetLocationAtIndex(bp_loc_idx);
              bp_file_addrs.insert(bp_loc_sp->GetAddress().GetFileAddress());
            }
          }
        }

        const attr_t selected_highlight_attr = A_REVERSE;
        const attr_t pc_highlight_attr = COLOR_PAIR(WhiteOnBlue);

        StreamString strm;

        InstructionList &insts = m_disassembly_sp->GetInstructionList();
        Address pc_address;

        if (frame_sp)
          pc_address = frame_sp->GetFrameCodeAddress();
        const uint32_t pc_idx =
            pc_address.IsValid()
                ? insts.GetIndexOfInstructionAtAddress(pc_address)
                : UINT32_MAX;
        if (set_selected_line_to_pc) {
          m_selected_line = pc_idx;
        }

        const uint32_t non_visible_pc_offset = (num_visible_lines / 5);
        if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines)
          m_first_visible_line = 0;

        if (pc_idx < num_disassembly_lines) {
          if (pc_idx < static_cast<uint32_t>(m_first_visible_line) ||
              pc_idx >= m_first_visible_line + num_visible_lines)
            m_first_visible_line = pc_idx - non_visible_pc_offset;
        }

        for (size_t i = 0; i < num_visible_lines; ++i) {
          const uint32_t inst_idx = m_first_visible_line + i;
          Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get();
          if (!inst)
            break;

          const int line_y = m_min_y + i;
          window.MoveCursor(1, line_y);
          const bool is_pc_line = frame_sp && inst_idx == pc_idx;
          const bool line_is_selected = m_selected_line == inst_idx;
          // Highlight the line as the PC line first, then if the selected
          // line isn't the same as the PC line, highlight it differently
          attr_t highlight_attr = 0;
          attr_t bp_attr = 0;
          if (is_pc_line)
            highlight_attr = pc_highlight_attr;
          else if (line_is_selected)
            highlight_attr = selected_highlight_attr;

          if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) !=
              bp_file_addrs.end())
            bp_attr = COLOR_PAIR(BlackOnWhite);

          if (bp_attr)
            window.AttributeOn(bp_attr);

          window.Printf(" 0x%16.16llx ",
                        static_cast<unsigned long long>(
                            inst->GetAddress().GetLoadAddress(target)));

          if (bp_attr)
            window.AttributeOff(bp_attr);

          window.PutChar(ACS_VLINE);
          // Mark the line with the PC with a diamond
          if (is_pc_line)
            window.PutChar(ACS_DIAMOND);
          else
            window.PutChar(' ');

          if (highlight_attr)
            window.AttributeOn(highlight_attr);

          const char *mnemonic = inst->GetMnemonic(&exe_ctx);
          const char *operands = inst->GetOperands(&exe_ctx);
          const char *comment = inst->GetComment(&exe_ctx);

          if (mnemonic != nullptr && mnemonic[0] == '\0')
            mnemonic = nullptr;
          if (operands != nullptr && operands[0] == '\0')
            operands = nullptr;
          if (comment != nullptr && comment[0] == '\0')
            comment = nullptr;

          strm.Clear();

          if (mnemonic != nullptr && operands != nullptr && comment != nullptr)
            strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment);
          else if (mnemonic != nullptr && operands != nullptr)
            strm.Printf("%-8s %s", mnemonic, operands);
          else if (mnemonic != nullptr)
            strm.Printf("%s", mnemonic);

          int right_pad = 1;
          window.PutCStringTruncated(
              right_pad,
              strm.GetString().substr(m_first_visible_column).data());

          if (is_pc_line && frame_sp &&
              frame_sp->GetConcreteFrameIndex() == 0) {
            StopInfoSP stop_info_sp;
            if (thread)
              stop_info_sp = thread->GetStopInfo();
            if (stop_info_sp) {
              const char *stop_description = stop_info_sp->GetDescription();
              if (stop_description && stop_description[0]) {
                size_t stop_description_len = strlen(stop_description);
                int desc_x = window_width - stop_description_len - 16;
                if (desc_x - window.GetCursorX() > 0)
                  window.Printf("%*s", desc_x - window.GetCursorX(), "");
                window.MoveCursor(window_width - stop_description_len - 15,
                                  line_y);
                if (thread)
                  window.PrintfTruncated(1, "<<< Thread %u: %s ",
                                         thread->GetIndexID(),
                                         stop_description);
              }
            } else {
              window.Printf("%*s", window_width - window.GetCursorX() - 1, "");
            }
          }
          if (highlight_attr)
            window.AttributeOff(highlight_attr);
        }
      }
    }
    return true; // Drawing handled
  }

  size_t GetNumLines() {
    size_t num_lines = GetNumSourceLines();
    if (num_lines == 0)
      num_lines = GetNumDisassemblyLines();
    return num_lines;
  }

  size_t GetNumSourceLines() const {
    if (m_file_sp)
      return m_file_sp->GetNumLines();
    return 0;
  }

  size_t GetNumDisassemblyLines() const {
    if (m_disassembly_sp)
      return m_disassembly_sp->GetInstructionList().GetSize();
    return 0;
  }

  HandleCharResult WindowDelegateHandleChar(Window &window, int c) override {
    const uint32_t num_visible_lines = NumVisibleLines();
    const size_t num_lines = GetNumLines();

    switch (c) {
    case ',':
    case KEY_PPAGE:
      // Page up key
      if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines)
        m_first_visible_line -= num_visible_lines;
      else
        m_first_visible_line = 0;
      m_selected_line = m_first_visible_line;
      return eKeyHandled;

    case '.':
    case KEY_NPAGE:
      // Page down key
      {
        if (m_first_visible_line + num_visible_lines < num_lines)
          m_first_visible_line += num_visible_lines;
        else if (num_lines < num_visible_lines)
          m_first_visible_line = 0;
        else
          m_first_visible_line = num_lines - num_visible_lines;
        m_selected_line = m_first_visible_line;
      }
      return eKeyHandled;

    case KEY_UP:
      if (m_selected_line > 0) {
        m_selected_line--;
        if (static_cast<size_t>(m_first_visible_line) > m_selected_line)
          m_first_visible_line = m_selected_line;
      }
      return eKeyHandled;

    case KEY_DOWN:
      if (m_selected_line + 1 < num_lines) {
        m_selected_line++;
        if (m_first_visible_line + num_visible_lines < m_selected_line)
          m_first_visible_line++;
      }
      return eKeyHandled;

    case KEY_LEFT:
      if (m_first_visible_column > 0)
        --m_first_visible_column;
      return eKeyHandled;

    case KEY_RIGHT:
      ++m_first_visible_column;
      return eKeyHandled;

    case '\r':
    case '\n':
    case KEY_ENTER:
      // Set a breakpoint and run to the line using a one shot breakpoint
      if (GetNumSourceLines() > 0) {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) {
          BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
              nullptr, // Don't limit the breakpoint to certain modules
              m_file_sp->GetSupportFile()->GetSpecOnly(), // Source file
              m_selected_line +
                  1, // Source line number (m_selected_line is zero based)
              0,     // Unspecified column.
              0,     // No offset
              eLazyBoolCalculate,  // Check inlines using global setting
              eLazyBoolCalculate,  // Skip prologue using global setting,
              false,               // internal
              false,               // request_hardware
              eLazyBoolCalculate); // move_to_nearest_code
          // Make breakpoint one shot
          bp_sp->GetOptions().SetOneShot(true);
          exe_ctx.GetProcessRef().Resume();
        }
      } else if (m_selected_line < GetNumDisassemblyLines()) {
        const Instruction *inst = m_disassembly_sp->GetInstructionList()
                                      .GetInstructionAtIndex(m_selected_line)
                                      .get();
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasTargetScope()) {
          Address addr = inst->GetAddress();
          BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
              addr,   // lldb_private::Address
              false,  // internal
              false); // request_hardware
          // Make breakpoint one shot
          bp_sp->GetOptions().SetOneShot(true);
          exe_ctx.GetProcessRef().Resume();
        }
      }
      return eKeyHandled;

    case 'b': // 'b' == toggle breakpoint on currently selected line
      ToggleBreakpointOnSelectedLine();
      return eKeyHandled;

    case 'D': // 'D' == detach and keep stopped
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasProcessScope())
        exe_ctx.GetProcessRef().Detach(true);
    }
      return eKeyHandled;

    case 'c':
      // 'c' == continue
      {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasProcessScope())
          exe_ctx.GetProcessRef().Resume();
      }
      return eKeyHandled;

    case 'f':
      // 'f' == step out (finish)
      {
        ExecutionContext exe_ctx =
            m_debugger.GetCommandInterpreter().GetExecutionContext();
        if (exe_ctx.HasThreadScope() &&
            StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
          Thread *thread = exe_ctx.GetThreadPtr();
          uint32_t frame_idx =
              thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
          exe_ctx.GetThreadRef().StepOut(frame_idx);
        }
      }
      return eKeyHandled;

    case 'n': // 'n' == step over
    case 'N': // 'N' == step over instruction
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope() &&
          StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
        bool source_step = (c == 'n');
        exe_ctx.GetThreadRef().StepOver(source_step);
      }
    }
      return eKeyHandled;

    case 's': // 's' == step into
    case 'S': // 'S' == step into instruction
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope() &&
          StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) {
        bool source_step = (c == 's');
        exe_ctx.GetThreadRef().StepIn(source_step);
      }
    }
      return eKeyHandled;

    case 'u': // 'u' == frame up
    case 'd': // 'd' == frame down
    {
      ExecutionContext exe_ctx =
          m_debugger.GetCommandInterpreter().GetExecutionContext();
      if (exe_ctx.HasThreadScope()) {
        Thread *thread = exe_ctx.GetThreadPtr();
        uint32_t frame_idx =
            thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
        if (frame_idx == UINT32_MAX)
          frame_idx = 0;
        if (c == 'u' && frame_idx + 1 < thread->GetStackFrameCount())
          ++frame_idx;
        else if (c == 'd' && frame_idx > 0)
          --frame_idx;
        if (thread->SetSelectedFrameByIndex(frame_idx, true))
          exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
      }
    }
      return eKeyHandled;

    case 'h':
      window.CreateHelpSubwindow();
      return eKeyHandled;

    default:
      break;
    }
    return eKeyNotHandled;
  }

  void ToggleBreakpointOnSelectedLine() {
    ExecutionContext exe_ctx =
        m_debugger.GetCommandInterpreter().GetExecutionContext();
    if (!exe_ctx.HasTargetScope())
      return;
    if (GetNumSourceLines() > 0) {
      // Source file breakpoint.
      BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
      const size_t num_bps = bp_list.GetSize();
      for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
        BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
        const size_t num_bps_locs = bp_sp->GetNumLocations();
        for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
          BreakpointLocationSP bp_loc_sp =
              bp_sp->GetLocationAtIndex(bp_loc_idx);
          LineEntry bp_loc_line_entry;
          if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry(
                  bp_loc_line_entry)) {
            if (m_file_sp->GetSupportFile()->GetSpecOnly() ==
                    bp_loc_line_entry.GetFile() &&
                m_selected_line + 1 == bp_loc_line_entry.line) {
              bool removed =
                  exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
              assert(removed);
              UNUSED_IF_ASSERT_DISABLED(removed);
              return; // Existing breakpoint removed.
            }
          }
        }
      }
      // No breakpoint found on the location, add it.
      BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(
          nullptr, // Don't limit the breakpoint to certain modules
          m_file_sp->GetSupportFile()->GetSpecOnly(), // Source file
          m_selected_line +
              1, // Source line number (m_selected_line is zero based)
          0,     // No column specified.
          0,     // No offset
          eLazyBoolCalculate,  // Check inlines using global setting
          eLazyBoolCalculate,  // Skip prologue using global setting,
          false,               // internal
          false,               // request_hardware
          eLazyBoolCalculate); // move_to_nearest_code
    } else {
      // Disassembly breakpoint.
      assert(GetNumDisassemblyLines() > 0);
      assert(m_selected_line < GetNumDisassemblyLines());
      const Instruction *inst = m_disassembly_sp->GetInstructionList()
                                    .GetInstructionAtIndex(m_selected_line)
                                    .get();
      Address addr = inst->GetAddress();
      // Try to find it.
      BreakpointList &bp_list = exe_ctx.GetTargetRef().GetBreakpointList();
      const size_t num_bps = bp_list.GetSize();
      for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) {
        BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx);
        const size_t num_bps_locs = bp_sp->GetNumLocations();
        for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) {
          BreakpointLocationSP bp_loc_sp =
              bp_sp->GetLocationAtIndex(bp_loc_idx);
          LineEntry bp_loc_line_entry;
          const lldb::addr_t file_addr =
              bp_loc_sp->GetAddress().GetFileAddress();
          if (file_addr == addr.GetFileAddress()) {
            bool removed =
                exe_ctx.GetTargetRef().RemoveBreakpointByID(bp_sp->GetID());
            assert(removed);
            UNUSED_IF_ASSERT_DISABLED(removed);
            return; // Existing breakpoint removed.
          }
        }
      }
      // No breakpoint found on the address, add it.
      BreakpointSP bp_sp =
          exe_ctx.GetTargetRef().CreateBreakpoint(addr, // lldb_private::Address
                                                  false,  // internal
                                                  false); // request_hardware
    }
  }

protected:
  typedef std::set<uint32_t> BreakpointLines;
  typedef std::set<lldb::addr_t> BreakpointAddrs;

  Debugger &m_debugger;
  SymbolContext m_sc;
  SourceManager::FileSP m_file_sp;
  SymbolContextScope *m_disassembly_scope = nullptr;
  lldb::DisassemblerSP m_disassembly_sp;
  StreamString m_title;
  lldb::user_id_t m_tid = LLDB_INVALID_THREAD_ID;
  int m_line_width = 4;
  uint32_t m_selected_line = 0; // The selected line
  uint32_t m_pc_line = 0;       // The line with the PC
  uint32_t m_stop_id = 0;
  uint32_t m_frame_idx = UINT32_MAX;
  int m_first_visible_line = 0;
  int m_first_visible_column = 0;
  int m_min_x = 0;
  int m_min_y = 0;
  int m_max_x = 0;
  int m_max_y = 0;
};

DisplayOptions ValueObjectListDelegate::g_options = {true};

IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger)
    : IOHandler(debugger, IOHandler::Type::Curses) {}

void IOHandlerCursesGUI::Activate() {
  IOHandler::Activate();
  if (!m_app_up) {
    m_app_up = std::make_unique<Application>(
        m_input_sp ? m_input_sp->GetStream() : nullptr,
        m_output_sp ? m_input_sp->GetStream() : nullptr);

    // This is both a window and a menu delegate
    std::shared_ptr<ApplicationDelegate> app_delegate_sp(
        new ApplicationDelegate(*m_app_up, m_debugger));

    MenuDelegateSP app_menu_delegate_sp =
        std::static_pointer_cast<MenuDelegate>(app_delegate_sp);
    MenuSP lldb_menu_sp(
        new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB));
    MenuSP exit_menuitem_sp(
        new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
    exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
    lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
        "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
    lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
    lldb_menu_sp->AddSubmenu(exit_menuitem_sp);

    MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
                                   ApplicationDelegate::eMenuID_Target));
    target_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
    target_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));

    MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
                                    ApplicationDelegate::eMenuID_Process));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Detach and resume", nullptr, 'd',
                        ApplicationDelegate::eMenuID_ProcessDetachResume)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Detach suspended", nullptr, 's',
                        ApplicationDelegate::eMenuID_ProcessDetachSuspended)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
    process_menu_sp->AddSubmenu(
        MenuSP(new Menu("Continue", nullptr, 'c',
                        ApplicationDelegate::eMenuID_ProcessContinue)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
    process_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));

    MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
                                   ApplicationDelegate::eMenuID_Thread));
    thread_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
    thread_menu_sp->AddSubmenu(
        MenuSP(new Menu("Step Over", nullptr, 'v',
                        ApplicationDelegate::eMenuID_ThreadStepOver)));
    thread_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));

    MenuSP view_menu_sp(
        new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Backtrace", nullptr, 't',
                        ApplicationDelegate::eMenuID_ViewBacktrace)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Registers", nullptr, 'r',
                        ApplicationDelegate::eMenuID_ViewRegisters)));
    view_menu_sp->AddSubmenu(MenuSP(new Menu(
        "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Variables", nullptr, 'v',
                        ApplicationDelegate::eMenuID_ViewVariables)));
    view_menu_sp->AddSubmenu(
        MenuSP(new Menu("Breakpoints", nullptr, 'b',
                        ApplicationDelegate::eMenuID_ViewBreakpoints)));

    MenuSP help_menu_sp(
        new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
    help_menu_sp->AddSubmenu(MenuSP(new Menu(
        "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));

    m_app_up->Initialize();
    WindowSP &main_window_sp = m_app_up->GetMainWindow();

    MenuSP menubar_sp(new Menu(Menu::Type::Bar));
    menubar_sp->AddSubmenu(lldb_menu_sp);
    menubar_sp->AddSubmenu(target_menu_sp);
    menubar_sp->AddSubmenu(process_menu_sp);
    menubar_sp->AddSubmenu(thread_menu_sp);
    menubar_sp->AddSubmenu(view_menu_sp);
    menubar_sp->AddSubmenu(help_menu_sp);
    menubar_sp->SetDelegate(app_menu_delegate_sp);

    Rect content_bounds = main_window_sp->GetFrame();
    Rect menubar_bounds = content_bounds.MakeMenuBar();
    Rect status_bounds = content_bounds.MakeStatusBar();
    Rect source_bounds;
    Rect variables_bounds;
    Rect threads_bounds;
    Rect source_variables_bounds;
    content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds,
                                           threads_bounds);
    source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds,
                                                      variables_bounds);

    WindowSP menubar_window_sp =
        main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false);
    // Let the menubar get keys if the active window doesn't handle the keys
    // that are typed so it can respond to menubar key presses.
    menubar_window_sp->SetCanBeActive(
        false); // Don't let the menubar become the active window
    menubar_window_sp->SetDelegate(menubar_sp);

    WindowSP source_window_sp(
        main_window_sp->CreateSubWindow("Source", source_bounds, true));
    WindowSP variables_window_sp(
        main_window_sp->CreateSubWindow("Variables", variables_bounds, false));
    WindowSP threads_window_sp(
        main_window_sp->CreateSubWindow("Threads", threads_bounds, false));
    WindowSP status_window_sp(
        main_window_sp->CreateSubWindow("Status", status_bounds, false));
    status_window_sp->SetCanBeActive(
        false); // Don't let the status bar become the active window
    main_window_sp->SetDelegate(
        std::static_pointer_cast<WindowDelegate>(app_delegate_sp));
    source_window_sp->SetDelegate(
        WindowDelegateSP(new SourceFileWindowDelegate(m_debugger)));
    variables_window_sp->SetDelegate(
        WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger)));
    TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger));
    threads_window_sp->SetDelegate(WindowDelegateSP(
        new TreeWindowDelegate(m_debugger, thread_delegate_sp)));
    status_window_sp->SetDelegate(
        WindowDelegateSP(new StatusBarWindowDelegate(m_debugger)));

    // All colors with black background.
    init_pair(1, COLOR_BLACK, COLOR_BLACK);
    init_pair(2, COLOR_RED, COLOR_BLACK);
    init_pair(3, COLOR_GREEN, COLOR_BLACK);
    init_pair(4, COLOR_YELLOW, COLOR_BLACK);
    init_pair(5, COLOR_BLUE, COLOR_BLACK);
    init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
    init_pair(7, COLOR_CYAN, COLOR_BLACK);
    init_pair(8, COLOR_WHITE, COLOR_BLACK);
    // All colors with blue background.
    init_pair(9, COLOR_BLACK, COLOR_BLUE);
    init_pair(10, COLOR_RED, COLOR_BLUE);
    init_pair(11, COLOR_GREEN, COLOR_BLUE);
    init_pair(12, COLOR_YELLOW, COLOR_BLUE);
    init_pair(13, COLOR_BLUE, COLOR_BLUE);
    init_pair(14, COLOR_MAGENTA, COLOR_BLUE);
    init_pair(15, COLOR_CYAN, COLOR_BLUE);
    init_pair(16, COLOR_WHITE, COLOR_BLUE);
    // These must match the order in the color indexes enum.
    init_pair(17, COLOR_BLACK, COLOR_WHITE);
    init_pair(18, COLOR_MAGENTA, COLOR_WHITE);
    static_assert(LastColorPairIndex == 18, "Color indexes do not match.");

    define_key("\033[Z", KEY_SHIFT_TAB);
    define_key("\033\015", KEY_ALT_ENTER);
  }
}

void IOHandlerCursesGUI::Deactivate() { m_app_up->Terminate(); }

void IOHandlerCursesGUI::Run() {
  m_app_up->Run(m_debugger);
  SetIsDone(true);
}

IOHandlerCursesGUI::~IOHandlerCursesGUI() = default;

void IOHandlerCursesGUI::Cancel() {}

bool IOHandlerCursesGUI::Interrupt() {
  return m_debugger.GetCommandInterpreter().IOHandlerInterrupt(*this);
}

void IOHandlerCursesGUI::GotEOF() {}

void IOHandlerCursesGUI::TerminalSizeChanged() {
  m_app_up->TerminalSizeChanged();
}

#endif // LLDB_ENABLE_CURSES
