<commit_before>#include "client.hh"

#include "face_registry.hh"
#include "context.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "file.hh"
#include "remote.hh"
#include "option.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "event_manager.hh"
#include "user_interface.hh"
#include "window.hh"
#include "hash_map.hh"

#include <csignal>
#include <unistd.h>

#include <utility>

namespace Kakoune
{

Client::Client(std::unique_ptr<UserInterface>&& ui,
               std::unique_ptr<Window>&& window,
               SelectionList selections, int pid,
               EnvVarMap env_vars,
               String name,
               OnExitCallback on_exit)
    : m_ui{std::move(ui)}, m_window{std::move(window)},
      m_pid{pid},
      m_on_exit{std::move(on_exit)},
      m_input_handler{std::move(selections), Context::Flags::None,
                      std::move(name)},
      m_env_vars(std::move(env_vars))
{
    m_window->set_client(this);

    context().set_client(*this);
    context().set_window(*m_window);

    m_window->set_dimensions(m_ui->dimensions());
    m_window->options().register_watcher(*this);

    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
    m_ui->set_on_key([this](Key key) {
        if (key == ctrl('c'))
            killpg(getpgrp(), SIGINT);
        else
            m_pending_keys.push_back(key);
    });

    m_window->hooks().run_hook("WinDisplay", m_window->buffer().name(), context());

    force_redraw();
}

Client::~Client()
{
    m_window->options().unregister_watcher(*this);
    m_window->set_client(nullptr);
    // Do not move the selections here, as we need them to be valid
    // in order to correctly destroy the input handler
    ClientManager::instance().add_free_window(std::move(m_window),
                                              context().selections());
}

bool Client::process_pending_inputs()
{
    const bool debug_keys = (bool)(context().options()["debug"].get<DebugFlags>() & DebugFlags::Keys);
    // steal keys as we might receive new keys while handling them.
    Vector<Key, MemoryDomain::Client> keys = std::move(m_pending_keys);
    for (auto& key : keys)
    {
        try
        {
            if (debug_keys)
                write_to_debug_buffer(format("Client '{}' got key '{}'",
                                             context().name(), key_to_str(key)));

            if (key == Key::FocusIn)
                context().hooks().run_hook("FocusIn", context().name(), context());
            else if (key == Key::FocusOut)
                context().hooks().run_hook("FocusOut", context().name(), context());
            else if (key.modifiers == Key::Modifiers::Resize)
            {
                m_window->set_dimensions(m_ui->dimensions());
                force_redraw();
            }
            else
                m_input_handler.handle_key(key);

            context().hooks().run_hook("RawKey", key_to_str(key), context());
        }
        catch (Kakoune::runtime_error& error)
        {
            write_to_debug_buffer(format("Error: {}", error.what()));
            context().print_status({ fix_atom_text(error.what().str()), get_face("Error") });
            context().hooks().run_hook("RuntimeError", error.what(), context());
        }
    }
    return not keys.empty();
}

void Client::print_status(DisplayLine status_line, bool immediate)
{
    m_status_line = std::move(status_line);
    if (immediate)
    {
        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
        m_ui->refresh(true);
    }
    else
    {
        m_ui_pending |= StatusLine;
    }
}

DisplayCoord Client::dimensions() const
{
    return m_ui->dimensions();
}

String generate_context_info(const Context& context)
{
    String s = "";
    if (context.buffer().is_modified())
        s += "[+]";
    if (context.client().input_handler().is_recording())
        s += format("[recording ({})]", context.client().input_handler().recording_reg());
    if (context.buffer().flags() & Buffer::Flags::New)
        s += "[new file]";
    if (context.hooks_disabled())
        s += "[no-hooks]";
    if (context.buffer().flags() & Buffer::Flags::Fifo)
        s += "[fifo]";
    return s;
}

DisplayLine Client::generate_mode_line() const
{
    DisplayLine modeline;
    try
    {
        const String& modelinefmt = context().options()["modelinefmt"].get<String>();
        HashMap<String, DisplayLine> atoms{{ "mode_info", context().client().input_handler().mode_line() },
                                           { "context_info", {generate_context_info(context()), get_face("Information")}}};
        auto expanded = expand(modelinefmt, context(), ShellContext{},
                               [](String s) { return escape(s, '{', '\\'); });
        modeline = parse_display_line(expanded, atoms);
    }
    catch (runtime_error& err)
    {
        write_to_debug_buffer(format("Error while parsing modelinefmt: {}", err.what()));
        modeline.push_back({ "modelinefmt error, see *debug* buffer", get_face("Error") });
    }

    return modeline;
}

void Client::change_buffer(Buffer& buffer)
{
    if (m_buffer_reload_dialog_opened)
        close_buffer_reload_dialog();

    auto* current = &m_window->buffer();
    m_last_buffer = contains(BufferManager::instance(), current) ? current : nullptr;

    auto& client_manager = ClientManager::instance();
    m_window->options().unregister_watcher(*this);
    m_window->set_client(nullptr);
    client_manager.add_free_window(std::move(m_window),
                                   std::move(context().selections()));
    WindowAndSelections ws = client_manager.get_free_window(buffer);

    m_window = std::move(ws.window);
    m_window->set_client(this);
    m_window->options().register_watcher(*this);
    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());

    context().selections_write_only() = std::move(ws.selections);
    context().set_window(*m_window);
    m_window->set_dimensions(m_ui->dimensions());

    m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
    force_redraw();
}

static bool is_inline(InfoStyle style)
{
    return style == InfoStyle::Inline or
           style == InfoStyle::InlineAbove or
           style == InfoStyle::InlineBelow;
}

void Client::redraw_ifn()
{
    Window& window = context().window();
    if (window.needs_redraw(context()))
        m_ui_pending |= Draw;

    DisplayLine mode_line = generate_mode_line();
    if (mode_line.atoms() != m_mode_line.atoms())
    {
        m_ui_pending |= StatusLine;
        m_mode_line = std::move(mode_line);
    }

    if (m_ui_pending == 0)
        return;

    if (m_ui_pending & Draw)
        m_ui->draw(window.update_display_buffer(context()),
                   get_face("Default"), get_face("BufferPadding"));

    const bool update_menu_anchor = (m_ui_pending & Draw) and not (m_ui_pending & MenuHide) and
                                    not m_menu.items.empty() and m_menu.style == MenuStyle::Inline;
    if ((m_ui_pending & MenuShow) or update_menu_anchor)
    {
        auto anchor = m_menu.style == MenuStyle::Inline ?
            window.display_position(m_menu.anchor) : DisplayCoord{};
        if (not (m_ui_pending & MenuShow) and m_menu.ui_anchor != anchor)
            m_ui_pending |= anchor ? (MenuShow | MenuSelect) : MenuHide;
        m_menu.ui_anchor = anchor;
    }

    if (m_ui_pending & MenuShow and m_menu.ui_anchor)
        m_ui->menu_show(m_menu.items, *m_menu.ui_anchor,
                        get_face("MenuForeground"), get_face("MenuBackground"),
                        m_menu.style);
    if (m_ui_pending & MenuSelect and m_menu.ui_anchor)
        m_ui->menu_select(m_menu.selected);
    if (m_ui_pending & MenuHide)
        m_ui->menu_hide();

    const bool update_info_anchor = (m_ui_pending & Draw) and not (m_ui_pending & InfoHide) and
                                    not m_info.content.empty() and is_inline(m_info.style);
    if ((m_ui_pending & InfoShow) or update_info_anchor)
    {
        auto anchor = is_inline(m_info.style) ?
             window.display_position(m_info.anchor) : DisplayCoord{};
        if (not (m_ui_pending & MenuShow) and m_info.ui_anchor != anchor)
            m_ui_pending |= anchor ? InfoShow : InfoHide;
        m_info.ui_anchor = anchor;
    }

    if (m_ui_pending & InfoShow and m_info.ui_anchor)
        m_ui->info_show(m_info.title, m_info.content, *m_info.ui_anchor,
                        get_face("Information"), m_info.style);
    if (m_ui_pending & InfoHide)
        m_ui->info_hide();

    if (m_ui_pending & StatusLine)
        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));

    auto cursor = m_input_handler.get_cursor_info();
    m_ui->set_cursor(cursor.first, cursor.second);

    m_ui->refresh(m_ui_pending | Refresh);
    m_ui_pending = 0;
}

void Client::force_redraw()
{
    m_ui_pending |= Refresh | Draw | StatusLine |
        (m_menu.items.empty() ? MenuHide : MenuShow | MenuSelect) |
        (m_info.content.empty() ? InfoHide : InfoShow);
}

void Client::reload_buffer()
{
    Buffer& buffer = context().buffer();
    reload_file_buffer(buffer);
    context().print_status({ format("'{}' reloaded", buffer.display_name()),
                             get_face("Information") });
}

void Client::on_buffer_reload_key(Key key)
{
    auto& buffer = context().buffer();

    if (key == 'y' or key == Key::Return)
        reload_buffer();
    else if (key == 'n' or key == Key::Escape)
    {
        // reread timestamp in case the file was modified again
        buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
        print_status({ format("'{}' kept", buffer.display_name()),
                       get_face("Information") });
    }
    else
    {
        print_status({ format("'{}' is not a valid choice", key_to_str(key)),
                       get_face("Error") });
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
        return;
    }

    for (auto& client : ClientManager::instance())
    {
        if (&client->context().buffer() == &buffer and
            client->m_buffer_reload_dialog_opened)
            client->close_buffer_reload_dialog();
    }
}

void Client::close_buffer_reload_dialog()
{
    kak_assert(m_buffer_reload_dialog_opened);
    m_buffer_reload_dialog_opened = false;
    info_hide(true);
    m_input_handler.reset_normal_mode();
}

void Client::check_if_buffer_needs_reloading()
{
    if (m_buffer_reload_dialog_opened)
        return;

    Buffer& buffer = context().buffer();
    auto reload = context().options()["autoreload"].get<Autoreload>();
    if (not (buffer.flags() & Buffer::Flags::File) or reload == Autoreload::No)
        return;

    const String& filename = buffer.name();
    timespec ts = get_fs_timestamp(filename);
    if (ts == InvalidTime or ts == buffer.fs_timestamp())
        return;
    if (reload == Autoreload::Ask)
    {
        StringView bufname = buffer.display_name();
        info_show(format("reload '{}' ?", bufname),
                  format("'{}' was modified externally\n"
                         "press <ret> or y to reload, <esc> or n to keep",
                         bufname), {}, InfoStyle::Modal);

        m_buffer_reload_dialog_opened = true;
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
    }
    else
        reload_buffer();
}

StringView Client::get_env_var(StringView name) const
{
    auto it = m_env_vars.find(name);
    if (it == m_env_vars.end())
        return {};
    return it->value;
}

void Client::on_option_changed(const Option& option)
{
    if (option.name() == "ui_options")
    {
        m_ui->set_ui_options(option.get<UserInterface::Options>());
        m_ui_pending |= Draw;
    }
}

void Client::menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style)
{
    m_menu = Menu{ std::move(choices), anchor, {}, style, -1 };
    m_ui_pending |= MenuShow;
    m_ui_pending &= ~MenuHide;
}

void Client::menu_select(int selected)
{
    m_menu.selected = selected;
    m_ui_pending |= MenuSelect;
    m_ui_pending &= ~MenuHide;
}

void Client::menu_hide()
{
    m_menu = Menu{};
    m_ui_pending |= MenuHide;
    m_ui_pending &= ~(MenuShow | MenuSelect);
}

void Client::info_show(String title, String content, BufferCoord anchor, InfoStyle style)
{
    if (m_info.style == InfoStyle::Modal) // We already have a modal info opened, do not touch it.
        return;

    m_info = Info{ std::move(title), std::move(content), anchor, {}, style };
    m_ui_pending |= InfoShow;
    m_ui_pending &= ~InfoHide;
}

void Client::info_hide(bool even_modal)
{
    if (not even_modal and m_info.style == InfoStyle::Modal)
        return;

    m_info = Info{};
    m_ui_pending |= InfoHide;
    m_ui_pending &= ~InfoShow;
}

}
<commit_msg>Add '[debug]' context_info for debug buffers<commit_after>#include "client.hh"

#include "face_registry.hh"
#include "context.hh"
#include "buffer_manager.hh"
#include "buffer_utils.hh"
#include "file.hh"
#include "remote.hh"
#include "option.hh"
#include "client_manager.hh"
#include "command_manager.hh"
#include "event_manager.hh"
#include "user_interface.hh"
#include "window.hh"
#include "hash_map.hh"

#include <csignal>
#include <unistd.h>

#include <utility>

namespace Kakoune
{

Client::Client(std::unique_ptr<UserInterface>&& ui,
               std::unique_ptr<Window>&& window,
               SelectionList selections, int pid,
               EnvVarMap env_vars,
               String name,
               OnExitCallback on_exit)
    : m_ui{std::move(ui)}, m_window{std::move(window)},
      m_pid{pid},
      m_on_exit{std::move(on_exit)},
      m_input_handler{std::move(selections), Context::Flags::None,
                      std::move(name)},
      m_env_vars(std::move(env_vars))
{
    m_window->set_client(this);

    context().set_client(*this);
    context().set_window(*m_window);

    m_window->set_dimensions(m_ui->dimensions());
    m_window->options().register_watcher(*this);

    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
    m_ui->set_on_key([this](Key key) {
        if (key == ctrl('c'))
            killpg(getpgrp(), SIGINT);
        else
            m_pending_keys.push_back(key);
    });

    m_window->hooks().run_hook("WinDisplay", m_window->buffer().name(), context());

    force_redraw();
}

Client::~Client()
{
    m_window->options().unregister_watcher(*this);
    m_window->set_client(nullptr);
    // Do not move the selections here, as we need them to be valid
    // in order to correctly destroy the input handler
    ClientManager::instance().add_free_window(std::move(m_window),
                                              context().selections());
}

bool Client::process_pending_inputs()
{
    const bool debug_keys = (bool)(context().options()["debug"].get<DebugFlags>() & DebugFlags::Keys);
    // steal keys as we might receive new keys while handling them.
    Vector<Key, MemoryDomain::Client> keys = std::move(m_pending_keys);
    for (auto& key : keys)
    {
        try
        {
            if (debug_keys)
                write_to_debug_buffer(format("Client '{}' got key '{}'",
                                             context().name(), key_to_str(key)));

            if (key == Key::FocusIn)
                context().hooks().run_hook("FocusIn", context().name(), context());
            else if (key == Key::FocusOut)
                context().hooks().run_hook("FocusOut", context().name(), context());
            else if (key.modifiers == Key::Modifiers::Resize)
            {
                m_window->set_dimensions(m_ui->dimensions());
                force_redraw();
            }
            else
                m_input_handler.handle_key(key);

            context().hooks().run_hook("RawKey", key_to_str(key), context());
        }
        catch (Kakoune::runtime_error& error)
        {
            write_to_debug_buffer(format("Error: {}", error.what()));
            context().print_status({ fix_atom_text(error.what().str()), get_face("Error") });
            context().hooks().run_hook("RuntimeError", error.what(), context());
        }
    }
    return not keys.empty();
}

void Client::print_status(DisplayLine status_line, bool immediate)
{
    m_status_line = std::move(status_line);
    if (immediate)
    {
        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
        m_ui->refresh(true);
    }
    else
    {
        m_ui_pending |= StatusLine;
    }
}

DisplayCoord Client::dimensions() const
{
    return m_ui->dimensions();
}

String generate_context_info(const Context& context)
{
    String s = "";
    if (context.buffer().is_modified())
        s += "[+]";
    if (context.client().input_handler().is_recording())
        s += format("[recording ({})]", context.client().input_handler().recording_reg());
    if (context.buffer().flags() & Buffer::Flags::New)
        s += "[new file]";
    if (context.hooks_disabled())
        s += "[no-hooks]";
    if (context.buffer().flags() & Buffer::Flags::Fifo)
        s += "[fifo]";
    if (context.buffer().flags() & Buffer::Flags::Debug)
        s += "[debug]";
    return s;
}

DisplayLine Client::generate_mode_line() const
{
    DisplayLine modeline;
    try
    {
        const String& modelinefmt = context().options()["modelinefmt"].get<String>();
        HashMap<String, DisplayLine> atoms{{ "mode_info", context().client().input_handler().mode_line() },
                                           { "context_info", {generate_context_info(context()), get_face("Information")}}};
        auto expanded = expand(modelinefmt, context(), ShellContext{},
                               [](String s) { return escape(s, '{', '\\'); });
        modeline = parse_display_line(expanded, atoms);
    }
    catch (runtime_error& err)
    {
        write_to_debug_buffer(format("Error while parsing modelinefmt: {}", err.what()));
        modeline.push_back({ "modelinefmt error, see *debug* buffer", get_face("Error") });
    }

    return modeline;
}

void Client::change_buffer(Buffer& buffer)
{
    if (m_buffer_reload_dialog_opened)
        close_buffer_reload_dialog();

    auto* current = &m_window->buffer();
    m_last_buffer = contains(BufferManager::instance(), current) ? current : nullptr;

    auto& client_manager = ClientManager::instance();
    m_window->options().unregister_watcher(*this);
    m_window->set_client(nullptr);
    client_manager.add_free_window(std::move(m_window),
                                   std::move(context().selections()));
    WindowAndSelections ws = client_manager.get_free_window(buffer);

    m_window = std::move(ws.window);
    m_window->set_client(this);
    m_window->options().register_watcher(*this);
    m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());

    context().selections_write_only() = std::move(ws.selections);
    context().set_window(*m_window);
    m_window->set_dimensions(m_ui->dimensions());

    m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
    force_redraw();
}

static bool is_inline(InfoStyle style)
{
    return style == InfoStyle::Inline or
           style == InfoStyle::InlineAbove or
           style == InfoStyle::InlineBelow;
}

void Client::redraw_ifn()
{
    Window& window = context().window();
    if (window.needs_redraw(context()))
        m_ui_pending |= Draw;

    DisplayLine mode_line = generate_mode_line();
    if (mode_line.atoms() != m_mode_line.atoms())
    {
        m_ui_pending |= StatusLine;
        m_mode_line = std::move(mode_line);
    }

    if (m_ui_pending == 0)
        return;

    if (m_ui_pending & Draw)
        m_ui->draw(window.update_display_buffer(context()),
                   get_face("Default"), get_face("BufferPadding"));

    const bool update_menu_anchor = (m_ui_pending & Draw) and not (m_ui_pending & MenuHide) and
                                    not m_menu.items.empty() and m_menu.style == MenuStyle::Inline;
    if ((m_ui_pending & MenuShow) or update_menu_anchor)
    {
        auto anchor = m_menu.style == MenuStyle::Inline ?
            window.display_position(m_menu.anchor) : DisplayCoord{};
        if (not (m_ui_pending & MenuShow) and m_menu.ui_anchor != anchor)
            m_ui_pending |= anchor ? (MenuShow | MenuSelect) : MenuHide;
        m_menu.ui_anchor = anchor;
    }

    if (m_ui_pending & MenuShow and m_menu.ui_anchor)
        m_ui->menu_show(m_menu.items, *m_menu.ui_anchor,
                        get_face("MenuForeground"), get_face("MenuBackground"),
                        m_menu.style);
    if (m_ui_pending & MenuSelect and m_menu.ui_anchor)
        m_ui->menu_select(m_menu.selected);
    if (m_ui_pending & MenuHide)
        m_ui->menu_hide();

    const bool update_info_anchor = (m_ui_pending & Draw) and not (m_ui_pending & InfoHide) and
                                    not m_info.content.empty() and is_inline(m_info.style);
    if ((m_ui_pending & InfoShow) or update_info_anchor)
    {
        auto anchor = is_inline(m_info.style) ?
             window.display_position(m_info.anchor) : DisplayCoord{};
        if (not (m_ui_pending & MenuShow) and m_info.ui_anchor != anchor)
            m_ui_pending |= anchor ? InfoShow : InfoHide;
        m_info.ui_anchor = anchor;
    }

    if (m_ui_pending & InfoShow and m_info.ui_anchor)
        m_ui->info_show(m_info.title, m_info.content, *m_info.ui_anchor,
                        get_face("Information"), m_info.style);
    if (m_ui_pending & InfoHide)
        m_ui->info_hide();

    if (m_ui_pending & StatusLine)
        m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));

    auto cursor = m_input_handler.get_cursor_info();
    m_ui->set_cursor(cursor.first, cursor.second);

    m_ui->refresh(m_ui_pending | Refresh);
    m_ui_pending = 0;
}

void Client::force_redraw()
{
    m_ui_pending |= Refresh | Draw | StatusLine |
        (m_menu.items.empty() ? MenuHide : MenuShow | MenuSelect) |
        (m_info.content.empty() ? InfoHide : InfoShow);
}

void Client::reload_buffer()
{
    Buffer& buffer = context().buffer();
    reload_file_buffer(buffer);
    context().print_status({ format("'{}' reloaded", buffer.display_name()),
                             get_face("Information") });
}

void Client::on_buffer_reload_key(Key key)
{
    auto& buffer = context().buffer();

    if (key == 'y' or key == Key::Return)
        reload_buffer();
    else if (key == 'n' or key == Key::Escape)
    {
        // reread timestamp in case the file was modified again
        buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
        print_status({ format("'{}' kept", buffer.display_name()),
                       get_face("Information") });
    }
    else
    {
        print_status({ format("'{}' is not a valid choice", key_to_str(key)),
                       get_face("Error") });
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
        return;
    }

    for (auto& client : ClientManager::instance())
    {
        if (&client->context().buffer() == &buffer and
            client->m_buffer_reload_dialog_opened)
            client->close_buffer_reload_dialog();
    }
}

void Client::close_buffer_reload_dialog()
{
    kak_assert(m_buffer_reload_dialog_opened);
    m_buffer_reload_dialog_opened = false;
    info_hide(true);
    m_input_handler.reset_normal_mode();
}

void Client::check_if_buffer_needs_reloading()
{
    if (m_buffer_reload_dialog_opened)
        return;

    Buffer& buffer = context().buffer();
    auto reload = context().options()["autoreload"].get<Autoreload>();
    if (not (buffer.flags() & Buffer::Flags::File) or reload == Autoreload::No)
        return;

    const String& filename = buffer.name();
    timespec ts = get_fs_timestamp(filename);
    if (ts == InvalidTime or ts == buffer.fs_timestamp())
        return;
    if (reload == Autoreload::Ask)
    {
        StringView bufname = buffer.display_name();
        info_show(format("reload '{}' ?", bufname),
                  format("'{}' was modified externally\n"
                         "press <ret> or y to reload, <esc> or n to keep",
                         bufname), {}, InfoStyle::Modal);

        m_buffer_reload_dialog_opened = true;
        m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
    }
    else
        reload_buffer();
}

StringView Client::get_env_var(StringView name) const
{
    auto it = m_env_vars.find(name);
    if (it == m_env_vars.end())
        return {};
    return it->value;
}

void Client::on_option_changed(const Option& option)
{
    if (option.name() == "ui_options")
    {
        m_ui->set_ui_options(option.get<UserInterface::Options>());
        m_ui_pending |= Draw;
    }
}

void Client::menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style)
{
    m_menu = Menu{ std::move(choices), anchor, {}, style, -1 };
    m_ui_pending |= MenuShow;
    m_ui_pending &= ~MenuHide;
}

void Client::menu_select(int selected)
{
    m_menu.selected = selected;
    m_ui_pending |= MenuSelect;
    m_ui_pending &= ~MenuHide;
}

void Client::menu_hide()
{
    m_menu = Menu{};
    m_ui_pending |= MenuHide;
    m_ui_pending &= ~(MenuShow | MenuSelect);
}

void Client::info_show(String title, String content, BufferCoord anchor, InfoStyle style)
{
    if (m_info.style == InfoStyle::Modal) // We already have a modal info opened, do not touch it.
        return;

    m_info = Info{ std::move(title), std::move(content), anchor, {}, style };
    m_ui_pending |= InfoShow;
    m_ui_pending &= ~InfoHide;
}

void Client::info_hide(bool even_modal)
{
    if (not even_modal and m_info.style == InfoStyle::Modal)
        return;

    m_info = Info{};
    m_ui_pending |= InfoHide;
    m_ui_pending &= ~InfoShow;
}

}
<|endoftext|>


<commit_before>#include <coffee/core/CUnitTesting>
#include <coffee/core/CFiles>

using namespace Coffee;
using namespace CResources;

const constexpr sbyte_t probe_text[25] = "I'M THE TRASHMAN! Hello.";

bool resource_exist_test()
{
    {
        Resource rsc("the-one-that-works",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests limitations in implementation for names */
        if(!FileExists(rsc))
            return false;
    }

    {
        Resource rsc("filled-dir/subdir/we-need-to-go-deeper/odd-file-with-long-extension.txt.zip.exe",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests limitations in implementation for names */
        if(!FileExists(rsc))
            return false;
    }

    {
        Resource rsc("filled-dir/subdir/we-need-to-go-deeper/Spaced filename.txt",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests errors in scripts regarding spaces */
        if(!FileExists(rsc))
            return false;
    }

    return true;
}

const constexpr cstring filename_odd = "Oddball: æøå, カケ";

bool resource_exists_odd_characters_test()
{
    Resource rsc(filename_odd,
                 ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
    /* Tests what happens to unexpected characters. We want these to work. */
    /* If existence passes, we assume the rest works too for these cases. */
    return FileExists(rsc);
}

const constexpr cstring filename_testable = "filled-dir/subdir/we-need-to-go-deeper/odd-file-with-long-extension.txt.zip.exe";

bool resource_read_test()
{
    Resource rsc(filename_testable,
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FilePull(rsc))
        return false;

    if(sizeof(probe_text)-1 != rsc.size || !MemCmp(rsc.data,probe_text,rsc.size))
    {
        cDebug("Sizes: {0} ?= {1}",sizeof(probe_text),rsc.size);
        cDebug("Data:\n"
               "Internal: {0}\n"
               "Resource: {1}\n",
               StrUtil::hexdump(probe_text,sizeof(probe_text)),
               StrUtil::hexdump(rsc.data,rsc.size));
        return false;
    }

    FileFree(rsc);

    return true;
}

bool resource_map_test()
{
    Resource rsc("Oddball: æøå, カケ",
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FileMap(rsc,ResourceAccess::ReadOnly))
        return false;

    if(!FileUnmap(rsc))
        return false;

    return true;
}

bool resource_write_test()
{
    Resource rsc("Oddball: æøå, カケ",
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FileMap(rsc,ResourceAccess::ReadWrite))
        return false;

    if(!FileUnmap(rsc))
        return false;

    return true;
}

const constexpr CoffeeTest::Test _tests[10] = {
    {resource_exist_test,
     "Resource existence",
     "Test whether the resources are there"},
    {resource_read_test,
     "Resource reading",
     "Opening and reading a resource, uses an odd filename"},

    /* The ones below only test feature sets */

    {resource_exists_odd_characters_test,
     "Gettin weird with filenames",
     "Test what happens with multibyte characters",true},

    {resource_map_test,
     "Resource mapping",
     "If the resources are mappable",true},
    {resource_write_test,
     "Resource writing",
     "If the resources are writable",true},
};

COFFEE_RUN_TESTS(_tests);
<commit_msg> - Make packaging-api/test01 more friendly to Win32 by dumbing it down<commit_after>#include <coffee/core/CUnitTesting>
#include <coffee/core/CFiles>

using namespace Coffee;
using namespace CResources;

const constexpr sbyte_t probe_text[25] = "I'M THE TRASHMAN! Hello.";

bool resource_exist_test()
{
    {
        Resource rsc("the-one-that-works",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests limitations in implementation for names */
        if(!FileExists(rsc))
            return false;
    }

    {
        Resource rsc("filled-dir/subdir/we-need-to-go-deeper/odd-file-with-long-extension.txt.zip.exe",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests limitations in implementation for names */
        if(!FileExists(rsc))
            return false;
    }

    {
        Resource rsc("filled-dir/subdir/we-need-to-go-deeper/Spaced filename.txt",
                     ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
        /* Tests errors in scripts regarding spaces */
        if(!FileExists(rsc))
            return false;
    }

    return true;
}

const constexpr cstring filename_odd = "Oddball: æøå, カケ";

bool resource_exists_odd_characters_test()
{
    Resource rsc(filename_odd,
                 ResourceAccess::SpecifyStorage|ResourceAccess::AssetFile);
    /* Tests what happens to unexpected characters. We want these to work. */
    /* If existence passes, we assume the rest works too for these cases. */
	/* It is known that it does not work with Win32's resource system. */
    return FileExists(rsc);
}

const constexpr cstring filename_testable = "filled-dir/subdir/we-need-to-go-deeper/odd-file-with-long-extension.txt.zip.exe";

bool resource_read_test()
{
    Resource rsc(filename_testable,
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FilePull(rsc))
        return false;

    if(sizeof(probe_text)-1 != rsc.size || !MemCmp(rsc.data,probe_text,rsc.size))
    {
        cDebug("Sizes: {0} ?= {1}", sizeof(probe_text) - 1,rsc.size);
        cDebug("Data:\n"
               "Internal: {0}\n"
               "Resource: {1}\n",
               StrUtil::hexdump(probe_text, sizeof(probe_text) - 1),
               StrUtil::hexdump(rsc.data,rsc.size));
        return false;
    }

    FileFree(rsc);

    return true;
}

bool resource_map_test()
{
    Resource rsc(filename_testable,
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FileMap(rsc,ResourceAccess::ReadOnly))
        return false;

    if(!FileUnmap(rsc))
        return false;

    return true;
}

bool resource_write_test()
{
    Resource rsc(filename_testable,
                 ResourceAccess::SpecifyStorage
                 |ResourceAccess::AssetFile);

    if(!FileMap(rsc,ResourceAccess::ReadWrite))
        return false;

    if(!FileUnmap(rsc))
        return false;

    return true;
}

const constexpr CoffeeTest::Test _tests[10] = {
    {resource_exist_test,
     "Resource existence",
     "Test whether the resources are there"},
    {resource_read_test,
     "Resource reading",
     "Opening and reading a resource, uses an odd filename"},

    /* The ones below only test feature sets */

    {resource_exists_odd_characters_test,
     "Gettin weird with filenames",
     "Test what happens with multibyte characters",true},

    {resource_map_test,
     "Resource mapping",
     "If the resources are mappable",true},
    {resource_write_test,
     "Resource writing",
     "If the resources are writable",true},
};

COFFEE_RUN_TESTS(_tests);
<|endoftext|>


<commit_before>#include <iostream>
#include "parser.h"

int
main(int argc, char * argv[])
{
	if (argc != 2) {
		std::cout << "Try ./calc expr" << std::endl;
		return 0;
	}

	try {
		std::cout << calc(argv[1]) << std::endl;
	}
	catch(const char *msg) {
		std::cout << msg << std::endl;
		return 1;
	}

	return 0;
}
<commit_msg>added non-zero exit code<commit_after>#include <iostream>
#include "parser.h"

int
main(int argc, char * argv[])
{
	if (argc != 2) {
		std::cout << "Try ./calc expr" << std::endl;
		return 0;
	}

	try {
		std::cout << calc(argv[1]) << std::endl;
	}
	catch(const char *msg) {
		std::cout << msg << std::endl;
		//code 1
		return 1;
	}

	return 0;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferSceneUI/SceneGadget.h"

#include "GafferUI/ViewportGadget.h"

#include "Gaffer/BackgroundTask.h"
#include "Gaffer/Node.h"
#include "Gaffer/StringPlug.h"

#include "IECoreGL/CachedConverter.h"
#include "IECoreGL/CurvesPrimitive.h"
#include "IECoreGL/PointsPrimitive.h"
#include "IECoreGL/Primitive.h"
#include "IECoreGL/Renderable.h"
#include "IECoreGL/Selector.h"

#include "IECoreScene/CurvesPrimitive.h"

#include "IECore/MessageHandler.h"

#include "boost/algorithm/string/predicate.hpp"
#include "boost/bind.hpp"

#include "tbb/concurrent_unordered_set.h"
#include "tbb/task.h"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferUI;
using namespace GafferScene;
using namespace GafferSceneUI;

//////////////////////////////////////////////////////////////////////////
// SceneGadget implementation
//////////////////////////////////////////////////////////////////////////

SceneGadget::SceneGadget()
	:	Gadget( defaultName<SceneGadget>() ),
		m_paused( false ),
		m_renderer( IECoreScenePreview::Renderer::create( "OpenGL", IECoreScenePreview::Renderer::Interactive ) ),
		m_controller( nullptr, nullptr, m_renderer ),
		m_updateErrored( false ),
		m_renderRequestPending( false )
{
	typedef CompoundObject::ObjectMap::value_type Option;
	CompoundObjectPtr openGLOptions = new CompoundObject;
	openGLOptions->members().insert( {
		Option( "gl:primitive:wireframeColor", new Color4fData( Color4f( 0.2f, 0.2f, 0.2f, 1.0f ) ) ),
		Option( "gl:primitive:pointColor", new Color4fData( Color4f( 0.9f, 0.9f, 0.9f, 1.0f ) ) ),
		Option( "gl:primitive:pointWidth", new FloatData( 2.0f ) )
	} );
	setOpenGLOptions( openGLOptions.get() );

	m_controller.updateRequiredSignal().connect(
		boost::bind( &SceneGadget::requestRender, this )
	);

	visibilityChangedSignal().connect( boost::bind( &SceneGadget::visibilityChanged, this ) );

	setContext( new Context );
}

SceneGadget::~SceneGadget()
{
	// Make sure background task completes before anything
	// it relies on is destroyed.
	m_updateTask.reset();
}

void SceneGadget::setScene( GafferScene::ConstScenePlugPtr scene )
{
	m_controller.setScene( scene );
}

const GafferScene::ScenePlug *SceneGadget::getScene() const
{
	return m_controller.getScene();
}

void SceneGadget::setContext( Gaffer::ConstContextPtr context )
{
	m_controller.setContext( context );
}

const Gaffer::Context *SceneGadget::getContext() const
{
	return m_controller.getContext();
}

void SceneGadget::setExpandedPaths( const IECore::PathMatcher &expandedPaths )
{
	m_controller.setExpandedPaths( expandedPaths );
}

const IECore::PathMatcher &SceneGadget::getExpandedPaths() const
{
	return m_controller.getExpandedPaths();
}

void SceneGadget::setMinimumExpansionDepth( size_t depth )
{
	m_controller.setMinimumExpansionDepth( depth );
}

size_t SceneGadget::getMinimumExpansionDepth() const
{
	return m_controller.getMinimumExpansionDepth();
}

void SceneGadget::setPaused( bool paused )
{
	if( paused == m_paused )
	{
		return;
	}

	m_paused = paused;
	if( m_paused )
	{
		if( m_updateTask )
		{
			m_updateTask->cancelAndWait();
			m_updateTask.reset();
		}
		stateChangedSignal()( this );
	}
	else if( m_controller.updateRequired() )
	{
		requestRender();
	}
}

bool SceneGadget::getPaused() const
{
	return m_paused;
}

void SceneGadget::setBlockingPaths( const IECore::PathMatcher &blockingPaths )
{
	if( m_updateTask )
	{
		m_updateTask->cancelAndWait();
		m_updateTask.reset();
	}
	m_blockingPaths = blockingPaths;
	requestRender();
}

const IECore::PathMatcher &SceneGadget::getBlockingPaths() const
{
	return m_blockingPaths;
}

void SceneGadget::setPriorityPaths( const IECore::PathMatcher &priorityPaths )
{
	if( m_updateTask )
	{
		m_updateTask->cancelAndWait();
		m_updateTask.reset();
	}
	m_priorityPaths = priorityPaths;
	requestRender();
}

const IECore::PathMatcher &SceneGadget::getPriorityPaths() const
{
	return m_priorityPaths;
}

SceneGadget::State SceneGadget::state() const
{
	if( m_paused )
	{
		return Paused;
	}

	return m_controller.updateRequired() ? Running : Complete;
}

SceneGadget::SceneGadgetSignal &SceneGadget::stateChangedSignal()
{
	return m_stateChangedSignal;
}

void SceneGadget::waitForCompletion()
{
	updateRenderer();
	if( m_updateTask )
	{
		m_updateTask->wait();
	}
}

void SceneGadget::setOpenGLOptions( const IECore::CompoundObject *options )
{
	if( m_openGLOptions && *m_openGLOptions == *options )
	{
		return;
	}

	// Output anything that has changed or was added

	for( const auto &option : options->members() )
	{
		bool changedOrAdded = true;
		if( m_openGLOptions )
		{
			if( const Object *previousOption = m_openGLOptions->member<Object>( option.first ) )
			{
				changedOrAdded = *previousOption != *option.second;
			}
		}
		if( changedOrAdded )
		{
			m_renderer->option( option.first, option.second.get() );
		}
	}

	// Remove anything that was removed

	if( m_openGLOptions )
	{
		for( const auto &oldOption : m_openGLOptions->members() )
		{
			if( !options->member<Object>( oldOption.first ) )
			{
				m_renderer->option( oldOption.first, nullptr );
			}
		}
	}

	m_openGLOptions = options->copy();
	requestRender();
}

const IECore::CompoundObject *SceneGadget::getOpenGLOptions() const
{
	return m_openGLOptions.get();
}

void SceneGadget::setSelectionMask( const IECore::StringVectorData *typeNames )
{
	m_selectionMask = typeNames ? typeNames->copy() : nullptr;
}

const IECore::StringVectorData *SceneGadget::getSelectionMask() const
{
	return m_selectionMask.get();
}

bool SceneGadget::objectAt( const IECore::LineSegment3f &lineInGadgetSpace, GafferScene::ScenePlug::ScenePath &path ) const
{
	std::vector<IECoreGL::HitRecord> selection;
	{
		ViewportGadget::SelectionScope selectionScope( lineInGadgetSpace, this, selection, IECoreGL::Selector::IDRender );
		renderScene();
	}

	if( !selection.size() )
	{
		return false;
	}

	float depthMin = selection[0].depthMin;
	unsigned int name = selection[0].name;
	for( const auto &i : selection )
	{
		if( i.depthMin < depthMin )
		{
			depthMin = i.depthMin;
			name = i.name;
		}
	}

	PathMatcher paths = convertSelection( new UIntVectorData( { name } ) );
	if( paths.isEmpty() )
	{
		return false;
	}

	path = *PathMatcher::Iterator( paths.begin() );
	return true;
}

size_t SceneGadget::objectsAt(
	const Imath::V3f &corner0InGadgetSpace,
	const Imath::V3f &corner1InGadgetSpace,
	IECore::PathMatcher &paths
) const
{

	vector<IECoreGL::HitRecord> selection;
	{
		ViewportGadget::SelectionScope selectionScope( corner0InGadgetSpace, corner1InGadgetSpace, this, selection, IECoreGL::Selector::OcclusionQuery );
		renderScene();
	}

	UIntVectorDataPtr ids = new UIntVectorData;
	std::transform(
		selection.begin(), selection.end(), std::back_inserter( ids->writable() ),
		[]( const IECoreGL::HitRecord &h ) { return h.name; }
	);

	PathMatcher selectedPaths = convertSelection( ids );
	paths.addPaths( selectedPaths );

	return selectedPaths.size();
}

IECore::PathMatcher SceneGadget::convertSelection( IECore::UIntVectorDataPtr ids ) const
{
	CompoundDataMap parameters = { { "selection", ids } };
	if( m_selectionMask )
	{
		parameters["mask"] = m_selectionMask;
	}

	auto pathsData = static_pointer_cast<PathMatcherData>(
		m_renderer->command(
			"gl:querySelection",
			parameters
		)
	);

	PathMatcher result = pathsData->readable();

	// Unexpanded locations are represented with
	// objects named __unexpandedChildren__ to allow
	// locations to have an object _and_ children.
	// We want to replace any such locations with their
	// parent location.
	const InternedString unexpandedChildren = "__unexpandedChildren__";
	vector<InternedString> parent;

	PathMatcher toAdd;
	PathMatcher toRemove;
	for( PathMatcher::Iterator it = result.begin(), eIt = result.end(); it != eIt; ++it )
	{
		if( it->size() && it->back() == unexpandedChildren )
		{
			toRemove.addPath( *it );
			parent.assign( it->begin(), it->end() - 1 );
			toAdd.addPath( parent );
		}
	}

	result.addPaths( toAdd );
	result.removePaths( toRemove );

	return result;
}

const IECore::PathMatcher &SceneGadget::getSelection() const
{
	return m_selection;
}

void SceneGadget::setSelection( const IECore::PathMatcher &selection )
{
	m_selection = selection;
	ConstDataPtr d = new IECore::PathMatcherData( selection );
	m_renderer->option( "gl:selection", d.get() );
	requestRender();
}

Imath::Box3f SceneGadget::selectionBound() const
{
	DataPtr d = m_renderer->command( "gl:queryBound", { { "selection", new BoolData( true ) } } );
	return static_cast<Box3fData *>( d.get() )->readable();
}

std::string SceneGadget::getToolTip( const IECore::LineSegment3f &line ) const
{
	std::string result = Gadget::getToolTip( line );
	if( result.size() )
	{
		return result;
	}

	ScenePlug::ScenePath path;
	if( objectAt( line, path ) )
	{
		ScenePlug::pathToString( path, result );
	}

	return result;
}

Imath::Box3f SceneGadget::bound() const
{
	if( m_updateErrored )
	{
		return Box3f();
	}
	DataPtr d = m_renderer->command( "gl:queryBound" );
	return static_cast<Box3fData *>( d.get() )->readable();
}

void SceneGadget::doRenderLayer( Layer layer, const GafferUI::Style *style ) const
{
	if( layer != Layer::Main )
	{
		return;
	}

	if( IECoreGL::Selector::currentSelector() )
	{
		return;
	}

	const_cast<SceneGadget *>( this )->updateRenderer();
	renderScene();
}

void SceneGadget::updateRenderer()
{
	if( m_paused )
	{
		return;
	}

	if( m_updateTask )
	{
		if( m_updateTask->status() == BackgroundTask::Running )
		{
			return;
		}
		m_updateTask.reset();
	}

	if( !m_controller.updateRequired() )
	{
		return;
	}

	auto progressCallback = [this] ( BackgroundTask::Status progress ) {

		if( !refCount() )
		{
			return;
		}
		bool shouldRequestRender = !m_renderRequestPending.exchange( true );
		bool shouldEmitStateChange =
			progress == BackgroundTask::Completed ||
			progress == BackgroundTask::Errored
		;

		if( shouldRequestRender || shouldEmitStateChange )
		{
			// Must hold a reference to stop us dying before our UI thread call is scheduled.
			SceneGadgetPtr thisRef = this;
			ParallelAlgo::callOnUIThread(
				[thisRef, shouldRequestRender, shouldEmitStateChange, progress] {
					if( progress == BackgroundTask::Errored )
					{
						thisRef->m_updateErrored = true;
					}
					if( shouldEmitStateChange )
					{
						thisRef->stateChangedSignal()( thisRef.get() );
					}
					if( shouldRequestRender )
					{
						thisRef->m_renderRequestPending = false;
						thisRef->requestRender();
					}
				}
			);
		}

	};

	if( !m_blockingPaths.isEmpty() )
	{
		try
		{
			m_controller.updateMatchingPaths( m_blockingPaths );
		}
		catch( std::exception &e )
		{
			// Leave it to the rest of the UI to report the error.
			m_updateErrored = true;
		}
	}

	m_updateErrored = false;
	m_updateTask = m_controller.updateInBackground( progressCallback, m_priorityPaths );
	stateChangedSignal()( this );

	// Give ourselves a 0.1s grace period in which we block
	// the UI while our updates occur. This means that for reasonably
	// interactive animation or manipulation, we only show the final
	// result, rathen than a series of partial intermediate results.
	// It also prevents a "cancellation storm" where new UI events
	// cancel our background updates faster than we can show them.
	m_updateTask->waitFor( 0.1 );
}

void SceneGadget::renderScene() const
{
	if( m_updateErrored )
	{
		return;
	}
	m_renderer->render();
}

void SceneGadget::visibilityChanged()
{
	if( !visible() && m_updateTask )
	{
		m_updateTask->cancelAndWait();
	}
}
<commit_msg>SceneGadget : Remove unused includes<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "GafferSceneUI/SceneGadget.h"

#include "GafferUI/ViewportGadget.h"

#include "Gaffer/BackgroundTask.h"

#include "boost/bind.hpp"

using namespace std;
using namespace Imath;
using namespace IECore;
using namespace Gaffer;
using namespace GafferUI;
using namespace GafferScene;
using namespace GafferSceneUI;

//////////////////////////////////////////////////////////////////////////
// SceneGadget implementation
//////////////////////////////////////////////////////////////////////////

SceneGadget::SceneGadget()
	:	Gadget( defaultName<SceneGadget>() ),
		m_paused( false ),
		m_renderer( IECoreScenePreview::Renderer::create( "OpenGL", IECoreScenePreview::Renderer::Interactive ) ),
		m_controller( nullptr, nullptr, m_renderer ),
		m_updateErrored( false ),
		m_renderRequestPending( false )
{
	typedef CompoundObject::ObjectMap::value_type Option;
	CompoundObjectPtr openGLOptions = new CompoundObject;
	openGLOptions->members().insert( {
		Option( "gl:primitive:wireframeColor", new Color4fData( Color4f( 0.2f, 0.2f, 0.2f, 1.0f ) ) ),
		Option( "gl:primitive:pointColor", new Color4fData( Color4f( 0.9f, 0.9f, 0.9f, 1.0f ) ) ),
		Option( "gl:primitive:pointWidth", new FloatData( 2.0f ) )
	} );
	setOpenGLOptions( openGLOptions.get() );

	m_controller.updateRequiredSignal().connect(
		boost::bind( &SceneGadget::requestRender, this )
	);

	visibilityChangedSignal().connect( boost::bind( &SceneGadget::visibilityChanged, this ) );

	setContext( new Context );
}

SceneGadget::~SceneGadget()
{
	// Make sure background task completes before anything
	// it relies on is destroyed.
	m_updateTask.reset();
}

void SceneGadget::setScene( GafferScene::ConstScenePlugPtr scene )
{
	m_controller.setScene( scene );
}

const GafferScene::ScenePlug *SceneGadget::getScene() const
{
	return m_controller.getScene();
}

void SceneGadget::setContext( Gaffer::ConstContextPtr context )
{
	m_controller.setContext( context );
}

const Gaffer::Context *SceneGadget::getContext() const
{
	return m_controller.getContext();
}

void SceneGadget::setExpandedPaths( const IECore::PathMatcher &expandedPaths )
{
	m_controller.setExpandedPaths( expandedPaths );
}

const IECore::PathMatcher &SceneGadget::getExpandedPaths() const
{
	return m_controller.getExpandedPaths();
}

void SceneGadget::setMinimumExpansionDepth( size_t depth )
{
	m_controller.setMinimumExpansionDepth( depth );
}

size_t SceneGadget::getMinimumExpansionDepth() const
{
	return m_controller.getMinimumExpansionDepth();
}

void SceneGadget::setPaused( bool paused )
{
	if( paused == m_paused )
	{
		return;
	}

	m_paused = paused;
	if( m_paused )
	{
		if( m_updateTask )
		{
			m_updateTask->cancelAndWait();
			m_updateTask.reset();
		}
		stateChangedSignal()( this );
	}
	else if( m_controller.updateRequired() )
	{
		requestRender();
	}
}

bool SceneGadget::getPaused() const
{
	return m_paused;
}

void SceneGadget::setBlockingPaths( const IECore::PathMatcher &blockingPaths )
{
	if( m_updateTask )
	{
		m_updateTask->cancelAndWait();
		m_updateTask.reset();
	}
	m_blockingPaths = blockingPaths;
	requestRender();
}

const IECore::PathMatcher &SceneGadget::getBlockingPaths() const
{
	return m_blockingPaths;
}

void SceneGadget::setPriorityPaths( const IECore::PathMatcher &priorityPaths )
{
	if( m_updateTask )
	{
		m_updateTask->cancelAndWait();
		m_updateTask.reset();
	}
	m_priorityPaths = priorityPaths;
	requestRender();
}

const IECore::PathMatcher &SceneGadget::getPriorityPaths() const
{
	return m_priorityPaths;
}

SceneGadget::State SceneGadget::state() const
{
	if( m_paused )
	{
		return Paused;
	}

	return m_controller.updateRequired() ? Running : Complete;
}

SceneGadget::SceneGadgetSignal &SceneGadget::stateChangedSignal()
{
	return m_stateChangedSignal;
}

void SceneGadget::waitForCompletion()
{
	updateRenderer();
	if( m_updateTask )
	{
		m_updateTask->wait();
	}
}

void SceneGadget::setOpenGLOptions( const IECore::CompoundObject *options )
{
	if( m_openGLOptions && *m_openGLOptions == *options )
	{
		return;
	}

	// Output anything that has changed or was added

	for( const auto &option : options->members() )
	{
		bool changedOrAdded = true;
		if( m_openGLOptions )
		{
			if( const Object *previousOption = m_openGLOptions->member<Object>( option.first ) )
			{
				changedOrAdded = *previousOption != *option.second;
			}
		}
		if( changedOrAdded )
		{
			m_renderer->option( option.first, option.second.get() );
		}
	}

	// Remove anything that was removed

	if( m_openGLOptions )
	{
		for( const auto &oldOption : m_openGLOptions->members() )
		{
			if( !options->member<Object>( oldOption.first ) )
			{
				m_renderer->option( oldOption.first, nullptr );
			}
		}
	}

	m_openGLOptions = options->copy();
	requestRender();
}

const IECore::CompoundObject *SceneGadget::getOpenGLOptions() const
{
	return m_openGLOptions.get();
}

void SceneGadget::setSelectionMask( const IECore::StringVectorData *typeNames )
{
	m_selectionMask = typeNames ? typeNames->copy() : nullptr;
}

const IECore::StringVectorData *SceneGadget::getSelectionMask() const
{
	return m_selectionMask.get();
}

bool SceneGadget::objectAt( const IECore::LineSegment3f &lineInGadgetSpace, GafferScene::ScenePlug::ScenePath &path ) const
{
	std::vector<IECoreGL::HitRecord> selection;
	{
		ViewportGadget::SelectionScope selectionScope( lineInGadgetSpace, this, selection, IECoreGL::Selector::IDRender );
		renderScene();
	}

	if( !selection.size() )
	{
		return false;
	}

	float depthMin = selection[0].depthMin;
	unsigned int name = selection[0].name;
	for( const auto &i : selection )
	{
		if( i.depthMin < depthMin )
		{
			depthMin = i.depthMin;
			name = i.name;
		}
	}

	PathMatcher paths = convertSelection( new UIntVectorData( { name } ) );
	if( paths.isEmpty() )
	{
		return false;
	}

	path = *PathMatcher::Iterator( paths.begin() );
	return true;
}

size_t SceneGadget::objectsAt(
	const Imath::V3f &corner0InGadgetSpace,
	const Imath::V3f &corner1InGadgetSpace,
	IECore::PathMatcher &paths
) const
{

	vector<IECoreGL::HitRecord> selection;
	{
		ViewportGadget::SelectionScope selectionScope( corner0InGadgetSpace, corner1InGadgetSpace, this, selection, IECoreGL::Selector::OcclusionQuery );
		renderScene();
	}

	UIntVectorDataPtr ids = new UIntVectorData;
	std::transform(
		selection.begin(), selection.end(), std::back_inserter( ids->writable() ),
		[]( const IECoreGL::HitRecord &h ) { return h.name; }
	);

	PathMatcher selectedPaths = convertSelection( ids );
	paths.addPaths( selectedPaths );

	return selectedPaths.size();
}

IECore::PathMatcher SceneGadget::convertSelection( IECore::UIntVectorDataPtr ids ) const
{
	CompoundDataMap parameters = { { "selection", ids } };
	if( m_selectionMask )
	{
		parameters["mask"] = m_selectionMask;
	}

	auto pathsData = static_pointer_cast<PathMatcherData>(
		m_renderer->command(
			"gl:querySelection",
			parameters
		)
	);

	PathMatcher result = pathsData->readable();

	// Unexpanded locations are represented with
	// objects named __unexpandedChildren__ to allow
	// locations to have an object _and_ children.
	// We want to replace any such locations with their
	// parent location.
	const InternedString unexpandedChildren = "__unexpandedChildren__";
	vector<InternedString> parent;

	PathMatcher toAdd;
	PathMatcher toRemove;
	for( PathMatcher::Iterator it = result.begin(), eIt = result.end(); it != eIt; ++it )
	{
		if( it->size() && it->back() == unexpandedChildren )
		{
			toRemove.addPath( *it );
			parent.assign( it->begin(), it->end() - 1 );
			toAdd.addPath( parent );
		}
	}

	result.addPaths( toAdd );
	result.removePaths( toRemove );

	return result;
}

const IECore::PathMatcher &SceneGadget::getSelection() const
{
	return m_selection;
}

void SceneGadget::setSelection( const IECore::PathMatcher &selection )
{
	m_selection = selection;
	ConstDataPtr d = new IECore::PathMatcherData( selection );
	m_renderer->option( "gl:selection", d.get() );
	requestRender();
}

Imath::Box3f SceneGadget::selectionBound() const
{
	DataPtr d = m_renderer->command( "gl:queryBound", { { "selection", new BoolData( true ) } } );
	return static_cast<Box3fData *>( d.get() )->readable();
}

std::string SceneGadget::getToolTip( const IECore::LineSegment3f &line ) const
{
	std::string result = Gadget::getToolTip( line );
	if( result.size() )
	{
		return result;
	}

	ScenePlug::ScenePath path;
	if( objectAt( line, path ) )
	{
		ScenePlug::pathToString( path, result );
	}

	return result;
}

Imath::Box3f SceneGadget::bound() const
{
	if( m_updateErrored )
	{
		return Box3f();
	}
	DataPtr d = m_renderer->command( "gl:queryBound" );
	return static_cast<Box3fData *>( d.get() )->readable();
}

void SceneGadget::doRenderLayer( Layer layer, const GafferUI::Style *style ) const
{
	if( layer != Layer::Main )
	{
		return;
	}

	if( IECoreGL::Selector::currentSelector() )
	{
		return;
	}

	const_cast<SceneGadget *>( this )->updateRenderer();
	renderScene();
}

void SceneGadget::updateRenderer()
{
	if( m_paused )
	{
		return;
	}

	if( m_updateTask )
	{
		if( m_updateTask->status() == BackgroundTask::Running )
		{
			return;
		}
		m_updateTask.reset();
	}

	if( !m_controller.updateRequired() )
	{
		return;
	}

	auto progressCallback = [this] ( BackgroundTask::Status progress ) {

		if( !refCount() )
		{
			return;
		}
		bool shouldRequestRender = !m_renderRequestPending.exchange( true );
		bool shouldEmitStateChange =
			progress == BackgroundTask::Completed ||
			progress == BackgroundTask::Errored
		;

		if( shouldRequestRender || shouldEmitStateChange )
		{
			// Must hold a reference to stop us dying before our UI thread call is scheduled.
			SceneGadgetPtr thisRef = this;
			ParallelAlgo::callOnUIThread(
				[thisRef, shouldRequestRender, shouldEmitStateChange, progress] {
					if( progress == BackgroundTask::Errored )
					{
						thisRef->m_updateErrored = true;
					}
					if( shouldEmitStateChange )
					{
						thisRef->stateChangedSignal()( thisRef.get() );
					}
					if( shouldRequestRender )
					{
						thisRef->m_renderRequestPending = false;
						thisRef->requestRender();
					}
				}
			);
		}

	};

	if( !m_blockingPaths.isEmpty() )
	{
		try
		{
			m_controller.updateMatchingPaths( m_blockingPaths );
		}
		catch( std::exception &e )
		{
			// Leave it to the rest of the UI to report the error.
			m_updateErrored = true;
		}
	}

	m_updateErrored = false;
	m_updateTask = m_controller.updateInBackground( progressCallback, m_priorityPaths );
	stateChangedSignal()( this );

	// Give ourselves a 0.1s grace period in which we block
	// the UI while our updates occur. This means that for reasonably
	// interactive animation or manipulation, we only show the final
	// result, rathen than a series of partial intermediate results.
	// It also prevents a "cancellation storm" where new UI events
	// cancel our background updates faster than we can show them.
	m_updateTask->waitFor( 0.1 );
}

void SceneGadget::renderScene() const
{
	if( m_updateErrored )
	{
		return;
	}
	m_renderer->render();
}

void SceneGadget::visibilityChanged()
{
	if( !visible() && m_updateTask )
	{
		m_updateTask->cancelAndWait();
	}
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "core/Setup.h"
#include <iostream>
#include <string>

#if OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
#include <sys/syslog.h>
#endif

#if OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#if OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#if OUZEL_PLATFORM_EMSCRIPTEN
#include <emscripten.h>
#endif

#include "Log.hpp"

namespace ouzel
{
#ifdef DEBUG
    Log::Level Log::threshold = Log::Level::ALL;
#else
    Log::Level Log::threshold = Log::Level::INFO;

#endif

    Log::~Log()
    {
        if (!s.empty())
        {
#if OUZEL_PLATFORM_MACOS || OUZEL_PLATFORM_LINUX || OUZEL_PLATFORM_RASPBIAN
            switch (level)
            {
                case Level::ERR:
                case Level::WARN:
                    std::cerr << s << std::endl;
                    break;
                case Level::INFO:
                case Level::ALL:
                    std::cout << s << std::endl;
                    break;
                default: break;
            }
#elif OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
            int priority = 0;
            switch (level)
            {
                case Level::ERR: priority = LOG_ERR; break;
                case Level::WARN: priority = LOG_WARNING; break;
                case Level::INFO: priority = LOG_INFO; break;
                case Level::ALL: priority = LOG_DEBUG; break;
                default: break;
            }
            syslog(priority, "%s", s.c_str());
#elif OUZEL_PLATFORM_WINDOWS
            std::vector<wchar_t> szBuffer(s.length() + 1);
            if (MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, szBuffer.data(), static_cast<int>(szBuffer.size())) == 0)
            {
                Log(Log::Level::ERR) << "Failed to convert UTF-8 to wide char";
                return;
            }

            StringCchCatW(szBuffer.data(), szBuffer.size(), L"\n");
            OutputDebugStringW(szBuffer.data());

    #if DEBUG
            HANDLE handle = 0;
            switch (level)
            {
            case Level::ERR:
            case Level::WARN:
                handle = GetStdHandle(STD_ERROR_HANDLE);
                break;
            case Level::INFO:
            case Level::ALL:
                handle = GetStdHandle(STD_OUTPUT_HANDLE);
                break;
            default: break;
            }

            if (handle)
            {
                DWORD bytesWritten;
                WriteConsoleW(handle, szBuffer.data(), static_cast<DWORD>(wcslen(szBuffer.data())), &bytesWritten, nullptr);
            }
    #endif

#elif OUZEL_PLATFORM_ANDROID
            int priority = 0;
            switch (level)
            {
                case Level::ERR: priority = ANDROID_LOG_ERROR; break;
                case Level::WARN: priority = ANDROID_LOG_WARN; break;
                case Level::INFO: priority = ANDROID_LOG_INFO; break;
                case Level::ALL: priority = ANDROID_LOG_DEBUG; break;
                default: break;
            }
            __android_log_print(priority, "Ouzel", "%s", s.c_str());
#elif OUZEL_PLATFORM_EMSCRIPTEN
            int flags = EM_LOG_CONSOLE;
            if (level == Level::ERR) flags |= EM_LOG_ERROR;
            else if (level == Level::WARN) flags |= EM_LOG_WARN;
            emscripten_log(flags, "%s", s.c_str());
#endif
            s.clear();
        }
    }
}
<commit_msg>Readd the +1<commit_after>// Copyright (C) 2018 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "core/Setup.h"
#include <iostream>
#include <string>

#if OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
#include <sys/syslog.h>
#endif

#if OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#if OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#if OUZEL_PLATFORM_EMSCRIPTEN
#include <emscripten.h>
#endif

#include "Log.hpp"

namespace ouzel
{
#ifdef DEBUG
    Log::Level Log::threshold = Log::Level::ALL;
#else
    Log::Level Log::threshold = Log::Level::INFO;

#endif

    Log::~Log()
    {
        if (!s.empty())
        {
#if OUZEL_PLATFORM_MACOS || OUZEL_PLATFORM_LINUX || OUZEL_PLATFORM_RASPBIAN
            switch (level)
            {
                case Level::ERR:
                case Level::WARN:
                    std::cerr << s << std::endl;
                    break;
                case Level::INFO:
                case Level::ALL:
                    std::cout << s << std::endl;
                    break;
                default: break;
            }
#elif OUZEL_PLATFORM_IOS || OUZEL_PLATFORM_TVOS
            int priority = 0;
            switch (level)
            {
                case Level::ERR: priority = LOG_ERR; break;
                case Level::WARN: priority = LOG_WARNING; break;
                case Level::INFO: priority = LOG_INFO; break;
                case Level::ALL: priority = LOG_DEBUG; break;
                default: break;
            }
            syslog(priority, "%s", s.c_str());
#elif OUZEL_PLATFORM_WINDOWS
            std::vector<wchar_t> szBuffer(s.length() + 1 + 1); // for the newline and the terminating char
            if (MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, szBuffer.data(), static_cast<int>(szBuffer.size())) == 0)
            {
                Log(Log::Level::ERR) << "Failed to convert UTF-8 to wide char";
                return;
            }

            StringCchCatW(szBuffer.data(), szBuffer.size(), L"\n");
            OutputDebugStringW(szBuffer.data());

    #if DEBUG
            HANDLE handle = 0;
            switch (level)
            {
            case Level::ERR:
            case Level::WARN:
                handle = GetStdHandle(STD_ERROR_HANDLE);
                break;
            case Level::INFO:
            case Level::ALL:
                handle = GetStdHandle(STD_OUTPUT_HANDLE);
                break;
            default: break;
            }

            if (handle)
            {
                DWORD bytesWritten;
                WriteConsoleW(handle, szBuffer.data(), static_cast<DWORD>(wcslen(szBuffer.data())), &bytesWritten, nullptr);
            }
    #endif

#elif OUZEL_PLATFORM_ANDROID
            int priority = 0;
            switch (level)
            {
                case Level::ERR: priority = ANDROID_LOG_ERROR; break;
                case Level::WARN: priority = ANDROID_LOG_WARN; break;
                case Level::INFO: priority = ANDROID_LOG_INFO; break;
                case Level::ALL: priority = ANDROID_LOG_DEBUG; break;
                default: break;
            }
            __android_log_print(priority, "Ouzel", "%s", s.c_str());
#elif OUZEL_PLATFORM_EMSCRIPTEN
            int flags = EM_LOG_CONSOLE;
            if (level == Level::ERR) flags |= EM_LOG_ERROR;
            else if (level == Level::WARN) flags |= EM_LOG_WARN;
            emscripten_log(flags, "%s", s.c_str());
#endif
            s.clear();
        }
    }
}
<|endoftext|>


<commit_before>#ifndef _SNARKFRONT_AES_INV_SBOX_HPP_
#define _SNARKFRONT_AES_INV_SBOX_HPP_

#include <array>
#include <cstdint>
#include "DSL_utility.hpp"

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// FIPS PUB 197, NIST November 2001
//
// Algorithm     Key Length    Block Size   Number of Rounds
//               (Nk words)    (Nb words)   (Nr)
//
// AES-128       4             4            10
// AES-192       6             4            12
// AES-256       8             4            14
//

////////////////////////////////////////////////////////////////////////////////
// Inverse S-Box
//

template <typename T, typename U, typename BITWISE>
class AES_InvSBox
{
public:
    AES_InvSBox()
        : m_lut(std::array<std::uint8_t, 256>{
            // 00
            0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
            0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,

            // 10
            0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
            0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,

            // 20
            0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
            0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,

            // 30
            0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
            0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,

            // 40
            0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
            0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,

            // 50
            0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
            0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,

            // 60
            0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
            0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,

            // 70
            0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
            0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,

            // 80
            0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
            0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,

            // 90
            0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
            0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,

            // a0
            0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
            0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,

            // b0
            0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
            0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,

            // c0
            0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
            0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,

            // d0
            0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
            0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,

            // e0
            0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
            0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,

            // f0
            0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
            0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d })
    {}

    U operator() (const T& x) const {
        return m_lut[x];
    }

private:
    const BitwiseLUT<T, U, std::uint8_t, BITWISE> m_lut;
};

} // namespace snarkfront

#endif
<commit_msg>scope header file paths<commit_after>#ifndef _SNARKFRONT_AES_INV_SBOX_HPP_
#define _SNARKFRONT_AES_INV_SBOX_HPP_

#include <array>
#include <cstdint>

#include <snarkfront/DSL_utility.hpp>

namespace snarkfront {

////////////////////////////////////////////////////////////////////////////////
// FIPS PUB 197, NIST November 2001
//
// Algorithm     Key Length    Block Size   Number of Rounds
//               (Nk words)    (Nb words)   (Nr)
//
// AES-128       4             4            10
// AES-192       6             4            12
// AES-256       8             4            14
//

////////////////////////////////////////////////////////////////////////////////
// Inverse S-Box
//

template <typename T, typename U, typename BITWISE>
class AES_InvSBox
{
public:
    AES_InvSBox()
        : m_lut(std::array<std::uint8_t, 256>{
            // 00
            0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
            0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,

            // 10
            0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
            0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,

            // 20
            0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
            0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,

            // 30
            0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
            0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,

            // 40
            0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
            0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,

            // 50
            0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
            0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,

            // 60
            0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
            0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,

            // 70
            0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
            0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,

            // 80
            0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
            0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,

            // 90
            0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
            0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,

            // a0
            0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
            0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,

            // b0
            0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
            0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,

            // c0
            0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
            0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,

            // d0
            0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
            0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,

            // e0
            0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
            0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,

            // f0
            0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
            0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d })
    {}

    U operator() (const T& x) const {
        return m_lut[x];
    }

private:
    const BitwiseLUT<T, U, std::uint8_t, BITWISE> m_lut;
};

} // namespace snarkfront

#endif
<|endoftext|>


<commit_before>
<commit_msg>Delete 1.cpp<commit_after><|endoftext|>


<commit_before>#include "imageviewer.h"
#include "ui_imageviewer.h"

ImageViewer::ImageViewer(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ImageViewer)
{
    ui->setupUi(this);

    actionOpen = ui->actionOpen;
    actionZoomIn = ui->actionZoomIn;
    actionZoomOut = ui->actionZoomOut;
    actionRotateLeft = ui->actionRotateLeft;
    actionRotateRight = ui->actionRotateRight;
    actionCrop = ui->actionCrop;

    updateActions(false);

    imageLabel = new QLabel;
    imageLabel->setBackgroundRole(QPalette::Base);
    imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imageLabel->setScaledContents(true);
    imageLabel->installEventFilter(this);

    scrollArea = new QScrollArea;
    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(imageLabel);
    setCentralWidget(scrollArea);

    setWindowTitle(tr("Image Viewer"));
}

ImageViewer::~ImageViewer()
{
    delete ui;
}

void ImageViewer::updateActions(bool updateTo)
{
    actionZoomIn->setEnabled(updateTo);
    actionZoomOut->setEnabled(updateTo);
    actionRotateLeft->setEnabled(updateTo);
    actionRotateRight->setEnabled(updateTo);
    actionCrop->setEnabled(updateTo);
}

void ImageViewer::scaleImage(double factor)
{
    Q_ASSERT(imageLabel->pixmap());
    scaleFactor *= factor;
    imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());

    adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
    adjustScrollBar(scrollArea->verticalScrollBar(), factor);

    actionZoomIn->setEnabled(scaleFactor < 3.0);
    actionZoomOut->setEnabled(scaleFactor > 0.333);
}

void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
    int newValue = factor * scrollBar->value() + (factor - 1) * scrollBar->pageStep() / 2;
    scrollBar->setValue(newValue);
}

void ImageViewer::on_actionOpen_triggered()
{
    QString lastFileName = fileName.isEmpty() ? QDir::currentPath() : fileName;
    fileName = QFileDialog::getOpenFileName(this,
                                                 tr("Open File"),
                                                 lastFileName);
    if (!fileName.isEmpty()) {
         image = QImage(fileName);
         if (image.isNull()) {
             QMessageBox::information(this,
                                      tr("Image Viewer"),
                                      tr("Cannot load %1.").arg(fileName));

             return;
         }

         imageLabel->setPixmap(QPixmap::fromImage(image));
         scaleFactor = 1.0;
         croppingImage = false;

         updateActions(true);

         imageLabel->adjustSize();
    }
}

void ImageViewer::on_actionZoomIn_triggered()
{
    scaleImage(1.25);
}

void ImageViewer::on_actionZoomOut_triggered()
{
    scaleImage(0.80);
}

void ImageViewer::rotateImage(int angle)
{
    QPixmap pixmap(*imageLabel->pixmap());
    QMatrix rm;
    rm.rotate(angle);
    pixmap = pixmap.transformed(rm);
    imageLabel->setPixmap(pixmap);
}

void ImageViewer::on_actionRotateLeft_triggered()
{
    rotateImage(-90);
}

void ImageViewer::on_actionRotateRight_triggered()
{
    rotateImage(90);
}

void ImageViewer::on_actionCrop_triggered()
{
    changeCroppingImage(true);
}

void ImageViewer::changeCroppingImage(bool changeTo)
{
    croppingImage = changeTo;
    actionCrop->setDisabled(changeTo);
}

bool ImageViewer::eventFilter(QObject* watched, QEvent* event)
{
    if (watched != imageLabel || !croppingImage)
        return false;

    switch (event->type())
    {
        case QEvent::MouseButtonPress:
        {
            const QMouseEvent* const me = static_cast<const QMouseEvent*>(event);
            croppingStart = me->pos() / scaleFactor;
            break;
        }

        case QEvent::MouseButtonRelease:
        {
            const QMouseEvent* const me = static_cast<const QMouseEvent*>(event);
            croppingEnd = me->pos() / scaleFactor;

            QRect rect(croppingStart, croppingEnd);
            image = image.copy(rect);
            imageLabel->setPixmap(QPixmap::fromImage(image));
            imageLabel->adjustSize();
            scaleImage(1.0);

            changeCroppingImage(false);
            break;
        }

        default:
            break;
    }

    return false;
}
<commit_msg>Allow for cropping of rotated image<commit_after>#include "imageviewer.h"
#include "ui_imageviewer.h"

ImageViewer::ImageViewer(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ImageViewer)
{
    ui->setupUi(this);

    actionOpen = ui->actionOpen;
    actionZoomIn = ui->actionZoomIn;
    actionZoomOut = ui->actionZoomOut;
    actionRotateLeft = ui->actionRotateLeft;
    actionRotateRight = ui->actionRotateRight;
    actionCrop = ui->actionCrop;

    updateActions(false);

    imageLabel = new QLabel;
    imageLabel->setBackgroundRole(QPalette::Base);
    imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    imageLabel->setScaledContents(true);
    imageLabel->installEventFilter(this);

    scrollArea = new QScrollArea;
    scrollArea->setBackgroundRole(QPalette::Dark);
    scrollArea->setWidget(imageLabel);
    setCentralWidget(scrollArea);

    setWindowTitle(tr("Image Viewer"));
}

ImageViewer::~ImageViewer()
{
    delete ui;
}

void ImageViewer::updateActions(bool updateTo)
{
    actionZoomIn->setEnabled(updateTo);
    actionZoomOut->setEnabled(updateTo);
    actionRotateLeft->setEnabled(updateTo);
    actionRotateRight->setEnabled(updateTo);
    actionCrop->setEnabled(updateTo);
}

void ImageViewer::scaleImage(double factor)
{
    Q_ASSERT(imageLabel->pixmap());
    scaleFactor *= factor;
    imageLabel->resize(scaleFactor * imageLabel->pixmap()->size());

    adjustScrollBar(scrollArea->horizontalScrollBar(), factor);
    adjustScrollBar(scrollArea->verticalScrollBar(), factor);

    actionZoomIn->setEnabled(scaleFactor < 3.0);
    actionZoomOut->setEnabled(scaleFactor > 0.333);
}

void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
    int newValue = factor * scrollBar->value() + (factor - 1) * scrollBar->pageStep() / 2;
    scrollBar->setValue(newValue);
}

void ImageViewer::on_actionOpen_triggered()
{
    QString lastFileName = fileName.isEmpty() ? QDir::currentPath() : fileName;
    fileName = QFileDialog::getOpenFileName(this,
                                                 tr("Open File"),
                                                 lastFileName);
    if (!fileName.isEmpty()) {
         image = QImage(fileName);
         if (image.isNull()) {
             QMessageBox::information(this,
                                      tr("Image Viewer"),
                                      tr("Cannot load %1.").arg(fileName));

             return;
         }

         imageLabel->setPixmap(QPixmap::fromImage(image));
         scaleFactor = 1.0;
         croppingImage = false;

         updateActions(true);

         imageLabel->adjustSize();
    }
}

void ImageViewer::on_actionZoomIn_triggered()
{
    scaleImage(1.25);
}

void ImageViewer::on_actionZoomOut_triggered()
{
    scaleImage(0.80);
}

void ImageViewer::rotateImage(int angle)
{
    QPixmap pixmap(*imageLabel->pixmap());
    QMatrix rm;
    rm.rotate(angle);
    pixmap = pixmap.transformed(rm);
    image = pixmap.toImage();
    imageLabel->setPixmap(pixmap);
}

void ImageViewer::on_actionRotateLeft_triggered()
{
    rotateImage(-90);
}

void ImageViewer::on_actionRotateRight_triggered()
{
    rotateImage(90);
}

void ImageViewer::on_actionCrop_triggered()
{
    changeCroppingImage(true);
}

void ImageViewer::changeCroppingImage(bool changeTo)
{
    croppingImage = changeTo;
    actionCrop->setDisabled(changeTo);
}

bool ImageViewer::eventFilter(QObject* watched, QEvent* event)
{
    if (watched != imageLabel || !croppingImage)
        return false;

    switch (event->type())
    {
        case QEvent::MouseButtonPress:
        {
            const QMouseEvent* const me = static_cast<const QMouseEvent*>(event);
            croppingStart = me->pos() / scaleFactor;
            break;
        }

        case QEvent::MouseButtonRelease:
        {
            const QMouseEvent* const me = static_cast<const QMouseEvent*>(event);
            croppingEnd = me->pos() / scaleFactor;

            QRect rect(croppingStart, croppingEnd);
            image = image.copy(rect);
            imageLabel->setPixmap(QPixmap::fromImage(image));
            imageLabel->adjustSize();
            scaleImage(1.0);

            changeCroppingImage(false);
            break;
        }

        default:
            break;
    }

    return false;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Op.h"
#include "IECore/Parameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/Object.h"
#include "IECore/CompoundObject.h"
#include "IECore/bindings/RunTimeTypedBinding.h"
#include "IECore/bindings/Wrapper.h"

using namespace boost;
using namespace boost::python;

namespace IECore {

class OpWrap : public Op, public Wrapper<Op>
{
	public :

		OpWrap( PyObject *self, const std::string &description, ParameterPtr resultParameter ) : Op( description, resultParameter ), Wrapper<Op>( self, this ) {};

		OpWrap( PyObject *self, const std::string &description, CompoundParameterPtr compoundParameter, ParameterPtr resultParameter ) : Op( description, compoundParameter, resultParameter ), Wrapper<Op>( self, this ) {};

		virtual ObjectPtr doOperation( ConstCompoundObjectPtr operands )
		{
			override o = this->get_override( "doOperation" );
			if( o )
			{
				ObjectPtr r = o( const_pointer_cast<CompoundObject>( operands ) );
				if( !r )
				{
					throw Exception( "doOperation() python method didn't return an Object." );
				}
				return r;
			}
			else
			{
				throw Exception( "doOperation() python method not defined" );
			}
		};

};
IE_CORE_DECLAREPTR( OpWrap );

static ParameterPtr resultParameter( const Op &o )
{
	return const_pointer_cast<Parameter>( o.resultParameter() );
}

void bindOp()
{
	using boost::python::arg;

	RunTimeTypedClass<Op, OpWrapPtr>()
		.def( init< const std::string &, ParameterPtr >( ( arg( "name" ), arg( "description" ), arg( "resultParameter") ) ) )
		.def( init< const std::string &, CompoundParameterPtr, ParameterPtr >( ( arg( "name" ), arg( "description" ), arg( "compoundParameter" ), arg( "resultParameter") ) ) )
		.def( "resultParameter", &resultParameter )
		.def( "operate", &Op::operate )
		.def( "__call__", &Op::operate )
	;

}

} // namespace IECore
<commit_msg>Fixing argument description for OpBinding.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2007-2010, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/python.hpp"

#include "IECore/Op.h"
#include "IECore/Parameter.h"
#include "IECore/CompoundParameter.h"
#include "IECore/Object.h"
#include "IECore/CompoundObject.h"
#include "IECore/bindings/RunTimeTypedBinding.h"
#include "IECore/bindings/Wrapper.h"

using namespace boost;
using namespace boost::python;

namespace IECore {

class OpWrap : public Op, public Wrapper<Op>
{
	public :

		OpWrap( PyObject *self, const std::string &description, ParameterPtr resultParameter ) : Op( description, resultParameter ), Wrapper<Op>( self, this ) {};

		OpWrap( PyObject *self, const std::string &description, CompoundParameterPtr compoundParameter, ParameterPtr resultParameter ) : Op( description, compoundParameter, resultParameter ), Wrapper<Op>( self, this ) {};

		virtual ObjectPtr doOperation( ConstCompoundObjectPtr operands )
		{
			override o = this->get_override( "doOperation" );
			if( o )
			{
				ObjectPtr r = o( const_pointer_cast<CompoundObject>( operands ) );
				if( !r )
				{
					throw Exception( "doOperation() python method didn't return an Object." );
				}
				return r;
			}
			else
			{
				throw Exception( "doOperation() python method not defined" );
			}
		};

};
IE_CORE_DECLAREPTR( OpWrap );

static ParameterPtr resultParameter( const Op &o )
{
	return const_pointer_cast<Parameter>( o.resultParameter() );
}

void bindOp()
{
	using boost::python::arg;

	RunTimeTypedClass<Op, OpWrapPtr>()
		.def( init< const std::string &, ParameterPtr >( ( arg( "description" ), arg( "resultParameter") ) ) )
		.def( init< const std::string &, CompoundParameterPtr, ParameterPtr >( ( arg( "description" ), arg( "compoundParameter" ), arg( "resultParameter") ) ) )
		.def( "resultParameter", &resultParameter )
		.def( "operate", &Op::operate )
		.def( "__call__", &Op::operate )
	;

}

} // namespace IECore
<|endoftext|>