<commit_before>/******************************************************************************\
* File:          vcs.cpp
* Purpose:       Implementation of wxExVCS class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/vcs.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/frame.h>
#include <wx/extension/log.h>
#include <wx/extension/stcdlg.h>
#include <wx/extension/util.h>

wxExVCS* wxExVCS::m_Self = NULL;
#if wxUSE_GUI
wxExSTCEntryDialog* wxExVCS::m_STCEntryDialog = NULL;
#endif

wxExVCS::wxExVCS()
  : m_Command(VCS_NO_COMMAND)
  , m_FileName(wxExFileName())
{
  Initialize();
}

wxExVCS::wxExVCS(int command_id, const wxExFileName& filename)
  : m_Command(GetType(command_id))
  , m_FileName(filename)
{
  Initialize();
}

wxExVCS::wxExVCS(wxExCommand type, const wxExFileName& filename)
  : m_Command(type)
  , m_FileName(filename)
{
  Initialize();
}

bool wxExVCS::CheckGIT(const wxFileName& fn) const
{
  // The .git dir only exists in the root, so check all components.
  wxFileName root(fn.GetPath());

  while (root.DirExists() && root.GetDirCount() > 0)
  {
    wxFileName path(root);
    path.AppendDir(".git");

    if (path.DirExists())
    {
      return true;
    }

    root.RemoveLastDir();
  }

  return false;
}

bool wxExVCS::CheckSVN(const wxFileName& fn) const
{
  // these cannot be combined, as AppendDir is a void (2.9.1).
  wxFileName path(fn);
  path.AppendDir(".svn");
  return path.DirExists();
}

#if wxUSE_GUI
int wxExVCS::ConfigDialog(
  wxWindow* parent,
  const wxString& title) const
{
  std::vector<wxExConfigItem> v;

  std::map<long, const wxString> choices;
  choices.insert(std::make_pair(VCS_NONE, _("None")));
  choices.insert(std::make_pair(VCS_GIT, "GIT"));
  choices.insert(std::make_pair(VCS_SVN, "SVN"));
  choices.insert(std::make_pair(VCS_AUTO, "Auto"));
  v.push_back(wxExConfigItem("VCS", choices));

  v.push_back(wxExConfigItem("GIT", CONFIG_FILEPICKERCTRL));
  v.push_back(wxExConfigItem("SVN", CONFIG_FILEPICKERCTRL));
  v.push_back(wxExConfigItem(_("Comparator"), CONFIG_FILEPICKERCTRL));

  return wxExConfigDialog(parent, v, title).ShowModal();
}
#endif

bool wxExVCS::DirExists(const wxFileName& filename) const
{
  switch (GetVCS(filename))
  {
    case VCS_GIT:
      return CheckGIT(filename); break;

    case VCS_NONE: break; // prevent wxFAIL

    case VCS_SVN:
      return CheckSVN(filename); break;

    default: wxFAIL;
  }

  return false;
}

long wxExVCS::Execute()
{
  wxASSERT(m_Command != VCS_NO_COMMAND);

  wxString cwd;
  wxString file;

  if (!m_FileName.IsOk())
  {
    cwd = wxGetCwd();
    wxSetWorkingDirectory(wxExConfigFirstOf(_("Base folder")));

    if (m_Command == VCS_ADD)
    {
      file = " " + wxExConfigFirstOf(_("Path"));
    }
  }
  else
  {
    if (GetVCS() == VCS_GIT)
    {
      cwd = wxGetCwd();
      wxSetWorkingDirectory(m_FileName.GetPath());
      file = " \"" + m_FileName.GetFullName() + "\"";
    }
    else
    {
      file = " \"" + m_FileName.GetFullPath() + "\"";
    }
  }

  wxString comment;

  if (m_Command == VCS_COMMIT)
  {
    comment =
      " -m \"" + wxExConfigFirstOf(_("Revision comment")) + "\"";
  }

  wxString subcommand;

  if (UseSubcommand())
  {
    subcommand = wxConfigBase::Get()->Read(_("Subcommand"));

    if (!subcommand.empty())
    {
      subcommand = " " + subcommand;
    }
  }

  wxString flags;

  if (UseFlags())
  {
    flags = wxConfigBase::Get()->Read(_("Flags"));

    if (!flags.empty())
    {
      flags = " " + flags;

      // If we specified help flags, we do not need a file argument.
      if (flags.Contains("help"))
      {
        file.clear();
      }
    }
  }

  m_CommandWithFlags = m_CommandString + flags;

  wxString vcs_bin;

  switch (GetVCS())
  {
    case VCS_GIT: vcs_bin = wxConfigBase::Get()->Read("GIT", "git"); break;
    case VCS_SVN: vcs_bin = wxConfigBase::Get()->Read("SVN", "svn"); break;
    default: wxFAIL;
  }

  if (vcs_bin.empty())
  {
    wxLogError(GetVCSName() + " " + _("path is empty"));
    return -1;
  }

  const wxString commandline =
    vcs_bin + " " + m_CommandString + subcommand + flags + comment + file;

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(commandline);
#endif

  wxArrayString output;
  wxArrayString errors;
  long retValue;

  // Call wxExcute to execute the cvs command and
  // collect the output and the errors.
  if ((retValue = wxExecute(
    commandline,
    output,
    errors)) == -1)
  {
    // See also process, same log is shown.
    wxLogError(_("Cannot execute") + ": " + commandline);
  }
  else
  {
    wxExLog::Get()->Log(commandline);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  m_Output.clear();

  // First output the errors.
  for (
    size_t i = 0;
    i < errors.GetCount();
    i++)
  {
    m_Output += errors[i] + "\n";
  }

  // Then the normal output, will be empty if there are errors.
  for (
    size_t j = 0;
    j < output.GetCount();
    j++)
  {
    m_Output += output[j] + "\n";
  }

  return retValue;
}

#if wxUSE_GUI
wxStandardID wxExVCS::ExecuteDialog(wxWindow* parent)
{
  if (ShowDialog(parent) == wxID_CANCEL)
  {
    return wxID_CANCEL;
  }

  if (UseFlags())
  {
    wxConfigBase::Get()->Write(m_FlagsKey,
      wxConfigBase::Get()->Read(_("Flags")));
  }

  const auto retValue = Execute();

  return (retValue != -1 ? wxID_OK: wxID_CANCEL);
}
#endif

wxExVCS* wxExVCS::Get(bool createOnDemand)
{
  if (m_Self == NULL && createOnDemand)
  {
    m_Self = new wxExVCS;

    // Add default VCS.
    if (!wxConfigBase::Get()->Exists("VCS"))
    {
      // TODO: Add SVN only if svn bin exists on linux.
      wxConfigBase::Get()->Write("VCS", (long)VCS_SVN);
    }
  }

  return m_Self;
}

wxExVCS::wxExCommand wxExVCS::GetType(int command_id) const
{
  if (command_id > ID_VCS_LOWEST && command_id < ID_VCS_HIGHEST)
  {
    return (wxExCommand)(command_id - ID_VCS_LOWEST);
  }
  else if (command_id > ID_EDIT_VCS_LOWEST && command_id < ID_EDIT_VCS_HIGHEST)
  {
    return (wxExCommand)(command_id - ID_EDIT_VCS_LOWEST);
  }
  else
  {
    wxFAIL;
    return VCS_NO_COMMAND;
  }
}

long wxExVCS::GetVCS(const wxFileName& filename) const
{
  const wxExFileName fn = (!filename.IsOk() ? m_FileName: filename);

  long vcs = wxConfigBase::Get()->ReadLong("VCS", VCS_SVN);

  if (vcs == VCS_AUTO)
  {
    if (CheckSVN(fn))
    {
      vcs = VCS_SVN;
    }
    else if (CheckGIT(fn))
    {
      vcs = VCS_GIT;
    }
    else
    {
      vcs = VCS_NONE;
    }
  }

  return vcs;
}

const wxString wxExVCS::GetVCSName() const
{
  wxString text;

  switch (GetVCS())
  {
    case VCS_GIT: text = "GIT"; break;
    case VCS_SVN: text = "SVN"; break;
    default: wxFAIL;
  }

  return text;
}

void wxExVCS::Initialize()
{
  if (Use() && m_Command != VCS_NO_COMMAND)
  {
    switch (GetVCS())
    {
      case VCS_GIT:
        switch (m_Command)
        {
          case VCS_ADD:      m_CommandString = "add"; break;
          case VCS_BLAME:    m_CommandString = "blame"; break;
          case VCS_CAT:      break;
          case VCS_COMMIT:   m_CommandString = "commit"; break;
          case VCS_DIFF:     m_CommandString = "diff"; break;
          case VCS_HELP:     m_CommandString = "help"; break;
          case VCS_INFO:     break;
          case VCS_LOG:      m_CommandString = "log"; break;
          case VCS_LS:       break;
          case VCS_PROPLIST: break;
          case VCS_PROPSET:  break;
          case VCS_PUSH:     m_CommandString = "push"; break;
          case VCS_REVERT:   m_CommandString = "revert"; break;
          case VCS_SHOW:     m_CommandString = "show"; break;
          case VCS_STAT:     m_CommandString = "status"; break;
          case VCS_UPDATE:   m_CommandString = "update"; break;
          default:
            wxFAIL;
            break;
        }
        break;

      case VCS_SVN:
        switch (m_Command)
        {
          case VCS_ADD:      m_CommandString = "add"; break;
          case VCS_BLAME:    m_CommandString = "blame"; break;
          case VCS_CAT:      m_CommandString = "cat"; break;
          case VCS_COMMIT:   m_CommandString = "commit"; break;
          case VCS_DIFF:     m_CommandString = "diff"; break;
          case VCS_HELP:     m_CommandString = "help"; break;
          case VCS_INFO:     m_CommandString = "info"; break;
          case VCS_LOG:      m_CommandString = "log"; break;
          case VCS_LS:       m_CommandString = "ls"; break;
          case VCS_PROPLIST: m_CommandString = "proplist"; break;
          case VCS_PROPSET:  m_CommandString = "propset"; break;
          case VCS_PUSH:     break;
          case VCS_REVERT:   m_CommandString = "revert"; break;
          case VCS_SHOW:     break;
          case VCS_STAT:     m_CommandString = "stat"; break;
          case VCS_UPDATE:   m_CommandString = "update"; break;
          default:
            wxFAIL;
            break;
        }
        break;

      default: wxFAIL;
    }

    m_Caption = GetVCSName() + " " + m_CommandString;

    // Currently no flags, as no command was executed.
    m_CommandWithFlags = m_CommandString;

    // Use general key.
    m_FlagsKey = wxString::Format("cvsflags/name%d", m_Command);
  }

  m_Output.clear();
}

bool wxExVCS::IsOpenCommand() const
{
  return
    m_Command == wxExVCS::VCS_BLAME ||
    m_Command == wxExVCS::VCS_CAT ||
    m_Command == wxExVCS::VCS_DIFF;
}

#if wxUSE_GUI
wxStandardID wxExVCS::Request(wxWindow* parent)
{
  wxStandardID retValue;

  if ((retValue = ExecuteDialog(parent)) == wxID_OK)
  {
    ShowOutput(parent);
  }

  return retValue;
}
#endif

wxExVCS* wxExVCS::Set(wxExVCS* vcs)
{
  wxExVCS* old = m_Self;
  m_Self = vcs;
  return old;
}

#if wxUSE_GUI
int wxExVCS::ShowDialog(wxWindow* parent)
{
  std::vector<wxExConfigItem> v;

  if (m_Command == VCS_COMMIT)
  {
    v.push_back(wxExConfigItem(
      _("Revision comment"),
      CONFIG_COMBOBOX,
      wxEmptyString,
      true)); // required
  }

  if (!m_FileName.IsOk() && m_Command != VCS_HELP)
  {
    v.push_back(wxExConfigItem(
      _("Base folder"),
      CONFIG_COMBOBOXDIR,
      wxEmptyString,
      true,
      1000));

    if (m_Command == VCS_ADD)
    {
      v.push_back(wxExConfigItem(
        _("Path"),
        CONFIG_COMBOBOX,
        wxEmptyString,
        true)); // required
    }
  }

  if (UseFlags())
  {
    wxConfigBase::Get()->Write(
      _("Flags"),
      wxConfigBase::Get()->Read(m_FlagsKey));

    v.push_back(wxExConfigItem(_("Flags")));
  }

  if (UseSubcommand())
  {
    v.push_back(wxExConfigItem(_("Subcommand")));
  }

  return wxExConfigDialog(parent,
    v,
    m_Caption).ShowModal();
}
#endif

#if wxUSE_GUI
void wxExVCS::ShowOutput(wxWindow* parent) const
{
  wxString caption = m_Caption;

  if (m_Command != VCS_HELP)
  {
    caption += " " + (m_FileName.IsOk() ?
      m_FileName.GetFullName():
      wxExConfigFirstOf(_("Base folder")));
  }

  // Create a dialog for contents.
  if (m_STCEntryDialog == NULL)
  {
    m_STCEntryDialog = new wxExSTCEntryDialog(
      parent,
      caption,
      m_Output,
      wxEmptyString,
      wxOK,
      wxID_ANY,
      wxDefaultPosition,
      wxSize(350, 50));
  }
  else
  {
    m_STCEntryDialog->SetText(m_Output);
    m_STCEntryDialog->SetTitle(caption);
  }

  // Add a lexer when appropriate.
  if (m_Command == VCS_CAT || m_Command == VCS_BLAME)
  {
    if (m_FileName.GetLexer().IsOk())
    {
      m_STCEntryDialog->SetLexer(m_FileName.GetLexer().GetScintillaLexer());
    }
  }
  else if (m_Command == VCS_DIFF)
  {
    m_STCEntryDialog->SetLexer("diff");
  }
  else
  {
    m_STCEntryDialog->SetLexer(wxEmptyString);
  }

  m_STCEntryDialog->Show();
}
#endif

bool wxExVCS::SupportKeywordExpansion() const
{
  return GetVCS() == VCS_SVN;
}
bool wxExVCS::Use() const
{
  return GetVCS() != VCS_NONE;
}

bool wxExVCS::UseFlags() const
{
  return m_Command != VCS_UPDATE && m_Command != VCS_HELP;
}

bool wxExVCS::UseSubcommand() const
{
  return m_Command == VCS_HELP;
}
<commit_msg>used wxFileName whenever possible<commit_after>/******************************************************************************\
* File:          vcs.cpp
* Purpose:       Implementation of wxExVCS class
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/extension/vcs.h>
#include <wx/extension/configdlg.h>
#include <wx/extension/defs.h>
#include <wx/extension/frame.h>
#include <wx/extension/log.h>
#include <wx/extension/stcdlg.h>
#include <wx/extension/util.h>

wxExVCS* wxExVCS::m_Self = NULL;
#if wxUSE_GUI
wxExSTCEntryDialog* wxExVCS::m_STCEntryDialog = NULL;
#endif

wxExVCS::wxExVCS()
  : m_Command(VCS_NO_COMMAND)
  , m_FileName(wxExFileName())
{
  Initialize();
}

wxExVCS::wxExVCS(int command_id, const wxExFileName& filename)
  : m_Command(GetType(command_id))
  , m_FileName(filename)
{
  Initialize();
}

wxExVCS::wxExVCS(wxExCommand type, const wxExFileName& filename)
  : m_Command(type)
  , m_FileName(filename)
{
  Initialize();
}

bool wxExVCS::CheckGIT(const wxFileName& fn) const
{
  // The .git dir only exists in the root, so check all components.
  wxFileName root(fn.GetPath());

  while (root.DirExists() && root.GetDirCount() > 0)
  {
    wxFileName path(root);
    path.AppendDir(".git");

    if (path.DirExists())
    {
      return true;
    }

    root.RemoveLastDir();
  }

  return false;
}

bool wxExVCS::CheckSVN(const wxFileName& fn) const
{
  // these cannot be combined, as AppendDir is a void (2.9.1).
  wxFileName path(fn);
  path.AppendDir(".svn");
  return path.DirExists();
}

#if wxUSE_GUI
int wxExVCS::ConfigDialog(
  wxWindow* parent,
  const wxString& title) const
{
  std::vector<wxExConfigItem> v;

  std::map<long, const wxString> choices;
  choices.insert(std::make_pair(VCS_NONE, _("None")));
  choices.insert(std::make_pair(VCS_GIT, "GIT"));
  choices.insert(std::make_pair(VCS_SVN, "SVN"));
  choices.insert(std::make_pair(VCS_AUTO, "Auto"));
  v.push_back(wxExConfigItem("VCS", choices));

  v.push_back(wxExConfigItem("GIT", CONFIG_FILEPICKERCTRL));
  v.push_back(wxExConfigItem("SVN", CONFIG_FILEPICKERCTRL));
  v.push_back(wxExConfigItem(_("Comparator"), CONFIG_FILEPICKERCTRL));

  return wxExConfigDialog(parent, v, title).ShowModal();
}
#endif

bool wxExVCS::DirExists(const wxFileName& filename) const
{
  switch (GetVCS(filename))
  {
    case VCS_GIT:
      return CheckGIT(filename); break;

    case VCS_NONE: break; // prevent wxFAIL

    case VCS_SVN:
      return CheckSVN(filename); break;

    default: wxFAIL;
  }

  return false;
}

long wxExVCS::Execute()
{
  wxASSERT(m_Command != VCS_NO_COMMAND);

  wxString cwd;
  wxString file;

  if (!m_FileName.IsOk())
  {
    cwd = wxGetCwd();
    wxSetWorkingDirectory(wxExConfigFirstOf(_("Base folder")));

    if (m_Command == VCS_ADD)
    {
      file = " " + wxExConfigFirstOf(_("Path"));
    }
  }
  else
  {
    if (GetVCS() == VCS_GIT)
    {
      cwd = wxGetCwd();
      wxSetWorkingDirectory(m_FileName.GetPath());
      file = " \"" + m_FileName.GetFullName() + "\"";
    }
    else
    {
      file = " \"" + m_FileName.GetFullPath() + "\"";
    }
  }

  wxString comment;

  if (m_Command == VCS_COMMIT)
  {
    comment =
      " -m \"" + wxExConfigFirstOf(_("Revision comment")) + "\"";
  }

  wxString subcommand;

  if (UseSubcommand())
  {
    subcommand = wxConfigBase::Get()->Read(_("Subcommand"));

    if (!subcommand.empty())
    {
      subcommand = " " + subcommand;
    }
  }

  wxString flags;

  if (UseFlags())
  {
    flags = wxConfigBase::Get()->Read(_("Flags"));

    if (!flags.empty())
    {
      flags = " " + flags;

      // If we specified help flags, we do not need a file argument.
      if (flags.Contains("help"))
      {
        file.clear();
      }
    }
  }

  m_CommandWithFlags = m_CommandString + flags;

  wxString vcs_bin;

  switch (GetVCS())
  {
    case VCS_GIT: vcs_bin = wxConfigBase::Get()->Read("GIT", "git"); break;
    case VCS_SVN: vcs_bin = wxConfigBase::Get()->Read("SVN", "svn"); break;
    default: wxFAIL;
  }

  if (vcs_bin.empty())
  {
    wxLogError(GetVCSName() + " " + _("path is empty"));
    return -1;
  }

  const wxString commandline =
    vcs_bin + " " + m_CommandString + subcommand + flags + comment + file;

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(commandline);
#endif

  wxArrayString output;
  wxArrayString errors;
  long retValue;

  // Call wxExcute to execute the cvs command and
  // collect the output and the errors.
  if ((retValue = wxExecute(
    commandline,
    output,
    errors)) == -1)
  {
    // See also process, same log is shown.
    wxLogError(_("Cannot execute") + ": " + commandline);
  }
  else
  {
    wxExLog::Get()->Log(commandline);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  m_Output.clear();

  // First output the errors.
  for (
    size_t i = 0;
    i < errors.GetCount();
    i++)
  {
    m_Output += errors[i] + "\n";
  }

  // Then the normal output, will be empty if there are errors.
  for (
    size_t j = 0;
    j < output.GetCount();
    j++)
  {
    m_Output += output[j] + "\n";
  }

  return retValue;
}

#if wxUSE_GUI
wxStandardID wxExVCS::ExecuteDialog(wxWindow* parent)
{
  if (ShowDialog(parent) == wxID_CANCEL)
  {
    return wxID_CANCEL;
  }

  if (UseFlags())
  {
    wxConfigBase::Get()->Write(m_FlagsKey,
      wxConfigBase::Get()->Read(_("Flags")));
  }

  const auto retValue = Execute();

  return (retValue != -1 ? wxID_OK: wxID_CANCEL);
}
#endif

wxExVCS* wxExVCS::Get(bool createOnDemand)
{
  if (m_Self == NULL && createOnDemand)
  {
    m_Self = new wxExVCS;

    // Add default VCS.
    if (!wxConfigBase::Get()->Exists("VCS"))
    {
      // TODO: Add SVN only if svn bin exists on linux.
      wxConfigBase::Get()->Write("VCS", (long)VCS_SVN);
    }
  }

  return m_Self;
}

wxExVCS::wxExCommand wxExVCS::GetType(int command_id) const
{
  if (command_id > ID_VCS_LOWEST && command_id < ID_VCS_HIGHEST)
  {
    return (wxExCommand)(command_id - ID_VCS_LOWEST);
  }
  else if (command_id > ID_EDIT_VCS_LOWEST && command_id < ID_EDIT_VCS_HIGHEST)
  {
    return (wxExCommand)(command_id - ID_EDIT_VCS_LOWEST);
  }
  else
  {
    wxFAIL;
    return VCS_NO_COMMAND;
  }
}

long wxExVCS::GetVCS(const wxFileName& filename) const
{
  const wxFileName fn(!filename.IsOk() ? m_FileName: filename);

  long vcs = wxConfigBase::Get()->ReadLong("VCS", VCS_SVN);

  if (vcs == VCS_AUTO)
  {
    if (CheckSVN(fn))
    {
      vcs = VCS_SVN;
    }
    else if (CheckGIT(fn))
    {
      vcs = VCS_GIT;
    }
    else
    {
      vcs = VCS_NONE;
    }
  }

  return vcs;
}

const wxString wxExVCS::GetVCSName() const
{
  wxString text;

  switch (GetVCS())
  {
    case VCS_GIT: text = "GIT"; break;
    case VCS_SVN: text = "SVN"; break;
    default: wxFAIL;
  }

  return text;
}

void wxExVCS::Initialize()
{
  if (Use() && m_Command != VCS_NO_COMMAND)
  {
    switch (GetVCS())
    {
      case VCS_GIT:
        switch (m_Command)
        {
          case VCS_ADD:      m_CommandString = "add"; break;
          case VCS_BLAME:    m_CommandString = "blame"; break;
          case VCS_CAT:      break;
          case VCS_COMMIT:   m_CommandString = "commit"; break;
          case VCS_DIFF:     m_CommandString = "diff"; break;
          case VCS_HELP:     m_CommandString = "help"; break;
          case VCS_INFO:     break;
          case VCS_LOG:      m_CommandString = "log"; break;
          case VCS_LS:       break;
          case VCS_PROPLIST: break;
          case VCS_PROPSET:  break;
          case VCS_PUSH:     m_CommandString = "push"; break;
          case VCS_REVERT:   m_CommandString = "revert"; break;
          case VCS_SHOW:     m_CommandString = "show"; break;
          case VCS_STAT:     m_CommandString = "status"; break;
          case VCS_UPDATE:   m_CommandString = "update"; break;
          default:
            wxFAIL;
            break;
        }
        break;

      case VCS_SVN:
        switch (m_Command)
        {
          case VCS_ADD:      m_CommandString = "add"; break;
          case VCS_BLAME:    m_CommandString = "blame"; break;
          case VCS_CAT:      m_CommandString = "cat"; break;
          case VCS_COMMIT:   m_CommandString = "commit"; break;
          case VCS_DIFF:     m_CommandString = "diff"; break;
          case VCS_HELP:     m_CommandString = "help"; break;
          case VCS_INFO:     m_CommandString = "info"; break;
          case VCS_LOG:      m_CommandString = "log"; break;
          case VCS_LS:       m_CommandString = "ls"; break;
          case VCS_PROPLIST: m_CommandString = "proplist"; break;
          case VCS_PROPSET:  m_CommandString = "propset"; break;
          case VCS_PUSH:     break;
          case VCS_REVERT:   m_CommandString = "revert"; break;
          case VCS_SHOW:     break;
          case VCS_STAT:     m_CommandString = "stat"; break;
          case VCS_UPDATE:   m_CommandString = "update"; break;
          default:
            wxFAIL;
            break;
        }
        break;

      default: wxFAIL;
    }

    m_Caption = GetVCSName() + " " + m_CommandString;

    // Currently no flags, as no command was executed.
    m_CommandWithFlags = m_CommandString;

    // Use general key.
    m_FlagsKey = wxString::Format("cvsflags/name%d", m_Command);
  }

  m_Output.clear();
}

bool wxExVCS::IsOpenCommand() const
{
  return
    m_Command == wxExVCS::VCS_BLAME ||
    m_Command == wxExVCS::VCS_CAT ||
    m_Command == wxExVCS::VCS_DIFF;
}

#if wxUSE_GUI
wxStandardID wxExVCS::Request(wxWindow* parent)
{
  wxStandardID retValue;

  if ((retValue = ExecuteDialog(parent)) == wxID_OK)
  {
    ShowOutput(parent);
  }

  return retValue;
}
#endif

wxExVCS* wxExVCS::Set(wxExVCS* vcs)
{
  wxExVCS* old = m_Self;
  m_Self = vcs;
  return old;
}

#if wxUSE_GUI
int wxExVCS::ShowDialog(wxWindow* parent)
{
  std::vector<wxExConfigItem> v;

  if (m_Command == VCS_COMMIT)
  {
    v.push_back(wxExConfigItem(
      _("Revision comment"),
      CONFIG_COMBOBOX,
      wxEmptyString,
      true)); // required
  }

  if (!m_FileName.IsOk() && m_Command != VCS_HELP)
  {
    v.push_back(wxExConfigItem(
      _("Base folder"),
      CONFIG_COMBOBOXDIR,
      wxEmptyString,
      true,
      1000));

    if (m_Command == VCS_ADD)
    {
      v.push_back(wxExConfigItem(
        _("Path"),
        CONFIG_COMBOBOX,
        wxEmptyString,
        true)); // required
    }
  }

  if (UseFlags())
  {
    wxConfigBase::Get()->Write(
      _("Flags"),
      wxConfigBase::Get()->Read(m_FlagsKey));

    v.push_back(wxExConfigItem(_("Flags")));
  }

  if (UseSubcommand())
  {
    v.push_back(wxExConfigItem(_("Subcommand")));
  }

  return wxExConfigDialog(parent,
    v,
    m_Caption).ShowModal();
}
#endif

#if wxUSE_GUI
void wxExVCS::ShowOutput(wxWindow* parent) const
{
  wxString caption = m_Caption;

  if (m_Command != VCS_HELP)
  {
    caption += " " + (m_FileName.IsOk() ?
      m_FileName.GetFullName():
      wxExConfigFirstOf(_("Base folder")));
  }

  // Create a dialog for contents.
  if (m_STCEntryDialog == NULL)
  {
    m_STCEntryDialog = new wxExSTCEntryDialog(
      parent,
      caption,
      m_Output,
      wxEmptyString,
      wxOK,
      wxID_ANY,
      wxDefaultPosition,
      wxSize(350, 50));
  }
  else
  {
    m_STCEntryDialog->SetText(m_Output);
    m_STCEntryDialog->SetTitle(caption);
  }

  // Add a lexer when appropriate.
  if (m_Command == VCS_CAT || m_Command == VCS_BLAME)
  {
    if (m_FileName.GetLexer().IsOk())
    {
      m_STCEntryDialog->SetLexer(m_FileName.GetLexer().GetScintillaLexer());
    }
  }
  else if (m_Command == VCS_DIFF)
  {
    m_STCEntryDialog->SetLexer("diff");
  }
  else
  {
    m_STCEntryDialog->SetLexer(wxEmptyString);
  }

  m_STCEntryDialog->Show();
}
#endif

bool wxExVCS::SupportKeywordExpansion() const
{
  return GetVCS() == VCS_SVN;
}
bool wxExVCS::Use() const
{
  return GetVCS() != VCS_NONE;
}

bool wxExVCS::UseFlags() const
{
  return m_Command != VCS_UPDATE && m_Command != VCS_HELP;
}

bool wxExVCS::UseSubcommand() const
{
  return m_Command == VCS_HELP;
}
<|endoftext|>


<commit_before>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//
//           ----------------------------------------------------
//           Snake Miniapp:  Model of the Rubik's Snake_TM Puzzle
//           ----------------------------------------------------
//

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

static int joint_ = 0;
static int notch_ = 0;
static int step_  = 0;
static int nstep_ = 6;

static double cosa_ = cos(0.5 * M_PI / nstep_);
static double sina_ = sin(0.5 * M_PI / nstep_);

static int conf[7][23] =
{
   /* Ball       */ {
      3,1,3,3,1,3,1,1,
      3,1,3,3,1,3,1,1,
      3,1,3,3,1,3,1
   },
   /* Triangle   */ {
      1,0,0,0,0,0,0,3,
      1,0,0,0,0,0,0,3,
      1,0,0,0,0,0,0
   },
   /* Hexagon    */ {
      0,0,1,0,0,0,0,3,
      0,0,1,0,0,0,0,3,
      0,0,1,0,0,0,0
   },
   /* Snow Flake */ {
      1,1,1,1,3,3,3,3,
      1,1,1,1,3,3,3,3,
      1,1,1,1,3,3,3
   },
   /* Spiral     */ {
      2,1,2,1,2,1,2,1,
      2,1,2,1,2,1,2,1,
      2,1,2,1,2,1,2
   },
   /* Zig-zag    */ {
      3,3,3,1,1,1,3,3,
      3,1,1,1,3,3,3,1,
      1,1,3,3,3,1,1
   },
   /* Cobra      */ {
      2,0,0,2,1,3,0,2,
      0,2,3,0,1,3,2,1,
      1,2,3,1,0,3,0
   }
};

void trans(const int * conf, Mesh & mesh);

bool anim_step(const int * conf, Mesh & mesh);

int main(int argc, char *argv[])
{
   int cfg = -1;
   bool anim = true;
   bool visualization = true;

   OptionsParser args(argc, argv);
   args.AddOption(&cfg, "-c", "--configuration","");
   args.AddOption(&anim, "-anim", "--animation", "-no-anim",
                  "--no-animation",
                  "Enable or disable GLVis animation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // Define an empty mesh
   Mesh mesh(3, 6 * 24, 24);

   // Add vertices for 24 elements
   double c[9];
   int v[6];
   for (int i=0; i<12; i++)
   {
      // Add vertices for a pair of elements
      // First Upward-facing wedge
      c[0] = i-6; c[1] = 0.0; c[2] = i-6;
      c[3] = i-6; c[4] = 0.0; c[5] = i-5;
      c[6] = i-5; c[7] = 0.0; c[8] = i-5;

      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      c[1] = 1.0; c[4] = 1.0; c[7] = 1.0;
      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      for (int j=0; j<6; j++) { v[j] = 12 * i + j; }
      mesh.AddWedge(v);

      // Next Downward-facing wedge
      c[0] = i-6; c[1] = 0.0; c[2] = i-5;
      c[3] = i-5; c[4] = 0.0; c[5] = i-4;
      c[6] = i-5; c[7] = 0.0; c[8] = i-5;

      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      c[1] = 1.0; c[4] = 1.0; c[7] = 1.0;
      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      for (int j=0; j<6; j++) { v[j] = 12 * i + j + 6; }
      mesh.AddWedge(v);
   }

   mesh.FinalizeTopology();

   FiniteElementCollection *fec = new L2_FECollection(0, 3, 1);
   FiniteElementSpace fespace(&mesh, fec);
   GridFunction color(&fespace);

   for (int i=0; i<24; i++) { color[i] = (i%2)?1.0:-1.0; }

   // Output the initial mesh to a file
   {
      ostringstream oss;
      oss << "snake-init.mesh";
      ofstream ofs(oss.str().c_str());
      ofs.precision(8);
      mesh.Print(ofs);
      ofs.close();
   }

   if ( cfg >= 0 && !anim) { trans(conf[cfg], mesh); }

   // Output the resulting mesh to GLVis
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock.precision(8);
      sol_sock << "solution\n" << mesh << color << "keys Am\n"
               << "palette 22\n" << "valuerange -1.5 1\n"
               << "autoscale off\n" << flush;

      if (anim)
      {
         sol_sock << "pause\n" << flush;
         cout << "GLVis visualization paused."
              << " Press space (in the GLVis window) to resume it.\n";

         while (anim_step(conf[cfg], mesh))
         {
            static int turn = 0;
            sol_sock << "solution\n" << mesh << color;
            if (turn++ % 2 == 0)
            {
               sol_sock << "pause\n";
            }
            sol_sock << flush;
         }
      }
   }

   // Output the resulting mesh to a file
   {
      ostringstream oss;
      oss << "snake-c" << cfg << ".mesh";
      ofstream ofs(oss.str().c_str());
      ofs.precision(8);
      mesh.Print(ofs);
      ofs.close();
   }

   // Clean up and exit
   return 0;
}

void
rotate(double * x)
{
   if (notch_ == 0) { return; }

   double cent[3];
   Vector cVec(cent,3);
   Vector xVec(x,3);

   if (joint_%2 == 0)
   {
      cVec[0] = -5.5 + joint_ / 2; cVec[1] = 0.5; cVec[2] = 0.0;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            swap(xVec[0], xVec[1]);
            xVec[0] *= -1.0;
            break;
         case 2:
            xVec[0] *= -1.0;
            xVec[1] *= -1.0;
            break;
         case 3:
            swap(xVec[0], xVec[1]);
            xVec[1] *= -1.0;
            break;
      }
      xVec.Add(1.0, cVec);
   }
   else
   {
      cVec[0] = 0.0; cVec[1] = 0.5; cVec[2] = -4.5 + joint_ / 2;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            swap(xVec[1], xVec[2]);
            xVec[1] *= -1.0;
            break;
         case 2:
            xVec[1] *= -1.0;
            xVec[2] *= -1.0;
            break;
         case 3:
            swap(xVec[1], xVec[2]);
            xVec[2] *= -1.0;
            break;
      }
      xVec.Add(1.0, cVec);
   }
}

void
trans(const int * conf, Mesh & mesh)
{
   for (int i=0; i<23; i++)
   {
      joint_ = i;
      notch_ = conf[i];

      if (notch_ != 0)
      {
         for (int k=0; k<6*(i+1); k++)
         {
            rotate(mesh.GetVertex(k));
         }
      }
   }
}

void
rotate_step(double * x)
{
   if (notch_ == 0) { return; }

   double cent[3], y[3];
   Vector cVec(cent,3);
   Vector xVec(x,3);
   Vector yVec(y,3);

   if (joint_%2 == 0)
   {
      cVec[0] = -5.5 + joint_ / 2; cVec[1] = 0.5; cVec[2] = 0.0;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            yVec[0] = cosa_ * xVec[0] - sina_ * xVec[1];
            yVec[1] = sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
         case 2:
            yVec[0] = cosa_ * xVec[0] - sina_ * xVec[1];
            yVec[1] = sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
         case 3:
            yVec[0] =  cosa_ * xVec[0] + sina_ * xVec[1];
            yVec[1] = -sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
      }
      add(yVec, 1.0, cVec, xVec);
   }
   else
   {
      cVec[0] = 0.0; cVec[1] = 0.5; cVec[2] = -4.5 + joint_ / 2;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            yVec[0] = xVec[0];
            yVec[1] = cosa_ * xVec[1] - sina_ * xVec[2];
            yVec[2] = sina_ * xVec[1] + cosa_ * xVec[2];
            break;
         case 2:
            yVec[0] = xVec[0];
            yVec[1] = cosa_ * xVec[1] - sina_ * xVec[2];
            yVec[2] = sina_ * xVec[1] + cosa_ * xVec[2];
            break;
         case 3:
            yVec[0] = xVec[0];
            yVec[1] =  cosa_ * xVec[1] + sina_ * xVec[2];
            yVec[2] = -sina_ * xVec[1] + cosa_ * xVec[2];
            break;
      }
      add(yVec, 1.0, cVec, xVec);
   }
}

bool
anim_step(const int * conf, Mesh & mesh)
{
   if (notch_ == 2 && step_ == 2 * nstep_) { joint_++; step_ = 0; }
   if (notch_ != 2 && step_ == nstep_) { joint_++; step_ = 0; }
   if (joint_ == 23) { return false; }
   notch_ = conf[joint_];

   if (notch_ == 0)
   {
      step_ = nstep_;
      return true;
   }
   else
   {
      for (int k=0; k<6*(joint_+1); k++)
      {
         rotate_step(mesh.GetVertex(k));
      }
   }
   step_++;
   return true;
}
<commit_msg>Add recentering/rescaling step after animation<commit_after>// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
//
//           ----------------------------------------------------
//           Snake Miniapp:  Model of the Rubik's Snake_TM Puzzle
//           ----------------------------------------------------
//

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

static int joint_ = 0;
static int notch_ = 0;
static int step_  = 0;
static int nstep_ = 6;

static double cosa_ = cos(0.5 * M_PI / nstep_);
static double sina_ = sin(0.5 * M_PI / nstep_);

static int conf[7][23] =
{
   /* Ball       */ {
      3,1,3,3,1,3,1,1,
      3,1,3,3,1,3,1,1,
      3,1,3,3,1,3,1
   },
   /* Triangle   */ {
      1,0,0,0,0,0,0,3,
      1,0,0,0,0,0,0,3,
      1,0,0,0,0,0,0
   },
   /* Hexagon    */ {
      0,0,1,0,0,0,0,3,
      0,0,1,0,0,0,0,3,
      0,0,1,0,0,0,0
   },
   /* Snow Flake */ {
      1,1,1,1,3,3,3,3,
      1,1,1,1,3,3,3,3,
      1,1,1,1,3,3,3
   },
   /* Spiral     */ {
      2,1,2,1,2,1,2,1,
      2,1,2,1,2,1,2,1,
      2,1,2,1,2,1,2
   },
   /* Zig-zag    */ {
      3,3,3,1,1,1,3,3,
      3,1,1,1,3,3,3,1,
      1,1,3,3,3,1,1
   },
   /* Cobra      */ {
      2,0,0,2,1,3,0,2,
      0,2,3,0,1,3,2,1,
      1,2,3,1,0,3,0
   }
};

void trans(const int * conf, Mesh & mesh);

bool anim_step(const int * conf, Mesh & mesh);

int main(int argc, char *argv[])
{
   int cfg = -1;
   bool anim = true;
   bool visualization = true;

   OptionsParser args(argc, argv);
   args.AddOption(&cfg, "-c", "--configuration","");
   args.AddOption(&anim, "-anim", "--animation", "-no-anim",
                  "--no-animation",
                  "Enable or disable GLVis animation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // Define an empty mesh
   Mesh mesh(3, 6 * 24, 24);

   // Add vertices for 24 elements
   double c[9];
   int v[6];
   for (int i=0; i<12; i++)
   {
      // Add vertices for a pair of elements
      // First Upward-facing wedge
      c[0] = i-6; c[1] = 0.0; c[2] = i-6;
      c[3] = i-6; c[4] = 0.0; c[5] = i-5;
      c[6] = i-5; c[7] = 0.0; c[8] = i-5;

      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      c[1] = 1.0; c[4] = 1.0; c[7] = 1.0;
      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      for (int j=0; j<6; j++) { v[j] = 12 * i + j; }
      mesh.AddWedge(v);

      // Next Downward-facing wedge
      c[0] = i-6; c[1] = 0.0; c[2] = i-5;
      c[3] = i-5; c[4] = 0.0; c[5] = i-4;
      c[6] = i-5; c[7] = 0.0; c[8] = i-5;

      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      c[1] = 1.0; c[4] = 1.0; c[7] = 1.0;
      mesh.AddVertex(&c[0]);
      mesh.AddVertex(&c[3]);
      mesh.AddVertex(&c[6]);

      for (int j=0; j<6; j++) { v[j] = 12 * i + j + 6; }
      mesh.AddWedge(v);
   }

   mesh.FinalizeTopology();

   FiniteElementCollection *fec = new L2_FECollection(0, 3, 1);
   FiniteElementSpace fespace(&mesh, fec);
   GridFunction color(&fespace);

   for (int i=0; i<24; i++) { color[i] = (i%2)?1.0:-1.0; }

   // Output the initial mesh to a file
   {
      ostringstream oss;
      oss << "snake-init.mesh";
      ofstream ofs(oss.str().c_str());
      ofs.precision(8);
      mesh.Print(ofs);
      ofs.close();
   }

   if ( cfg >= 0 && !anim) { trans(conf[cfg], mesh); }

   // Output the resulting mesh to GLVis
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock.precision(8);
      sol_sock << "solution\n" << mesh << color << "keys Am\n"
               << "palette 22\n" << "valuerange -1.5 1\n"
               << "autoscale off\n" << flush;

      if (anim)
      {
         sol_sock << "pause\n" << flush;
         cout << "GLVis visualization paused."
              << " Press space (in the GLVis window) to resume it.\n";

         while (anim_step(conf[cfg], mesh))
         {
            static int turn = 0;
            sol_sock << "solution\n" << mesh << color;
            if (turn++ % 2 == 0)
            {
               sol_sock << "pause\n";
            }
            sol_sock << flush;
         }
         sol_sock << "autoscale on\n" << "valuerange -1.5 1\n" << flush;
      }
   }

   // Output the resulting mesh to a file
   {
      ostringstream oss;
      oss << "snake-c" << cfg << ".mesh";
      ofstream ofs(oss.str().c_str());
      ofs.precision(8);
      mesh.Print(ofs);
      ofs.close();
   }

   // Clean up and exit
   return 0;
}

void
rotate(double * x)
{
   if (notch_ == 0) { return; }

   double cent[3];
   Vector cVec(cent,3);
   Vector xVec(x,3);

   if (joint_%2 == 0)
   {
      cVec[0] = -5.5 + joint_ / 2; cVec[1] = 0.5; cVec[2] = 0.0;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            swap(xVec[0], xVec[1]);
            xVec[0] *= -1.0;
            break;
         case 2:
            xVec[0] *= -1.0;
            xVec[1] *= -1.0;
            break;
         case 3:
            swap(xVec[0], xVec[1]);
            xVec[1] *= -1.0;
            break;
      }
      xVec.Add(1.0, cVec);
   }
   else
   {
      cVec[0] = 0.0; cVec[1] = 0.5; cVec[2] = -4.5 + joint_ / 2;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            swap(xVec[1], xVec[2]);
            xVec[1] *= -1.0;
            break;
         case 2:
            xVec[1] *= -1.0;
            xVec[2] *= -1.0;
            break;
         case 3:
            swap(xVec[1], xVec[2]);
            xVec[2] *= -1.0;
            break;
      }
      xVec.Add(1.0, cVec);
   }
}

void
trans(const int * conf, Mesh & mesh)
{
   for (int i=0; i<23; i++)
   {
      joint_ = i;
      notch_ = conf[i];

      if (notch_ != 0)
      {
         for (int k=0; k<6*(i+1); k++)
         {
            rotate(mesh.GetVertex(k));
         }
      }
   }
}

void
rotate_step(double * x)
{
   if (notch_ == 0) { return; }

   double cent[3], y[3];
   Vector cVec(cent,3);
   Vector xVec(x,3);
   Vector yVec(y,3);

   if (joint_%2 == 0)
   {
      cVec[0] = -5.5 + joint_ / 2; cVec[1] = 0.5; cVec[2] = 0.0;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            yVec[0] = cosa_ * xVec[0] - sina_ * xVec[1];
            yVec[1] = sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
         case 2:
            yVec[0] = cosa_ * xVec[0] - sina_ * xVec[1];
            yVec[1] = sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
         case 3:
            yVec[0] =  cosa_ * xVec[0] + sina_ * xVec[1];
            yVec[1] = -sina_ * xVec[0] + cosa_ * xVec[1];
            yVec[2] = xVec[2];
            break;
      }
      add(yVec, 1.0, cVec, xVec);
   }
   else
   {
      cVec[0] = 0.0; cVec[1] = 0.5; cVec[2] = -4.5 + joint_ / 2;
      xVec.Add(-1.0, cVec);
      switch (notch_)
      {
         case 1:
            yVec[0] = xVec[0];
            yVec[1] = cosa_ * xVec[1] - sina_ * xVec[2];
            yVec[2] = sina_ * xVec[1] + cosa_ * xVec[2];
            break;
         case 2:
            yVec[0] = xVec[0];
            yVec[1] = cosa_ * xVec[1] - sina_ * xVec[2];
            yVec[2] = sina_ * xVec[1] + cosa_ * xVec[2];
            break;
         case 3:
            yVec[0] = xVec[0];
            yVec[1] =  cosa_ * xVec[1] + sina_ * xVec[2];
            yVec[2] = -sina_ * xVec[1] + cosa_ * xVec[2];
            break;
      }
      add(yVec, 1.0, cVec, xVec);
   }
}

bool
anim_step(const int * conf, Mesh & mesh)
{
   if (notch_ == 2 && step_ == 2 * nstep_) { joint_++; step_ = 0; }
   if (notch_ != 2 && step_ == nstep_) { joint_++; step_ = 0; }
   if (joint_ == 23) { return false; }
   notch_ = conf[joint_];

   if (notch_ == 0)
   {
      step_ = nstep_;
      return true;
   }
   else
   {
      for (int k=0; k<6*(joint_+1); k++)
      {
         rotate_step(mesh.GetVertex(k));
      }
   }
   step_++;
   return true;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>

using namespace std;

int main() {
    int x, y, z;
    cin >> x;
    y = 1;
    z = sqrt(x);
    while (z > y) {
        cout << y * y << endl;
        ++y;
    }
    return 0;
}<commit_msg>fixed<commit_after>#include <iostream>
#include <cmath>

using namespace std;

int main() {
    int x, y, z;
    cin >> x;
    y = 1;
    z = sqrt(x);
    while (z >= y) {
        cout << y * y << " ";
        ++y;
    }
    return 0;
}<|endoftext|>


<commit_before>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"

#include "axlib/axlib.h"

#define internal static

const std::string KwmCurrentVersion = "Kwm Version 2.2.0";
ax_state AXState = {};
ax_application *FocusedApplication;
ax_display *FocusedDisplay;
std::map<CFStringRef, space_info> WindowTree;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_focus KWMFocus = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_cache KWMCache = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

/* TODO(koekeishiya): focus-follows-mouse

                      Need to keep track of windows on the currently active space using 'CGCopyWindowList..' to get
                      z-ordering used for focus-follows-mouse. There are also cases in which applications doesn't seem
                      to trigger a kAXWindowCreated notification, so we probably have to pick these up from this list. */

/* TODO(koekeishiya): Should probably be moved to a 'cursor.cpp' or similar in the future,
                      along with other cursor-related functionality we might want */
EVENT_CALLBACK(Callback_AXEvent_MouseMoved)
{
    FocusWindowBelowCursor();
}

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMToggles.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = (hotkey *) calloc(1, sizeof(hotkey));
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMMode.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    std::map<int, CFTypeRef>::iterator It;
    for(It = KWMTiling.AllowedWindowRoles.begin(); It != KWMTiling.AllowedWindowRoles.end(); ++It)
        CFRelease(It->second);

    KWMTiling.AllowedWindowRoles.clear();
    KWMHotkeys.Modes.clear();
    KWMTiling.WindowRules.clear();
    KWMTiling.SpaceSettings.clear();
    KWMTiling.DisplaySettings.clear();
    KWMTiling.EnforcedWindows.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    /*
    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    */

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = SPLIT_OPTIMAL;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();
    KWMScreen.MaxCount = 5;
    KWMScreen.ActiveCount = 0;

    KWMToggles.EnableTilingMode = true;
    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.UseMouseFollowsFocus = true;
    KWMTiling.OptimalRatio = 1.618;
    KWMTiling.LockToContainer = true;
    KWMTiling.MonitorWindows = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
    KwmExecuteConfig();
    KwmExecuteInitScript();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    FocusedDisplay = AXLibMainDisplay();
    FocusedDisplay->Space = AXLibGetActiveSpace(FocusedDisplay);
    FocusedApplication = AXLibGetFocusedApplication();
    CreateWindowNodeTree(FocusedDisplay);
    /* ----------------------------------- */

    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<commit_msg>remove todo<commit_after>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"

#include "axlib/axlib.h"

#define internal static

const std::string KwmCurrentVersion = "Kwm Version 2.2.0";
ax_state AXState = {};
ax_application *FocusedApplication;
ax_display *FocusedDisplay;
std::map<CFStringRef, space_info> WindowTree;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_focus KWMFocus = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_cache KWMCache = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

/* TODO(koekeishiya): Should probably be moved to a 'cursor.cpp' or similar in the future,
                      along with other cursor-related functionality we might want */
EVENT_CALLBACK(Callback_AXEvent_MouseMoved)
{
    FocusWindowBelowCursor();
}

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMToggles.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = (hotkey *) calloc(1, sizeof(hotkey));
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMMode.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    std::map<int, CFTypeRef>::iterator It;
    for(It = KWMTiling.AllowedWindowRoles.begin(); It != KWMTiling.AllowedWindowRoles.end(); ++It)
        CFRelease(It->second);

    KWMTiling.AllowedWindowRoles.clear();
    KWMHotkeys.Modes.clear();
    KWMTiling.WindowRules.clear();
    KWMTiling.SpaceSettings.clear();
    KWMTiling.DisplaySettings.clear();
    KWMTiling.EnforcedWindows.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    /*
    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    */

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = SPLIT_OPTIMAL;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();
    KWMScreen.MaxCount = 5;
    KWMScreen.ActiveCount = 0;

    KWMToggles.EnableTilingMode = true;
    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.UseMouseFollowsFocus = true;
    KWMTiling.OptimalRatio = 1.618;
    KWMTiling.LockToContainer = true;
    KWMTiling.MonitorWindows = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
    KwmExecuteConfig();
    KwmExecuteInitScript();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    FocusedDisplay = AXLibMainDisplay();
    FocusedDisplay->Space = AXLibGetActiveSpace(FocusedDisplay);
    FocusedApplication = AXLibGetFocusedApplication();
    CreateWindowNodeTree(FocusedDisplay);
    /* ----------------------------------- */

    NSApplicationLoad();
    CFRunLoopRun();
    return 0;
}
<|endoftext|>


<commit_before>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"

#include "axlib/axlib.h"

#define internal static

const std::string KwmCurrentVersion = "Kwm Version 2.2.0";
std::map<CFStringRef, space_info> WindowTree;

ax_state AXState = {};
ax_display *FocusedDisplay;
ax_application *FocusedApplication;
ax_window *MarkedWindow;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMToggles.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = (hotkey *) calloc(1, sizeof(hotkey));
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                    else
                    {
                        free(Hotkey);
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMMode.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    KWMHotkeys.Modes.clear();
    KWMTiling.WindowRules.clear();
    KWMTiling.SpaceSettings.clear();
    KWMTiling.DisplaySettings.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    /*
    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    */

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = SPLIT_OPTIMAL;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();

    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.UseMouseFollowsFocus = true;
    KWMTiling.OptimalRatio = 1.618;
    KWMTiling.LockToContainer = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
    KwmExecuteConfig();
    KwmExecuteInitScript();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);
    NSApplicationLoad();

    if(!AXLibDisplayHasSeparateSpaces())
        Fatal("Error: 'Displays have separate spaces' must be enabled!");

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    ax_display *MainDisplay = AXLibMainDisplay();
    ax_display *Display = MainDisplay;
    do
    {
        ax_space *PrevSpace = Display->Space;
        Display->Space = AXLibGetActiveSpace(Display);
        Display->PrevSpace = PrevSpace;
        Display = AXLibNextDisplay(Display);
    } while(Display != MainDisplay);

    FocusedDisplay = MainDisplay;
    FocusedApplication = AXLibGetFocusedApplication();
    CreateWindowNodeTree(MainDisplay);
    /* ----------------------------------- */

    CFRunLoopRun();
    return 0;
}
<commit_msg>bump to version 3.0.0<commit_after>#include "kwm.h"
#include "helpers.h"
#include "daemon.h"
#include "display.h"
#include "space.h"
#include "window.h"
#include "keys.h"
#include "interpreter.h"
#include "scratchpad.h"
#include "border.h"
#include "config.h"
#include "command.h"
#include "cursor.h"

#include "axlib/axlib.h"

#define internal static

const std::string KwmCurrentVersion = "Kwm Version 3.0.0";
std::map<CFStringRef, space_info> WindowTree;

ax_state AXState = {};
ax_display *FocusedDisplay;
ax_application *FocusedApplication;
ax_window *MarkedWindow;

kwm_mach KWMMach = {};
kwm_path KWMPath = {};
kwm_screen KWMScreen = {};
kwm_toggles KWMToggles = {};
kwm_mode KWMMode = {};
kwm_tiling KWMTiling = {};
kwm_thread KWMThread = {};
kwm_hotkeys KWMHotkeys = {};
kwm_border FocusedBorder = {};
kwm_border MarkedBorder = {};
scratchpad Scratchpad = {};

CGEventRef CGEventCallback(CGEventTapProxy Proxy, CGEventType Type, CGEventRef Event, void *Refcon)
{
    switch(Type)
    {
        case kCGEventTapDisabledByTimeout:
        case kCGEventTapDisabledByUserInput:
        {
            if(!KWMMach.DisableEventTapInternal)
            {
                DEBUG("Restarting Event Tap");
                CGEventTapEnable(KWMMach.EventTap, true);
            }
        } break;
        case kCGEventKeyDown:
        {
            /* TODO(koekeishiya): Is there a better way to decide whether
                                  we should eat the CGEventRef or not (?) */
            if(KWMToggles.UseBuiltinHotkeys)
            {
                hotkey Eventkey = {}, *Hotkey = NULL;
                Hotkey = (hotkey *) calloc(1, sizeof(hotkey));
                if(Hotkey)
                {
                    CreateHotkeyFromCGEvent(Event, &Eventkey);
                    if(HotkeyExists(Eventkey.Mod, Eventkey.Key, Hotkey, KWMHotkeys.ActiveMode->Name))
                    {
                        AXLibConstructEvent(AXEvent_HotkeyPressed, Hotkey);
                        if(!Hotkey->Passthrough)
                            return NULL;
                    }
                    else
                    {
                        free(Hotkey);
                    }
                }
            }
        } break;
        case kCGEventMouseMoved:
        {
            if(KWMMode.Focus == FocusModeAutoraise)
                AXLibConstructEvent(AXEvent_MouseMoved, NULL);
        } break;
        default: {} break;
    }

    return Event;
}

internal bool
CheckPrivileges()
{
    bool Result = false;
    const void * Keys[] = { kAXTrustedCheckOptionPrompt };
    const void * Values[] = { kCFBooleanTrue };

    CFDictionaryRef Options;
    Options = CFDictionaryCreate(kCFAllocatorDefault,
                                 Keys, Values, sizeof(Keys) / sizeof(*Keys),
                                 &kCFCopyStringDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks);

    Result = AXIsProcessTrustedWithOptions(Options);
    CFRelease(Options);

    return Result;
}

internal bool
CheckArguments(int argc, char **argv)
{
    bool Result = false;

    if(argc == 2)
    {
        std::string Arg = argv[1];
        if(Arg == "--version")
        {
            std::cout << KwmCurrentVersion << std::endl;
            Result = true;
        }
    }

    return Result;
}

internal bool
GetKwmFilePath()
{
    bool Result = false;
    char PathBuf[PROC_PIDPATHINFO_MAXSIZE];
    pid_t Pid = getpid();
    int Ret = proc_pidpath(Pid, PathBuf, sizeof(PathBuf));
    if (Ret > 0)
    {
        KWMPath.FilePath = PathBuf;

        std::size_t Split = KWMPath.FilePath.find_last_of("/\\");
        KWMPath.FilePath = KWMPath.FilePath.substr(0, Split);
        Result = true;
    }

    return Result;
}

internal void
KwmClearSettings()
{
    KWMHotkeys.Modes.clear();
    KWMTiling.WindowRules.clear();
    KWMTiling.SpaceSettings.clear();
    KWMTiling.DisplaySettings.clear();
    KWMHotkeys.ActiveMode = GetBindingMode("default");
}

internal void
KwmExecuteConfig()
{
    char *HomeP = std::getenv("HOME");
    if(!HomeP)
    {
        DEBUG("Failed to get environment variable 'HOME'");
        return;
    }

    KWMPath.EnvHome = HomeP;
    KwmParseConfig(KWMPath.ConfigFile);
}

internal void
KwmExecuteInitScript()
{
    std::string InitFile = KWMPath.EnvHome + "/" + KWMPath.ConfigFolder + "/init";

    struct stat Buffer;
    if(stat(InitFile.c_str(), &Buffer) == 0)
        KwmExecuteThreadedSystemCommand(InitFile);
}

internal void
SignalHandler(int Signum)
{
    ShowAllScratchpadWindows();
    DEBUG("SignalHandler() " << Signum);

    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);
    exit(Signum);
}

internal void
Fatal(const std::string &Err)
{
    std::cout << Err << std::endl;
    exit(1);
}

internal void
KwmInit()
{
    if(!CheckPrivileges())
        Fatal("Could not access OSX Accessibility!");

    if(KwmStartDaemon())
        pthread_create(&KWMThread.Daemon, NULL, &KwmDaemonHandleConnectionBG, NULL);
    else
        Fatal("Kwm: Could not start daemon..");

    /*
    signal(SIGSEGV, SignalHandler);
    signal(SIGABRT, SignalHandler);
    signal(SIGTRAP, SignalHandler);
    signal(SIGTERM, SignalHandler);
    signal(SIGKILL, SignalHandler);
    signal(SIGINT, SignalHandler);
    */

    KWMScreen.SplitRatio = 0.5;
    KWMScreen.SplitMode = SPLIT_OPTIMAL;
    KWMScreen.PrevSpace = -1;
    KWMScreen.DefaultOffset = CreateDefaultScreenOffset();

    KWMToggles.UseBuiltinHotkeys = true;
    KWMToggles.UseMouseFollowsFocus = true;
    KWMTiling.OptimalRatio = 1.618;
    KWMTiling.LockToContainer = true;

    KWMMode.Space = SpaceModeBSP;
    KWMMode.Focus = FocusModeAutoraise;
    KWMMode.Cycle = CycleModeScreen;

    FocusedBorder.Radius = -1;
    MarkedBorder.Radius = -1;

    KWMPath.ConfigFile = "kwmrc";
    KWMPath.ConfigFolder = ".kwm";
    KWMPath.BSPLayouts = "layouts";
    KWMHotkeys.ActiveMode = GetBindingMode("default");

    GetKwmFilePath();
    KwmExecuteConfig();
    KwmExecuteInitScript();
}

void KwmQuit()
{
    ShowAllScratchpadWindows();
    CloseBorder(&FocusedBorder);
    CloseBorder(&MarkedBorder);

    exit(0);
}

void KwmReloadConfig()
{
    KwmClearSettings();
    KwmExecuteConfig();
}

int main(int argc, char **argv)
{
    if(CheckArguments(argc, argv))
        return 0;

    KwmInit();
    KWMMach.EventMask = ((1 << kCGEventKeyDown) |
                         (1 << kCGEventMouseMoved));

    KWMMach.EventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, KWMMach.EventMask, CGEventCallback, NULL);
    if(!KWMMach.EventTap || !CGEventTapIsEnabled(KWMMach.EventTap))
        Fatal("ERROR: Could not create event-tap!");

    CFRunLoopAddSource(CFRunLoopGetMain(),
                       CFMachPortCreateRunLoopSource(kCFAllocatorDefault, KWMMach.EventTap, 0),
                       kCFRunLoopCommonModes);
    CGEventTapEnable(KWMMach.EventTap, true);
    NSApplicationLoad();

    if(!AXLibDisplayHasSeparateSpaces())
        Fatal("Error: 'Displays have separate spaces' must be enabled!");

    /* NOTE(koekeishiya): Initialize AXLIB */
    AXLibInit(&AXState);
    AXLibStartEventLoop();

    ax_display *MainDisplay = AXLibMainDisplay();
    ax_display *Display = MainDisplay;
    do
    {
        ax_space *PrevSpace = Display->Space;
        Display->Space = AXLibGetActiveSpace(Display);
        Display->PrevSpace = PrevSpace;
        Display = AXLibNextDisplay(Display);
    } while(Display != MainDisplay);

    FocusedDisplay = MainDisplay;
    FocusedApplication = AXLibGetFocusedApplication();
    CreateWindowNodeTree(MainDisplay);
    /* ----------------------------------- */

    CFRunLoopRun();
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * 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 the copyright holders nor the names of its
 * contributors 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.
 */

//The purpose of this file is to provide endainness conversion utility
//functions. Depending on the endianness of the guest system, either
//the LittleEndianGuest or BigEndianGuest namespace is used.

#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__

#include "base/logging.hh"
#include "base/types.hh"
#include "enums/ByteOrder.hh"

// This lets us figure out what the byte order of the host system is
#if defined(__linux__)
#include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#elif defined (__sun)
#include <sys/isa_defs.h>
#else
#include <machine/endian.h>
#endif

#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#endif

//These functions actually perform the swapping for parameters
//of various bit lengths
inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(__linux__)
    return bswap_64(x);
#elif defined(__APPLE__)
    return OSSwapInt64(x);
#else
    return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
            ((uint64_t)(x) & 0xff00ULL) << 40 |
            ((uint64_t)(x) & 0xff0000ULL) << 24 |
            ((uint64_t)(x) & 0xff000000ULL) << 8 |
            ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
            ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
            ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
            ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}

inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(__linux__)
    return bswap_32(x);
#elif defined(__APPLE__)
    return OSSwapInt32(x);
#else
    return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
            ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
            ((uint32_t)(x) & 0xff000000) >> 24);
#endif
}

inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(__linux__)
    return bswap_16(x);
#elif defined(__APPLE__)
    return OSSwapInt16(x);
#else
    return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
                      ((uint16_t)(x) & 0xff00) >> 8);
#endif
}

// This function lets the compiler figure out how to call the
// swap_byte functions above for different data types.  Since the
// sizeof() values are known at compile time, it should inline to a
// direct call to the right swap_byteNN() function.
template <typename T>
inline T swap_byte(T x) {
    if (sizeof(T) == 8)
        return swap_byte64((uint64_t)x);
    else if (sizeof(T) == 4)
        return swap_byte32((uint32_t)x);
    else if (sizeof(T) == 2)
        return swap_byte16((uint16_t)x);
    else if (sizeof(T) == 1)
        return x;
    else
        panic("Can't byte-swap values larger than 64 bits");
}

template <typename T, size_t N>
inline std::array<T, N>
swap_byte(std::array<T, N> a)
{
    for (T &v: a)
        v = swap_byte(v);
    return a;
}

//The conversion functions with fixed endianness on both ends don't need to
//be in a namespace
template <typename T> inline T betole(T value) {return swap_byte(value);}
template <typename T> inline T letobe(T value) {return swap_byte(value);}

//For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if (defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN)) && BYTE_ORDER == BIG_ENDIAN
const ByteOrder HostByteOrder = ByteOrder::big;
template <typename T> inline T htole(T value) {return swap_byte(value);}
template <typename T> inline T letoh(T value) {return swap_byte(value);}
template <typename T> inline T htobe(T value) {return value;}
template <typename T> inline T betoh(T value) {return value;}
#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
const ByteOrder HostByteOrder = ByteOrder::little;
template <typename T> inline T htole(T value) {return value;}
template <typename T> inline T letoh(T value) {return value;}
template <typename T> inline T htobe(T value) {return swap_byte(value);}
template <typename T> inline T betoh(T value) {return swap_byte(value);}
#else
        #error Invalid Endianess
#endif

template <typename T>
inline T htog(T value, ByteOrder guest_byte_order)
{
    return guest_byte_order == ByteOrder::big ?
        htobe(value) : htole(value);
}

template <typename T>
inline T gtoh(T value, ByteOrder guest_byte_order)
{
    return guest_byte_order == ByteOrder::big ?
        betoh(value) : letoh(value);
}

#endif // __SIM_BYTE_SWAP_HH__
<commit_msg>sim: Use type_traits to steer swap_bytes.<commit_after>/*
 * Copyright (c) 2004 The Regents of The University of Michigan
 * 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 the copyright holders nor the names of its
 * contributors 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.
 */

//The purpose of this file is to provide endainness conversion utility
//functions. Depending on the endianness of the guest system, either
//the LittleEndianGuest or BigEndianGuest namespace is used.

#ifndef __SIM_BYTE_SWAP_HH__
#define __SIM_BYTE_SWAP_HH__

#include "base/types.hh"
#include "enums/ByteOrder.hh"

// This lets us figure out what the byte order of the host system is
#if defined(__linux__)
#include <endian.h>
// If this is a linux system, lets used the optimized definitions if they exist.
// If one doesn't exist, we pretty much get what is listed below, so it all
// works out
#include <byteswap.h>
#elif defined (__sun)
#include <sys/isa_defs.h>
#else
#include <machine/endian.h>
#endif

#if defined(__APPLE__)
#include <libkern/OSByteOrder.h>
#endif

#include <type_traits>

// These functions actually perform the swapping for parameters of various bit
// lengths.
inline uint64_t
swap_byte64(uint64_t x)
{
#if defined(__linux__)
    return bswap_64(x);
#elif defined(__APPLE__)
    return OSSwapInt64(x);
#else
    return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
            ((uint64_t)(x) & 0xff00ULL) << 40 |
            ((uint64_t)(x) & 0xff0000ULL) << 24 |
            ((uint64_t)(x) & 0xff000000ULL) << 8 |
            ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
            ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
            ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
            ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
#endif
}

inline uint32_t
swap_byte32(uint32_t x)
{
#if defined(__linux__)
    return bswap_32(x);
#elif defined(__APPLE__)
    return OSSwapInt32(x);
#else
    return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
            ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
            ((uint32_t)(x) & 0xff000000) >> 24);
#endif
}

inline uint16_t
swap_byte16(uint16_t x)
{
#if defined(__linux__)
    return bswap_16(x);
#elif defined(__APPLE__)
    return OSSwapInt16(x);
#else
    return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
                      ((uint16_t)(x) & 0xff00) >> 8);
#endif
}

template <typename T>
inline std::enable_if_t<
    sizeof(T) == 8 && std::is_convertible<T, uint64_t>::value, T>
swap_byte(T x)
{
    return swap_byte64((uint64_t)x);
}

template <typename T>
inline std::enable_if_t<
    sizeof(T) == 4 && std::is_convertible<T, uint32_t>::value, T>
swap_byte(T x)
{
    return swap_byte32((uint32_t)x);
}

template <typename T>
inline std::enable_if_t<
    sizeof(T) == 2 && std::is_convertible<T, uint16_t>::value, T>
swap_byte(T x)
{
    return swap_byte16((uint16_t)x);
}

template <typename T>
inline std::enable_if_t<
    sizeof(T) == 1 && std::is_convertible<T, uint8_t>::value, T>
swap_byte(T x)
{
    return x;
}

template <typename T, size_t N>
inline std::array<T, N>
swap_byte(std::array<T, N> a)
{
    for (T &v: a)
        v = swap_byte(v);
    return a;
}

//The conversion functions with fixed endianness on both ends don't need to
//be in a namespace
template <typename T> inline T betole(T value) {return swap_byte(value);}
template <typename T> inline T letobe(T value) {return swap_byte(value);}

//For conversions not involving the guest system, we can define the functions
//conditionally based on the BYTE_ORDER macro and outside of the namespaces
#if (defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN)) && BYTE_ORDER == BIG_ENDIAN
const ByteOrder HostByteOrder = ByteOrder::big;
template <typename T> inline T htole(T value) {return swap_byte(value);}
template <typename T> inline T letoh(T value) {return swap_byte(value);}
template <typename T> inline T htobe(T value) {return value;}
template <typename T> inline T betoh(T value) {return value;}
#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
const ByteOrder HostByteOrder = ByteOrder::little;
template <typename T> inline T htole(T value) {return value;}
template <typename T> inline T letoh(T value) {return value;}
template <typename T> inline T htobe(T value) {return swap_byte(value);}
template <typename T> inline T betoh(T value) {return swap_byte(value);}
#else
        #error Invalid Endianess
#endif

template <typename T>
inline T htog(T value, ByteOrder guest_byte_order)
{
    return guest_byte_order == ByteOrder::big ?
        htobe(value) : htole(value);
}

template <typename T>
inline T gtoh(T value, ByteOrder guest_byte_order)
{
    return guest_byte_order == ByteOrder::big ?
        betoh(value) : letoh(value);
}

#endif // __SIM_BYTE_SWAP_HH__
<|endoftext|>