//===-- IOHandler.cpp -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//


#include "lldb/lldb-python.h"

#include <string>

#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectRegister.h"
#ifndef LLDB_DISABLE_LIBEDIT
#include "lldb/Host/Editline.h"
#endif
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/ThreadPlan.h"

#ifndef LLDB_DISABLE_CURSES
#include <ncurses.h>
#include <panel.h>
#endif

using namespace lldb;
using namespace lldb_private;

IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) :
    IOHandler (debugger,
               type,
               StreamFileSP(),  // Adopt STDIN from top input reader
               StreamFileSP(),  // Adopt STDOUT from top input reader
               StreamFileSP(),  // Adopt STDERR from top input reader
               0)               // Flags
{
}


IOHandler::IOHandler (Debugger &debugger,
                      IOHandler::Type type,
                      const lldb::StreamFileSP &input_sp,
                      const lldb::StreamFileSP &output_sp,
                      const lldb::StreamFileSP &error_sp,
                      uint32_t flags) :
    m_debugger (debugger),
    m_input_sp (input_sp),
    m_output_sp (output_sp),
    m_error_sp (error_sp),
    m_popped (false),
    m_flags (flags),
    m_type (type),
    m_user_data (NULL),
    m_done (false),
    m_active (false)
{
    // If any files are not specified, then adopt them from the top input reader.
    if (!m_input_sp || !m_output_sp || !m_error_sp)
        debugger.AdoptTopIOHandlerFilesIfInvalid (m_input_sp,
                                                  m_output_sp,
                                                  m_error_sp);
}

IOHandler::~IOHandler()
{
}


int
IOHandler::GetInputFD()
{
    if (m_input_sp)
        return m_input_sp->GetFile().GetDescriptor();
    return -1;
}

int
IOHandler::GetOutputFD()
{
    if (m_output_sp)
        return m_output_sp->GetFile().GetDescriptor();
    return -1;
}

int
IOHandler::GetErrorFD()
{
    if (m_error_sp)
        return m_error_sp->GetFile().GetDescriptor();
    return -1;
}

FILE *
IOHandler::GetInputFILE()
{
    if (m_input_sp)
        return m_input_sp->GetFile().GetStream();
    return NULL;
}

FILE *
IOHandler::GetOutputFILE()
{
    if (m_output_sp)
        return m_output_sp->GetFile().GetStream();
    return NULL;
}

FILE *
IOHandler::GetErrorFILE()
{
    if (m_error_sp)
        return m_error_sp->GetFile().GetStream();
    return NULL;
}

StreamFileSP &
IOHandler::GetInputStreamFile()
{
    return m_input_sp;
}

StreamFileSP &
IOHandler::GetOutputStreamFile()
{
    return m_output_sp;
}


StreamFileSP &
IOHandler::GetErrorStreamFile()
{
    return m_error_sp;
}

bool
IOHandler::GetIsInteractive ()
{
    return GetInputStreamFile()->GetFile().GetIsInteractive ();
}

bool
IOHandler::GetIsRealTerminal ()
{
    return GetInputStreamFile()->GetFile().GetIsRealTerminal();
}

void
IOHandler::SetPopped (bool b)
{
    m_popped.SetValue(b, eBroadcastOnChange);
}

void
IOHandler::WaitForPop ()
{
    m_popped.WaitForValueEqualTo(true);
}

IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger,
                                    const char *prompt,
                                    bool default_response) :
    IOHandlerEditline(debugger,
                      IOHandler::Type::Confirm,
                      NULL,     // NULL editline_name means no history loaded/saved
                      NULL,     // No prompt
                      NULL,     // No continuation prompt
                      false,    // Multi-line
                      false,    // Don't colorize the prompt (i.e. the confirm message.)
                      0,
                      *this),
    m_default_response (default_response),
    m_user_response (default_response)
{
    StreamString prompt_stream;
    prompt_stream.PutCString(prompt);
    if (m_default_response)
        prompt_stream.Printf(": [Y/n] ");
    else
        prompt_stream.Printf(": [y/N] ");
    
    SetPrompt (prompt_stream.GetString().c_str());
    
}


IOHandlerConfirm::~IOHandlerConfirm ()
{
}

int
IOHandlerConfirm::IOHandlerComplete (IOHandler &io_handler,
                                     const char *current_line,
                                     const char *cursor,
                                     const char *last_char,
                                     int skip_first_n_matches,
                                     int max_matches,
                                     StringList &matches)
{
    if (current_line == cursor)
    {
        if (m_default_response)
        {
            matches.AppendString("y");
        }
        else
        {
            matches.AppendString("n");
        }
    }
    return matches.GetSize();
}

void
IOHandlerConfirm::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
{
    if (line.empty())
    {
        // User just hit enter, set the response to the default
        m_user_response = m_default_response;
        io_handler.SetIsDone(true);
        return;
    }

    if (line.size() == 1)
    {
        switch (line[0])
        {
            case 'y':
            case 'Y':
                m_user_response = true;
                io_handler.SetIsDone(true);
                return;
            case 'n':
            case 'N':
                m_user_response = false;
                io_handler.SetIsDone(true);
                return;
            default:
                break;
        }
    }

    if (line == "yes" || line == "YES" || line == "Yes")
    {
        m_user_response = true;
        io_handler.SetIsDone(true);
    }
    else if (line == "no" || line == "NO" || line == "No")
    {
        m_user_response = false;
        io_handler.SetIsDone(true);
    }
}

int
IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler,
                                      const char *current_line,
                                      const char *cursor,
                                      const char *last_char,
                                      int skip_first_n_matches,
                                      int max_matches,
                                      StringList &matches)
{
    switch (m_completion)
    {
    case Completion::None:
        break;

    case Completion::LLDBCommand:
        return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion (current_line,
                                                                                  cursor,
                                                                                  last_char,
                                                                                  skip_first_n_matches,
                                                                                  max_matches,
                                                                                  matches);

    case Completion::Expression:
        {
            bool word_complete = false;
            const char *word_start = cursor;
            if (cursor > current_line)
                --word_start;
            while (word_start > current_line && !isspace(*word_start))
                --word_start;
            CommandCompletions::InvokeCommonCompletionCallbacks (io_handler.GetDebugger().GetCommandInterpreter(),
                                                                 CommandCompletions::eVariablePathCompletion,
                                                                 word_start,
                                                                 skip_first_n_matches,
                                                                 max_matches,
                                                                 NULL,
                                                                 word_complete,
                                                                 matches);
            
            size_t num_matches = matches.GetSize();
            if (num_matches > 0)
            {
                std::string common_prefix;
                matches.LongestCommonPrefix (common_prefix);
                const size_t partial_name_len = strlen(word_start);
                
                // If we matched a unique single command, add a space...
                // Only do this if the completer told us this was a complete word, however...
                if (num_matches == 1 && word_complete)
                {
                    common_prefix.push_back(' ');
                }
                common_prefix.erase (0, partial_name_len);
                matches.InsertStringAtIndex(0, std::move(common_prefix));
            }
            return num_matches;
        }
        break;
    }
    
    
    return 0;
}


IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
                                      IOHandler::Type type,
                                      const char *editline_name, // Used for saving history files
                                      const char *prompt,
                                      const char *continuation_prompt,
                                      bool multi_line,
                                      bool color_prompts,
                                      uint32_t line_number_start,
                                      IOHandlerDelegate &delegate) :
    IOHandlerEditline(debugger,
                      type,
                      StreamFileSP(), // Inherit input from top input reader
                      StreamFileSP(), // Inherit output from top input reader
                      StreamFileSP(), // Inherit error from top input reader
                      0,              // Flags
                      editline_name,  // Used for saving history files
                      prompt,
                      continuation_prompt,
                      multi_line,
                      color_prompts,
                      line_number_start,
                      delegate)
{
}

IOHandlerEditline::IOHandlerEditline (Debugger &debugger,
                                      IOHandler::Type type,
                                      const lldb::StreamFileSP &input_sp,
                                      const lldb::StreamFileSP &output_sp,
                                      const lldb::StreamFileSP &error_sp,
                                      uint32_t flags,
                                      const char *editline_name, // Used for saving history files
                                      const char *prompt,
                                      const char *continuation_prompt,
                                      bool multi_line,
                                      bool color_prompts,
                                      uint32_t line_number_start,
                                      IOHandlerDelegate &delegate) :
    IOHandler (debugger, type, input_sp, output_sp, error_sp, flags),
#ifndef LLDB_DISABLE_LIBEDIT
    m_editline_ap (),
#endif
    m_delegate (delegate),
    m_prompt (),
    m_continuation_prompt(),
    m_current_lines_ptr (NULL),
    m_base_line_number (line_number_start),
    m_curr_line_idx (UINT32_MAX),
    m_multi_line (multi_line),
    m_color_prompts (color_prompts),
    m_interrupt_exits (true)
{
    SetPrompt(prompt);

#ifndef LLDB_DISABLE_LIBEDIT
    bool use_editline = false;
    
    use_editline = m_input_sp->GetFile().GetIsRealTerminal();

    if (use_editline)
    {
        m_editline_ap.reset(new Editline (editline_name,
                                          GetInputFILE (),
                                          GetOutputFILE (),
                                          GetErrorFILE (),
                                          m_color_prompts));
        m_editline_ap->SetIsInputCompleteCallback (IsInputCompleteCallback, this);
        m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this);
        // See if the delegate supports fixing indentation
        const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters();
        if (indent_chars)
        {
            // The delegate does support indentation, hook it up so when any indentation
            // character is typed, the delegate gets a chance to fix it
            m_editline_ap->SetFixIndentationCallback (FixIndentationCallback, this, indent_chars);
        }
    }
#endif
    SetBaseLineNumber (m_base_line_number);
    SetPrompt(prompt ? prompt : "");
    SetContinuationPrompt(continuation_prompt);    
}

IOHandlerEditline::~IOHandlerEditline ()
{
#ifndef LLDB_DISABLE_LIBEDIT
    m_editline_ap.reset();
#endif
}

void
IOHandlerEditline::Activate ()
{
    IOHandler::Activate();
    m_delegate.IOHandlerActivated(*this);
}

void
IOHandlerEditline::Deactivate ()
{
    IOHandler::Deactivate();
    m_delegate.IOHandlerDeactivated(*this);
}


bool
IOHandlerEditline::GetLine (std::string &line, bool &interrupted)
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
    {
        return m_editline_ap->GetLine (line, interrupted);
    }
    else
    {
#endif
        line.clear();

        FILE *in = GetInputFILE();
        if (in)
        {
            if (GetIsInteractive())
            {
                const char *prompt = NULL;
                
                if (m_multi_line && m_curr_line_idx > 0)
                    prompt = GetContinuationPrompt();
                
                if (prompt == NULL)
                    prompt = GetPrompt();
                
                if (prompt && prompt[0])
                {
                    FILE *out = GetOutputFILE();
                    if (out)
                    {
                        ::fprintf(out, "%s", prompt);
                        ::fflush(out);
                    }
                }
            }
            char buffer[256];
            bool done = false;
            bool got_line = false;
            while (!done)
            {
                if (fgets(buffer, sizeof(buffer), in) == NULL)
                {
                    const int saved_errno = errno;
                    if (feof(in))
                        done = true;
                    else if (ferror(in))
                    {
                        if (saved_errno != EINTR)
                            done = true;
                    }
                }
                else
                {
                    got_line = true;
                    size_t buffer_len = strlen(buffer);
                    assert (buffer[buffer_len] == '\0');
                    char last_char = buffer[buffer_len-1];
                    if (last_char == '\r' || last_char == '\n')
                    {
                        done = true;
                        // Strip trailing newlines
                        while (last_char == '\r' || last_char == '\n')
                        {
                            --buffer_len;
                            if (buffer_len == 0)
                                break;
                            last_char = buffer[buffer_len-1];
                        }
                    }
                    line.append(buffer, buffer_len);
                }
            }
            // We might have gotten a newline on a line by itself
            // make sure to return true in this case.
            return got_line;
        }
        else
        {
            // No more input file, we are done...
            SetIsDone(true);
        }
        return false;
#ifndef LLDB_DISABLE_LIBEDIT
    }
#endif
}


#ifndef LLDB_DISABLE_LIBEDIT
bool
IOHandlerEditline::IsInputCompleteCallback (Editline *editline,
                                          StringList &lines,
                                          void *baton)
{
    IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
    return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader, lines);
}

int
IOHandlerEditline::FixIndentationCallback (Editline *editline,
                                           const StringList &lines,
                                           int cursor_position,
                                           void *baton)
{
    IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
    return editline_reader->m_delegate.IOHandlerFixIndentation(*editline_reader, lines, cursor_position);
}

int
IOHandlerEditline::AutoCompleteCallback (const char *current_line,
                                         const char *cursor,
                                         const char *last_char,
                                         int skip_first_n_matches,
                                         int max_matches,
                                         StringList &matches,
                                         void *baton)
{
    IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton;
    if (editline_reader)
        return editline_reader->m_delegate.IOHandlerComplete (*editline_reader,
                                                              current_line,
                                                              cursor,
                                                              last_char,
                                                              skip_first_n_matches,
                                                              max_matches,
                                                              matches);
    return 0;
}
#endif

const char *
IOHandlerEditline::GetPrompt ()
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
    {
        return m_editline_ap->GetPrompt ();
    }
    else
    {
#endif
        if (m_prompt.empty())
            return NULL;
#ifndef LLDB_DISABLE_LIBEDIT
    }
#endif
    return m_prompt.c_str();
}

bool
IOHandlerEditline::SetPrompt (const char *p)
{
    if (p && p[0])
        m_prompt = p;
    else
        m_prompt.clear();
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        m_editline_ap->SetPrompt (m_prompt.empty() ? NULL : m_prompt.c_str());
#endif
    return true;
}

const char *
IOHandlerEditline::GetContinuationPrompt ()
{
    if (m_continuation_prompt.empty())
        return NULL;
    return m_continuation_prompt.c_str();
}


void
IOHandlerEditline::SetContinuationPrompt (const char *p)
{
    if (p && p[0])
        m_continuation_prompt = p;
    else
        m_continuation_prompt.clear();

#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        m_editline_ap->SetContinuationPrompt (m_continuation_prompt.empty() ? NULL : m_continuation_prompt.c_str());
#endif
}


void
IOHandlerEditline::SetBaseLineNumber (uint32_t line)
{
    m_base_line_number = line;
}

uint32_t
IOHandlerEditline::GetCurrentLineIndex () const
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        return m_editline_ap->GetCurrentLine();
#endif
    return m_curr_line_idx;
}

bool
IOHandlerEditline::GetLines (StringList &lines, bool &interrupted)
{
    m_current_lines_ptr = &lines;
    
    bool success = false;
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
    {
        return m_editline_ap->GetLines (m_base_line_number, lines, interrupted);
    }
    else
    {
#endif
        bool done = false;
        Error error;

        while (!done)
        {
            // Show line numbers if we are asked to
            std::string line;
            if (m_base_line_number > 0 && GetIsInteractive())
            {
                FILE *out = GetOutputFILE();
                if (out)
                    ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), GetPrompt() == NULL ? " " : "");
            }
            
            m_curr_line_idx = lines.GetSize();
            
            bool interrupted = false;
            if (GetLine(line, interrupted) && !interrupted)
            {
                lines.AppendString(line);
                done = m_delegate.IOHandlerIsInputComplete(*this, lines);
            }
            else
            {
                done = true;
            }
        }
        success = lines.GetSize() > 0;
#ifndef LLDB_DISABLE_LIBEDIT
    }
#endif
    return success;
}

// Each IOHandler gets to run until it is done. It should read data
// from the "in" and place output into "out" and "err and return
// when done.
void
IOHandlerEditline::Run ()
{
    std::string line;
    while (IsActive())
    {
        bool interrupted = false;
        if (m_multi_line)
        {
            StringList lines;
            if (GetLines (lines, interrupted))
            {
                if (interrupted)
                {
                    m_done = m_interrupt_exits;
                    m_delegate.IOHandlerInputInterrupted (*this, line);

                }
                else
                {
                    line = lines.CopyList();
                    m_delegate.IOHandlerInputComplete (*this, line);
                }
            }
            else
            {
                m_done = true;
            }
        }
        else
        {
            if (GetLine(line, interrupted))
            {
                if (interrupted)
                    m_delegate.IOHandlerInputInterrupted (*this, line);
                else
                    m_delegate.IOHandlerInputComplete (*this, line);
            }
            else
            {
                m_done = true;
            }
        }
    }
}

void
IOHandlerEditline::Hide ()
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        m_editline_ap->Hide();
#endif
}


void
IOHandlerEditline::Refresh ()
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
    {
        m_editline_ap->Refresh();
    }
    else
    {
#endif
        const char *prompt = GetPrompt();
        if (prompt && prompt[0])
        {
            FILE *out = GetOutputFILE();
            if (out)
            {
                ::fprintf(out, "%s", prompt);
                ::fflush(out);
            }
        }
#ifndef LLDB_DISABLE_LIBEDIT
    }
#endif
}

void
IOHandlerEditline::Cancel ()
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        m_editline_ap->Interrupt ();
#endif
}

bool
IOHandlerEditline::Interrupt ()
{
    // Let the delgate handle it first
    if (m_delegate.IOHandlerInterrupt(*this))
        return true;

#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        return m_editline_ap->Interrupt();
#endif
    return false;
}

void
IOHandlerEditline::GotEOF()
{
#ifndef LLDB_DISABLE_LIBEDIT
    if (m_editline_ap)
        m_editline_ap->Interrupt();
#endif
}

// we may want curses to be disabled for some builds
// for instance, windows
#ifndef LLDB_DISABLE_CURSES

#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/StackFrame.h"

#define KEY_RETURN   10
#define KEY_ESCAPE  27

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;
    };

    class WindowDelegate
    {
    public:
        virtual
        ~WindowDelegate()
        {
        }
        
        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 NULL;
        }

        virtual KeyHelp *
        WindowDelegateGetKeyHelp ()
        {
            return NULL;
        }
    };
    
    class HelpDialogDelegate :
        public WindowDelegate
    {
    public:
        HelpDialogDelegate (const char *text, KeyHelp *key_help_array);
        
        virtual
        ~HelpDialogDelegate();
        
        virtual bool
        WindowDelegateDraw (Window &window, bool force);
        
        virtual HandleCharResult
        WindowDelegateHandleChar (Window &window, int key);
        
        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;
    };


    class Window
    {
    public:

        Window (const char *name) :
            m_name (name),
            m_window (NULL),
            m_panel (NULL),
            m_parent (NULL),
            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) :
            m_name (name),
            m_window (NULL),
            m_panel (NULL),
            m_parent (NULL),
            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) :
            m_name (name),
            m_window (NULL),
            m_parent (NULL),
            m_subwindows (),
            m_delegate_sp (),
            m_curr_active_window_idx (UINT32_MAX),
            m_prev_active_window_idx (UINT32_MAX),
            m_delete (true),
            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 = NULL, bool del = true)
        {
            if (m_window == w)
                return;
            
            if (m_panel)
            {
                ::del_panel (m_panel);
                m_panel = NULL;
            }
            if (m_window && m_delete)
            {
                ::delwin (m_window);
                m_window = NULL;
                m_delete = false;
            }
            if (w)
            {
                m_window = w;
                m_panel = ::new_panel (m_window);
                m_delete = del;
            }
        }
        
        void    AttributeOn (attr_t attr)   { ::wattron (m_window, attr); }
        void    AttributeOff (attr_t attr)  { ::wattroff (m_window, attr); }
        void    Box (chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) { ::box(m_window, v_char, h_char); }
        void    Clear ()    { ::wclear (m_window); }
        void    Erase ()    { ::werase (m_window); }
        Rect    GetBounds () { return Rect (GetParentOrigin(), GetSize()); } // Get the rectangle in our parent window
        int     GetChar ()  { return ::wgetch (m_window); }
        int     GetCursorX ()     { return getcurx (m_window); }
        int     GetCursorY ()     { return getcury (m_window); }
        Rect    GetFrame ()    { return Rect (Point(), GetSize()); } // Get our rectangle in our own coordinate system
        Point   GetParentOrigin() { return Point (GetParentX(), GetParentY()); }
        Size    GetSize()         { return Size (GetWidth(), GetHeight()); }
        int     GetParentX ()     { return getparx (m_window); }
        int     GetParentY ()     { return getpary (m_window); }
        int     GetMaxX()   { return getmaxx (m_window); }
        int     GetMaxY()   { return getmaxy (m_window); }
        int     GetWidth()  { return GetMaxX(); }
        int     GetHeight() { return GetMaxY(); }
        void    MoveCursor (int x, int y) {  ::wmove (m_window, y, x); }
        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    PutChar (int ch)    { ::waddch (m_window, ch); }
        void    PutCString (const char *s, int len = -1) { ::waddnstr (m_window, s, len); }
        void    Refresh ()  { ::wrefresh (m_window); }
        void    DeferredRefresh ()
        {
            // We are using panels, so we don't need to call this...
            //::wnoutrefresh(m_window);
        }
        void    SetBackground (int color_pair_idx) { ::wbkgd (m_window,COLOR_PAIR(color_pair_idx)); }
        void    UnderlineOn ()  { AttributeOn(A_UNDERLINE); }
        void    UnderlineOff () { AttributeOff(A_UNDERLINE); }

        void    PutCStringTruncated (const char *s, int right_pad)
        {
            int bytes_left = GetWidth() - GetCursorX();
            if (bytes_left > right_pad)
            {
                bytes_left -= right_pad;
                ::waddnstr (m_window, s, bytes_left);
            }
        }

        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
        Printf (const char *format, ...)  __attribute__ ((format (printf, 2, 3)))
        {
            va_list args;
            va_start (args, format);
            vwprintw(m_window, format, args);
            va_end (args);
        }

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

        WindowSP
        CreateSubWindow (const char *name, const Rect &bounds, bool make_active)
        {
            WindowSP subwindow_sp;
            if (m_window)
            {
                subwindow_sp.reset(new Window(name, ::subwin (m_window,
                                                              bounds.size.height,
                                                              bounds.size.width,
                                                              bounds.origin.y,
                                                              bounds.origin.x), true));
                subwindow_sp->m_is_subwin = true;
            }
            else
            {
                subwindow_sp.reset(new Window(name, ::newwin (bounds.size.height,
                                                              bounds.size.width,
                                                              bounds.origin.y,
                                                              bounds.origin.x), true));
                subwindow_sp->m_is_subwin = false;
            }
            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.compare(name) == 0)
                    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 *
        get()
        {
            return m_window;
        }

        operator WINDOW *()
        {
            return m_window;
        }
        
        //----------------------------------------------------------------------
        // Window drawing utilities
        //----------------------------------------------------------------------
        void
        DrawTitleBox (const char *title, const char *bottom_message = NULL)
        {
            attr_t attr = 0;
            if (IsActive())
                attr = A_BOLD | COLOR_PAIR(2);
            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 (bottom_message, 1);
                }
            }
            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::auto_ptr<HelpDialogDelegate> help_delegate_ap(new HelpDialogDelegate(text, key_help));
                    const size_t num_lines = help_delegate_ap->GetNumLines();
                    const size_t max_length = help_delegate_ap->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_ap.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 == false)
                {
                    HandleCharResult result = subwindow_sp->HandleChar(key);
                    if (result != eKeyNotHandled)
                        return result;
                }
            }

            return eKeyNotHandled;
        }

        bool
        SetActiveWindow (Window *window)
        {
            const size_t num_subwindows = m_subwindows.size();
            for (size_t i=0; i<num_subwindows; ++i)
            {
                if (m_subwindows[i].get() == window)
                {
                    m_prev_active_window_idx = m_curr_active_window_idx;
                    ::top_panel (window->m_panel);
                    m_curr_active_window_idx = i;
                    return true;
                }
            }
            return false;
        }

        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;
        }
        
        const WindowDelegateSP &
        GetDelegate () const
        {
            return m_delegate_sp;
        }

        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 size_t num_subwindows = m_subwindows.size();
            if (m_curr_active_window_idx == UINT32_MAX)
            {
                uint32_t idx = 0;
                for (auto subwindow_sp : m_subwindows)
                {
                    if (subwindow_sp->GetCanBeActive())
                    {
                        m_curr_active_window_idx = idx;
                        break;
                    }
                    ++idx;
                }
            }
            else if (m_curr_active_window_idx + 1 < num_subwindows)
            {
                bool handled = false;
                m_prev_active_window_idx = m_curr_active_window_idx;
                for (size_t idx=m_curr_active_window_idx + 1; idx<num_subwindows; ++idx)
                {
                    if (m_subwindows[idx]->GetCanBeActive())
                    {
                        m_curr_active_window_idx = idx;
                        handled = true;
                        break;
                    }
                }
                if (!handled)
                {
                    for (size_t idx=0; idx<=m_prev_active_window_idx; ++idx)
                    {
                        if (m_subwindows[idx]->GetCanBeActive())
                        {
                            m_curr_active_window_idx = idx;
                            break;
                        }
                    }
                }
            }
            else
            {
                m_prev_active_window_idx = m_curr_active_window_idx;
                for (size_t idx=0; idx<num_subwindows; ++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;
        WINDOW *m_window;
        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:
        DISALLOW_COPY_AND_ASSIGN(Window);
    };
    
    class MenuDelegate
    {
    public:
        virtual ~MenuDelegate() {}
        
        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);
        
        virtual ~
        Menu ()
        {
        }

        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);

        virtual bool
        WindowDelegateDraw (Window &window, bool force);
        
        virtual HandleCharResult
        WindowDelegateHandleChar (Window &window, int key);

        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;
        }
        
        void
        SetKeyValue(int key_value)
        {
            m_key_value = key_value;
        }

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

        std::string &
        GetKeyName()
        {
            return m_key_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 (NULL),
        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 (NULL),
        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 hilgight_attr = A_REVERSE;
            if (highlight)
                window.AttributeOn(hilgight_attr);
            if (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(hilgight_attr);

            if (m_key_name.empty())
            {
                if (!underlined_shortcut && isprint(m_key_value))
                {
                    window.AttributeOn (COLOR_PAIR(3));
                    window.Printf (" (%c)", m_key_value);
                    window.AttributeOff (COLOR_PAIR(3));
                }
            }
            else
            {
                window.AttributeOn (COLOR_PAIR(3));
                window.Printf (" (%s)", m_key_name.c_str());
                window.AttributeOff (COLOR_PAIR(3));
            }
        }
    }
    
    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(2);
                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(" |");
                window.DeferredRefresh();
            }
            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(2);
                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);
                window.DeferredRefresh();
            }
            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 caclulated
                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_screen (NULL),
            m_in (in),
            m_out (out)
        {
            
        }
        
        ~Application ()
        {
            m_window_delegates.clear();
            m_window_sp.reset();
            if (m_screen)
            {
                ::delscreen(m_screen);
                m_screen = NULL;
            }
        }
        
        void
        Initialize ()
        {
            ::setlocale(LC_ALL, "");
            ::setlocale(LC_CTYPE, "");
#if 0
            ::initscr();
#else
            m_screen = ::newterm(NULL, m_out, m_in);
#endif
            ::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 (new Listener ("lldb.IOHandler.curses.Application"));
            ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
            ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
            ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
            debugger.EnableForwardEvents (listener_sp);

            bool update = true;
#if defined(__APPLE__)
            std::deque<int> escape_chars;
#endif
            
            while (!done)
            {
                if (update)
                {
                    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();
                    update = 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->GetNextEvent(event_sp);
                            
                            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)
                                    {
                                        debugger.GetCommandInterpreter().UpdateExecutionContext(NULL);
                                        update = 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:
                            debugger.GetCommandInterpreter().UpdateExecutionContext(NULL);
                            update = true;
                            break;
                        case eKeyNotHandled:
                            break;
                        case eQuitApplication:
                            done = true;
                            break;
                    }
                }
            }
            
            debugger.CancelForwardEvents (listener_sp);

        }
        
        WindowSP &
        GetMainWindow ()
        {
            if (!m_window_sp)
                m_window_sp.reset (new Window ("main", stdscr, false));
            return m_window_sp;
        }
        
        WindowDelegates &
        GetWindowDelegates ()
        {
            return m_window_delegates;
        }

    protected:
        WindowSP m_window_sp;
        WindowDelegates m_window_delegates;
        SCREEN *m_screen;
        FILE *m_in;
        FILE *m_out;
    };
    

} // namespace curses


using namespace curses;

struct Row
{
    ValueObjectSP valobj;
    Row *parent;
    int row_idx;
    int x;
    int y;
    bool might_have_children;
    bool expanded;
    bool calculated_children;
    std::vector<Row> children;
    
    Row (const ValueObjectSP &v, Row *p) :
    valobj (v),
    parent (p),
    row_idx(0),
    x(1),
    y(1),
    might_have_children (v ? v->MightHaveChildren() : false),
    expanded (false),
    calculated_children (false),
    children()
    {
    }
    
    size_t
    GetDepth () const
    {
        if (parent)
            return 1 + parent->GetDepth();
        return 0;
    }
    
    void
    Expand()
    {
        expanded = true;
        if (!calculated_children)
        {
            calculated_children = true;
            if (valobj)
            {
                const size_t num_children = valobj->GetNumChildren();
                for (size_t i=0; i<num_children; ++i)
                {
                    children.push_back(Row (valobj->GetChildAtIndex(i, true), this));
                }
            }
        }
    }
    
    void
    Unexpand ()
    {
        expanded = false;
    }
    
    void
    DrawTree (Window &window)
    {
        if (parent)
            parent->DrawTreeForChild (window, this, 0);
        
        if (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);
        }
    }

    void
    DrawTreeForChild (Window &window, Row *child, uint32_t reverse_depth)
    {
        if (parent)
            parent->DrawTreeForChild (window, this, reverse_depth + 1);
        
        if (&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 (' ');
            }
        }
    }
};

struct DisplayOptions
{
    bool show_types;
};

class TreeItem;

class TreeDelegate
{
public:
    TreeDelegate() {}
    virtual ~TreeDelegate() {}
    virtual void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) = 0;
    virtual void TreeDelegateGenerateChildren (TreeItem &item) = 0;
    virtual bool TreeDelegateItemSelected (TreeItem &item) = 0; // Return true if we need to update views
};
typedef std::shared_ptr<TreeDelegate> TreeDelegateSP;

class TreeItem
{
public:
    
    TreeItem (TreeItem *parent, TreeDelegate &delegate, bool might_have_children) :
        m_parent (parent),
        m_delegate (delegate),
        m_user_data (NULL),
        m_identifier (0),
        m_row_idx (-1),
        m_children (),
        m_might_have_children (might_have_children),
        m_is_expanded (false)
    {
    }

    TreeItem &
    operator=(const TreeItem &rhs)
    {
        if (this != &rhs)
        {
            m_parent = rhs.m_parent;
            m_delegate = rhs.m_delegate;
            m_user_data = rhs.m_user_data;
            m_identifier = rhs.m_identifier;
            m_row_idx = rhs.m_row_idx;
            m_children = rhs.m_children;
            m_might_have_children = rhs.m_might_have_children;
            m_is_expanded = rhs.m_is_expanded;
        }
        return *this;
    }

    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, const TreeItem &t)
    {
        m_children.resize(n, t);
    }
    
    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 == NULL || 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) == false)
                    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 NULL;
        if (static_cast<uint32_t>(m_children.back().m_row_idx) < row_idx)
            return NULL;
        if (IsExpanded())
        {
            for (auto &item : m_children)
            {
                TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx);
                if (selected_item_ptr)
                    return selected_item_ptr;
            }
        }
        return NULL;
    }
    
    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;
    }
    

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

protected:
    TreeItem *m_parent;
    TreeDelegate &m_delegate;
    void *m_user_data;
    uint64_t m_identifier;
    int m_row_idx; // Zero based visible row index, -1 if not visible or for the root item
    std::vector<TreeItem> m_children;
    bool m_might_have_children;
    bool m_is_expanded;

};

class TreeWindowDelegate : public WindowDelegate
{
public:
    TreeWindowDelegate (Debugger &debugger, const TreeDelegateSP &delegate_sp) :
        m_debugger (debugger),
        m_delegate_sp (delegate_sp),
        m_root (NULL, *delegate_sp, true),
        m_selected_item (NULL),
        m_num_rows (0),
        m_selected_row_idx (0),
        m_first_visible_row (0),
        m_min_x (0),
        m_min_y (0),
        m_max_x (0),
        m_max_y (0)
    {
    }
    
    int
    NumVisibleRows () const
    {
        return m_max_y - m_min_y;
    }

    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
        Process *process = exe_ctx.GetProcessPtr();
        
        bool display_content = false;
        if (process)
        {
            StateType state = process->GetState();
            if (StateIsStoppedState(state, true))
            {
                // We are stopped, so it is ok to
                display_content = true;
            }
            else if (StateIsRunningState(state))
            {
                return true; // Don't do any updating when we are running
            }
        }

        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 (display_content)
        {
            const int num_visible_rows = NumVisibleRows();
            m_num_rows = 0;
            m_root.CalculateRowIndexes(m_num_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 && 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);
        }
        else
        {
            m_selected_item = NULL;
        }
        
        window.DeferredRefresh();
        
        
        return true; // Drawing handled
    }
    
    
    virtual const char *
    WindowDelegateGetHelpText ()
    {
        return "Thread window keyboard shortcuts:";
    }
    
    virtual KeyHelp *
    WindowDelegateGetKeyHelp ()
    {
        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', NULL }
        };
        return g_source_view_key_help;
    }
    
    virtual HandleCharResult
    WindowDelegateHandleChar (Window &window, int c)
    {
        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;
    int m_num_rows;
    int m_selected_row_idx;
    int m_first_visible_row;
    int m_min_x;
    int m_min_y;
    int m_max_x;
    int m_max_y;

};

class FrameTreeDelegate : public TreeDelegate
{
public:
    FrameTreeDelegate () :
        TreeDelegate()
    {
        FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}",
                             m_format);
    }
    
    virtual ~FrameTreeDelegate()
    {
    }
    
    virtual void
    TreeDelegateDrawTreeItem (TreeItem &item, Window &window)
    {
        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, NULL, NULL, false, false))
                {
                    int right_pad = 1;
                    window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
                }
            }
        }
    }
    virtual void
    TreeDelegateGenerateChildren (TreeItem &item)
    {
        // No children for frames yet...
    }
    
    virtual bool
    TreeDelegateItemSelected (TreeItem &item)
    {
        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),
        m_tid (LLDB_INVALID_THREAD_ID),
        m_stop_id (UINT32_MAX)
    {
        FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}",
                             m_format);
    }
    
    virtual
    ~ThreadTreeDelegate()
    {
    }
    
    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();
    }
    
    virtual void
    TreeDelegateDrawTreeItem (TreeItem &item, Window &window)
    {
        ThreadSP thread_sp = GetThread (item);
        if (thread_sp)
        {
            StreamString strm;
            ExecutionContext exe_ctx (thread_sp);
            if (FormatEntity::Format (m_format, strm, NULL, &exe_ctx, NULL, NULL, false, false))
            {
                int right_pad = 1;
                window.PutCStringTruncated(strm.GetString().c_str(), right_pad);
            }
        }
    }
    virtual void
    TreeDelegateGenerateChildren (TreeItem &item)
    {
        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.reset (new FrameTreeDelegate());
                    }

                    m_stop_id = process_sp->GetStopID();
                    m_tid = thread_sp->GetID();
                    
                    TreeItem t (&item, *m_frame_delegate_sp, false);
                    size_t num_frames = thread_sp->GetStackFrameCount();
                    item.Resize (num_frames, t);
                    for (size_t i=0; i<num_frames; ++i)
                    {
                        item[i].SetUserData(thread_sp.get());
                        item[i].SetIdentifier(i);
                    }
                }
                return;
            }
        }
        item.ClearChildren();
    }
    
    virtual bool
    TreeDelegateItemSelected (TreeItem &item)
    {
        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();
                    Mutex::Locker locker (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;
    uint32_t m_stop_id;
    FormatEntity::Entry m_format;

};

class ThreadsTreeDelegate : public TreeDelegate
{
public:
    ThreadsTreeDelegate (Debugger &debugger) :
        TreeDelegate(),
        m_thread_delegate_sp (),
        m_debugger (debugger),
        m_stop_id (UINT32_MAX)
    {
        FormatEntity::Parse("process ${process.id}{, name = ${process.name}}",
                            m_format);
    }
    
    virtual
    ~ThreadsTreeDelegate()
    {
    }
    
    ProcessSP
    GetProcess ()
    {
        return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP();
    }

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

    virtual void
    TreeDelegateGenerateChildren (TreeItem &item)
    {
        ProcessSP process_sp = GetProcess ();
        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;

                if (!m_thread_delegate_sp)
                {
                    // Always expand the thread item the first time we show it
                    //item.Expand();
                    m_thread_delegate_sp.reset (new ThreadTreeDelegate(m_debugger));
                }
                
                TreeItem t (&item, *m_thread_delegate_sp, false);
                ThreadList &threads = process_sp->GetThreadList();
                Mutex::Locker locker (threads.GetMutex());
                size_t num_threads = threads.GetSize();
                item.Resize (num_threads, t);
                for (size_t i=0; i<num_threads; ++i)
                {
                    item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID());
                    item[i].SetMightHaveChildren(true);
                }
                return;
            }
        }
        item.ClearChildren();
    }
    
    virtual bool
    TreeDelegateItemSelected (TreeItem &item)
    {
        return false;
    }
    
protected:
    std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp;
    Debugger &m_debugger;
    uint32_t m_stop_id;
    FormatEntity::Entry m_format;

};

class ValueObjectListDelegate : public WindowDelegate
{
public:
    ValueObjectListDelegate () :
        m_valobj_list (),
        m_rows (),
        m_selected_row (NULL),
        m_selected_row_idx (0),
        m_first_visible_row (0),
        m_num_rows (0),
        m_max_x (0),
        m_max_y (0)
    {
    }
    
    ValueObjectListDelegate (ValueObjectList &valobj_list) :
        m_valobj_list (valobj_list),
        m_rows (),
        m_selected_row (NULL),
        m_selected_row_idx (0),
        m_first_visible_row (0),
        m_num_rows (0),
        m_max_x (0),
        m_max_y (0)
    {
        SetValues (valobj_list);
    }
    
    virtual
    ~ValueObjectListDelegate()
    {
    }

    void
    SetValues (ValueObjectList &valobj_list)
    {
        m_selected_row = NULL;
        m_selected_row_idx = 0;
        m_first_visible_row = 0;
        m_num_rows = 0;
        m_rows.clear();
        m_valobj_list = valobj_list;
        const size_t num_values = m_valobj_list.GetSize();
        for (size_t i=0; i<num_values; ++i)
            m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), NULL));
    }
    
    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        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);
        
        window.DeferredRefresh();
        
        // 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
    }
    
    virtual KeyHelp *
    WindowDelegateGetKeyHelp ()
    {
        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', NULL }
        };
        return g_source_view_key_help;
    }

    
    virtual HandleCharResult
    WindowDelegateHandleChar (Window &window, int c)
    {
        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)
                    m_selected_row->valobj->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:
    ValueObjectList m_valobj_list;
    std::vector<Row> m_rows;
    Row *m_selected_row;
    uint32_t m_selected_row_idx;
    uint32_t m_first_visible_row;
    uint32_t m_num_rows;
    int m_min_x;
    int m_min_y;
    int m_max_x;
    int m_max_y;

    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.valobj.get();
        
        if (valobj == NULL)
            return false;
    
        const char *type_name = options.show_types ? valobj->GetTypeName().GetCString() : NULL;
        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.Printf ("(%s) ", type_name);
        
        if (name && name[0])
            window.PutCString(name);
        
        attr_t changd_attr = 0;
        if (valobj->GetValueDidChange())
            changd_attr = COLOR_PAIR(5) | A_BOLD;
        
        if (value && value[0])
        {
            window.PutCString(" = ");
            if (changd_attr)
                window.AttributeOn(changd_attr);
            window.PutCString (value);
            if (changd_attr)
                window.AttributeOff(changd_attr);
        }
        
        if (summary && summary[0])
        {
            window.PutChar(' ');
            if (changd_attr)
                window.AttributeOn(changd_attr);
            window.PutCString(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 && !row.children.empty())
            {
                DisplayRows (window,
                             row.children,
                             options);
            }
        }
    }
    
    int
    CalculateTotalNumberRows (const std::vector<Row> &rows)
    {
        int row_count = 0;
        for (const auto &row : rows)
        {
            ++row_count;
            if (row.expanded)
                row_count += CalculateTotalNumberRows(row.children);
        }
        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 && !row.children.empty())
                {
                    Row *result = GetRowForRowIndexImpl (row.children, row_index);
                    if (result)
                        return result;
                }
            }
        }
        return NULL;
    }
    
    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),
        m_frame_block (NULL)
    {
    }
    
    virtual
    ~FrameVariablesWindowDelegate()
    {
    }
    
    virtual const char *
    WindowDelegateGetHelpText ()
    {
        return "Frame variable window keyboard shortcuts:";
    }
    
    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext());
        Process *process = exe_ctx.GetProcessPtr();
        Block *frame_block = NULL;
        StackFrame *frame = NULL;
        
        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);
                if (locals)
                {
                    const DynamicValueType use_dynamic = eDynamicDontRunTarget;
                    const size_t num_locals = locals->GetSize();
                    for (size_t i=0; i<num_locals; ++i)
                        local_values.Append(frame->GetValueObjectForFrameVariable (locals->GetVariableAtIndex(i), use_dynamic));
                    // Update the values
                    SetValues(local_values);
                }
            }
        }
        else
        {
            m_frame_block = NULL;
            // 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;
};


class RegistersWindowDelegate : public ValueObjectListDelegate
{
public:
    RegistersWindowDelegate (Debugger &debugger) :
        ValueObjectListDelegate (),
        m_debugger (debugger)
    {
    }
    
    virtual
    ~RegistersWindowDelegate()
    {
    }
    
    virtual const char *
    WindowDelegateGetHelpText ()
    {
        return "Register window keyboard shortcuts:";
    }

    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        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";
        case KEY_EVENT:     return "We were interrupted by an event";
        case KEY_RETURN:    return "return";
        case ' ':           return "space";
        case '\t':          return "tab";
        case KEY_ESCAPE:    return "escape";
        default:
            if (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 NULL;
}

HelpDialogDelegate::HelpDialogDelegate (const char *text, KeyHelp *key_help_array) :
    m_text (),
    m_first_visible_line (0)
{
    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(std::move(key_description.GetString()));
        }
    }
}

HelpDialogDelegate::~HelpDialogDelegate()
{
}
    
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(m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1);
        ++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_ProcessDetach,
        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_Help,
        eMenuID_HelpGUIHelp
    };

    ApplicationDelegate (Application &app, Debugger &debugger) :
        WindowDelegate (),
        MenuDelegate (),
        m_app (app),
        m_debugger (debugger)
    {
    }
    
    virtual
    ~ApplicationDelegate ()
    {
    }
    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        return false; // Drawing not handled, let standard window drawing happen
    }
    
    virtual HandleCharResult
    WindowDelegateHandleChar (Window &window, int key)
    {
        switch (key)
        {
            case '\t':
                window.SelectNextWindowAsActive();
                return eKeyHandled;

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

            case KEY_ESCAPE:
                return eQuitApplication;

            default:
                break;
        }
        return eKeyNotHandled;
    }
    
    
    virtual const char *
    WindowDelegateGetHelpText ()
    {
        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:";
    }
    
    virtual KeyHelp *
    WindowDelegateGetKeyHelp ()
    {
        static curses::KeyHelp g_source_view_key_help[] = {
            { '\t', "Select next 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', NULL }
        };
        return g_source_view_key_help;
    }
    
    virtual MenuActionResult
    MenuDelegateAction (Menu &menu)
    {
        switch (menu.GetIdentifier())
        {
            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))
                            exe_ctx.GetThreadRef().StepOut();
                    }
                }
                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_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();
                    }
                }
                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_ProcessDetach:
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasProcessScope())
                    {
                        Process *process = exe_ctx.GetProcessPtr();
                        if (process && process->IsAlive())
                            process->Detach(false);
                    }
                }
                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();
                        Mutex::Locker locker (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().c_str(), NULL, 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 variables 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 registers 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_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);
    }
    
    virtual
    ~StatusBarWindowDelegate ()
    {
    }
    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        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(2);
        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, NULL, &exe_ctx, NULL, NULL, false, false))
                {
                    window.MoveCursor (40, 0);
                    window.PutCStringTruncated(strm.GetString().c_str(), 1);
                }

                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);
            }
        }
        window.DeferredRefresh();
        return true;
    }

protected:
    Debugger &m_debugger;
    FormatEntity::Entry m_format;
};

class SourceFileWindowDelegate : public WindowDelegate
{
public:
    SourceFileWindowDelegate (Debugger &debugger) :
        WindowDelegate (),
        m_debugger (debugger),
        m_sc (),
        m_file_sp (),
        m_disassembly_scope (NULL),
        m_disassembly_sp (),
        m_disassembly_range (),
        m_title (),
        m_line_width (4),
        m_selected_line (0),
        m_pc_line (0),
        m_stop_id (0),
        m_frame_idx (UINT32_MAX),
        m_first_visible_line (0),
        m_min_x (0),
        m_min_y (0),
        m_max_x (0),
        m_max_y (0)
    {
    }

    virtual
    ~SourceFileWindowDelegate()
    {
    }

    void
    Update (const SymbolContext &sc)
    {
        m_sc = sc;
    }

    uint32_t
    NumVisibleLines () const
    {
        return m_max_y - m_min_y;
    }

    virtual const char *
    WindowDelegateGetHelpText ()
    {
        return "Source/Disassembly window keyboard shortcuts:";
    }

    virtual KeyHelp *
    WindowDelegateGetKeyHelp ()
    {
        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_PPAGE, "Page up" },
            { KEY_NPAGE, "Page down" },
            { 'b', "Set breakpoint on selected source/disassembly line" },
            { 'c', "Continue process" },
            { 'd', "Detach and resume process" },
            { 'D', "Detach with process suspended" },
            { 'h', "Show help dialog" },
            { 'k', "Kill process" },
            { 'n', "Step over (source line)" },
            { 'N', "Step over (single instruction)" },
            { 'o', "Step out" },
            { 's', "Step in (source line)" },
            { 'S', "Step in (single instruction)" },
            { ',', "Page up" },
            { '.', "Page down" },
            { '\0', NULL }
        };
        return g_source_view_key_help;
    }

    virtual bool
    WindowDelegateDraw (Window &window, bool force)
    {
        ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
        Process *process = exe_ctx.GetProcessPtr();
        Thread *thread = NULL;

        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 ? process->IsAlive() : false;
            bool thread_changed = false;
            if (process_alive)
            {
                thread = exe_ctx.GetThreadPtr();
                if (thread)
                {
                    frame_sp = thread->GetSelectedFrame();
                    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->FileSpecMatches(m_sc.line_entry.file))
                    {
                        // 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);
                        if (m_file_sp)
                        {
                            const size_t num_lines = m_file_sp->GetNumLines();
                            int m_line_width = 1;
                            for (size_t n = num_lines; n >= 10; n = n / 10)
                                ++m_line_width;

                            snprintf (m_line_format, sizeof(m_line_format), " %%%iu ", 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, NULL, prefer_file_cache);
                            if (m_disassembly_sp)
                            {
                                set_selected_line_to_pc = true;
                                m_disassembly_range = m_sc.function->GetAddressRange();
                            }
                            else
                            {
                                m_disassembly_range.Clear();
                            }
                        }
                        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, NULL, prefer_file_cache);
                            if (m_disassembly_sp)
                            {
                                set_selected_line_to_pc = true;
                                m_disassembly_range.GetBaseAddress() = m_sc.symbol->GetAddress();
                                m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize());
                            }
                            else
                            {
                                m_disassembly_range.Clear();
                            }
                        }
                        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(m_title.GetString().c_str(), 1);
            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->GetFileSpec() == bp_loc_line_entry.file)
                            {
                                bp_lines.insert(bp_loc_line_entry.line);
                            }
                        }
                    }
                }
            }

            const attr_t selected_highlight_attr = A_REVERSE;
            const attr_t pc_highlight_attr = COLOR_PAIR(1);

            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, 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_lines.find(curr_line+1) != bp_lines.end())
                        bp_attr = COLOR_PAIR(2);

                    if (bp_attr)
                        window.AttributeOn(bp_attr);

                    window.Printf (m_line_format, 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);
                    const uint32_t line_len = m_file_sp->GetLineLength(curr_line + 1, false);
                    if (line_len > 0)
                        window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len);

                    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;
                                window.Printf ("%*s", desc_x - window.GetCursorX(), "");
                                //window.MoveCursor(window_width - stop_description_len - 15, line_y);
                                window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
                            }
                        }
                        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);
                            LineEntry bp_loc_line_entry;
                            const lldb::addr_t file_addr = bp_loc_sp->GetAddress().GetFileAddress();
                            if (file_addr != LLDB_INVALID_ADDRESS)
                            {
                                if (m_disassembly_range.ContainsFileAddress(file_addr))
                                    bp_file_addrs.insert(file_addr);
                            }
                        }
                    }
                }

                const attr_t selected_highlight_attr = A_REVERSE;
                const attr_t pc_highlight_attr = COLOR_PAIR(1);

                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(2);

                    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 && mnemonic[0] == '\0')
                        mnemonic = NULL;
                    if (operands && operands[0] == '\0')
                        operands = NULL;
                    if (comment && comment[0] == '\0')
                        comment = NULL;

                    strm.Clear();

                    if (mnemonic && operands && comment)
                        strm.Printf ("%-8s %-25s ; %s", mnemonic, operands, comment);
                    else if (mnemonic && operands)
                        strm.Printf ("%-8s %s", mnemonic, operands);
                    else if (mnemonic)
                        strm.Printf ("%s", mnemonic);

                    int right_pad = 1;
                    window.PutCStringTruncated(strm.GetString().c_str(), right_pad);

                    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;
                                window.Printf ("%*s", desc_x - window.GetCursorX(), "");
                                //window.MoveCursor(window_width - stop_description_len - 15, line_y);
                                window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description);
                            }
                        }
                        else
                        {
                            window.Printf ("%*s", window_width - window.GetCursorX() - 1, "");
                        }
                    }
                    if (highlight_attr)
                        window.AttributeOff(highlight_attr);
                }
            }
        }
        window.DeferredRefresh();
        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;
    }

    virtual HandleCharResult
    WindowDelegateHandleChar (Window &window, int c)
    {
        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 '\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 (NULL,                      // Don't limit the breakpoint to certain modules
                                                                                      m_file_sp->GetFileSpec(),  // Source file
                                                                                      m_selected_line + 1,       // Source line number (m_selected_line is zero based)
                                                                                      eLazyBoolCalculate,        // Check inlines using global setting
                                                                                      eLazyBoolCalculate,        // Skip prologue using global setting,
                                                                                      false,                     // internal
                                                                                      false);                    // request_hardware
                        // 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
                if (m_selected_line < GetNumSourceLines())
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasTargetScope())
                    {
                        BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (NULL,                      // Don't limit the breakpoint to certain modules
                                                                                      m_file_sp->GetFileSpec(),  // Source file
                                                                                      m_selected_line + 1,       // Source line number (m_selected_line is zero based)
                                                                                      eLazyBoolCalculate,        // Check inlines using global setting
                                                                                      eLazyBoolCalculate,        // Skip prologue using global setting,
                                                                                      false,                     // internal
                                                                                      false);                    // request_hardware
                    }
                }
                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
                    }
                }
                return eKeyHandled;

            case 'd':   // 'd' == detach and let run
            case 'D':   // 'D' == detach and keep stopped
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasProcessScope())
                        exe_ctx.GetProcessRef().Detach(c == 'D');
                }
                return eKeyHandled;

            case 'k':
                // 'k' == kill
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasProcessScope())
                        exe_ctx.GetProcessRef().Destroy();
                }
                return eKeyHandled;

            case 'c':
                // 'c' == continue
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasProcessScope())
                        exe_ctx.GetProcessRef().Resume();
                }
                return eKeyHandled;

            case 'o':
                // 'o' == step out
                {
                    ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext();
                    if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true))
                    {
                        exe_ctx.GetThreadRef().StepOut();
                    }
                }
                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 'h':
                window.CreateHelpSubwindow ();
                return eKeyHandled;

            default:
                break;
        }
        return eKeyNotHandled;
    }

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;
    lldb::DisassemblerSP m_disassembly_sp;
    AddressRange m_disassembly_range;
    StreamString m_title;
    lldb::user_id_t m_tid;
    char m_line_format[8];
    int m_line_width;
    uint32_t m_selected_line;       // The selected line
    uint32_t m_pc_line;             // The line with the PC
    uint32_t m_stop_id;
    uint32_t m_frame_idx;
    int m_first_visible_line;
    int m_min_x;
    int m_min_y;
    int m_max_x;
    int m_max_y;

};

DisplayOptions ValueObjectListDelegate::g_options = { true };

IOHandlerCursesGUI::IOHandlerCursesGUI (Debugger &debugger) :
    IOHandler (debugger, IOHandler::Type::Curses)
{
}

void
IOHandlerCursesGUI::Activate ()
{
    IOHandler::Activate();
    if (!m_app_ap)
    {
        m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE()));
        
        
        // This is both a window and a menu delegate
        std::shared_ptr<ApplicationDelegate> app_delegate_sp(new ApplicationDelegate(*m_app_ap, 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", NULL, 'x', ApplicationDelegate::eMenuID_LLDBExit));
        exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
        lldb_menu_sp->AddSubmenu (MenuSP (new Menu("About LLDB", NULL, '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", NULL, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
        target_menu_sp->AddSubmenu (MenuSP (new Menu("Delete", NULL, '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"  , NULL, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu("Detach"  , NULL, 'd', ApplicationDelegate::eMenuID_ProcessDetach)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu("Launch"  , NULL, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu("Continue", NULL, 'c', ApplicationDelegate::eMenuID_ProcessContinue)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu("Halt"    , NULL, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
        process_menu_sp->AddSubmenu (MenuSP (new Menu("Kill"    , NULL, '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"  , NULL, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
        thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Over", NULL, 'v', ApplicationDelegate::eMenuID_ThreadStepOver)));
        thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Out" , NULL, '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", NULL, 'b', ApplicationDelegate::eMenuID_ViewBacktrace)));
        view_menu_sp->AddSubmenu (MenuSP (new Menu("Registers", NULL, 'r', ApplicationDelegate::eMenuID_ViewRegisters)));
        view_menu_sp->AddSubmenu (MenuSP (new Menu("Source"   , NULL, 's', ApplicationDelegate::eMenuID_ViewSource)));
        view_menu_sp->AddSubmenu (MenuSP (new Menu("Variables", NULL, 'v', ApplicationDelegate::eMenuID_ViewVariables)));
        
        MenuSP help_menu_sp(new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
        help_menu_sp->AddSubmenu (MenuSP (new Menu("GUI Help", NULL, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
        
        m_app_ap->Initialize();
        WindowSP &main_window_sp = m_app_ap->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)));

        // Show the main help window once the first time the curses GUI is launched
        static bool g_showed_help = false;
        if (!g_showed_help)
        {
            g_showed_help = true;
            main_window_sp->CreateHelpSubwindow();
        }

        init_pair (1, COLOR_WHITE   , COLOR_BLUE  );
        init_pair (2, COLOR_BLACK   , COLOR_WHITE );
        init_pair (3, COLOR_MAGENTA , COLOR_WHITE );
        init_pair (4, COLOR_MAGENTA , COLOR_BLACK );
        init_pair (5, COLOR_RED     , COLOR_BLACK );

    }
}

void
IOHandlerCursesGUI::Deactivate ()
{
    m_app_ap->Terminate();
}

void
IOHandlerCursesGUI::Run ()
{
    m_app_ap->Run(m_debugger);
    SetIsDone(true);
}


IOHandlerCursesGUI::~IOHandlerCursesGUI ()
{
    
}

void
IOHandlerCursesGUI::Hide ()
{
}


void
IOHandlerCursesGUI::Refresh ()
{
}

void
IOHandlerCursesGUI::Cancel ()
{
}

bool
IOHandlerCursesGUI::Interrupt ()
{
    return false;
}


void
IOHandlerCursesGUI::GotEOF()
{
}

#endif // #ifndef LLDB_DISABLE_CURSES
