<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// $Id$

#include "kateschema.h"
#include "kateschema.moc"

#include "kateconfig.h"
#include "katefactory.h"

#include <klocale.h>
#include <kdialog.h>
#include <kcolorbutton.h>
#include <kcombobox.h>
#include <klineeditdlg.h>
#include <kfontdialog.h>

#include <qbuttongroup.h>
#include <qcheckbox.h>
#include <qptrcollection.h>
#include <qdialog.h>
#include <qgrid.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qtextcodec.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qhbox.h>
#include <qobjectlist.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qstringlist.h>
#include <qtabwidget.h>
#include <qvbox.h>
#include <qvgroupbox.h>
#include <qwhatsthis.h>

KateSchemaManager::KateSchemaManager ()
  : m_config ("kateschemarc", false, false)
{
  update ();
}

KateSchemaManager::~KateSchemaManager ()
{
}

//
// read the types from config file and update the internal list
//
void KateSchemaManager::update (bool readfromfile)
{
  if (readfromfile)
    m_config.reparseConfiguration ();

  m_schemas = m_config.groupList();
  m_schemas.sort ();

  m_schemas.remove ("Kate Printing Schema");
  m_schemas.remove ("Kate Normal Schema");
  m_schemas.prepend (i18n("Printing"));
  m_schemas.prepend (i18n("Normal"));
}

//
// get the right group
// special handling of the default schemas ;)
//
KConfig *KateSchemaManager::schema (uint number)
{
  if ((number>1) && (number < m_schemas.count()))
    m_config.setGroup (m_schemas[number]);
  else if (number == 1)
    m_config.setGroup ("Kate Printing Schema");
  else
    m_config.setGroup ("Kate Normal Schema");

  return &m_config;
}

void KateSchemaManager::addSchema (const QString &t)
{
  m_config.setGroup (t);
  m_config.writeEntry("Color Background", KGlobalSettings::baseColor());

  update (false);
}

void KateSchemaManager::removeSchema (uint number)
{
  if (number >= m_schemas.count())
    return;

  if (number < 2)
    return;

  m_config.deleteGroup (name (number));

  update (false);
}

uint KateSchemaManager::number (const QString &name)
{
  int i;
  if ((i = m_schemas.findIndex(name)) > -1)
    return i;

  return 0;
}

QString KateSchemaManager::name (uint number)
{
  if ((number>1) && (number < m_schemas.count()))
    return m_schemas[number];
  else if (number == 1)
    return "Kate Printing Schema";

  return "Kate Normal Schema";
}

//
//
//
// DIALOGS !!!
//
//

//BEGIN KateSchemaConfigColorTab
KateSchemaConfigColorTab::KateSchemaConfigColorTab( QWidget *parent, const char * )
  : QWidget (parent)
{
  QHBox *b;
  QLabel *label;

  QVBoxLayout *blay=new QVBoxLayout(this, 0, KDialog::spacingHint());

  QVGroupBox *gbTextArea = new QVGroupBox(i18n("Text Area Background"), this);

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Normal text:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_back = new KColorButton(b);
  connect( m_back, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Selected text:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_selected = new KColorButton(b);
  connect( m_selected, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Current line:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_current = new KColorButton(b);
  connect( m_current, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  blay->addWidget(gbTextArea);

  QVGroupBox *gbBorder = new QVGroupBox(i18n("Additional Elements"), this);

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Left border background:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_iconborder = new KColorButton(b);
  connect( m_iconborder, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Bracket highlight:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_bracket = new KColorButton(b);
  connect( m_bracket, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Word wrap markers:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_wwmarker = new KColorButton(b);
  connect( m_wwmarker, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Tab markers:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_tmarker = new KColorButton(b);
  connect( m_tmarker, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  blay->addWidget(gbBorder);

  blay->addStretch();

  // QWhatsThis help
  QWhatsThis::add(m_back, i18n("
Sets the background color of the editing area.
"));
  QWhatsThis::add(m_selected, i18n("
Sets the background color of the selection.
"
        "
To set the text color for selected text, use the \"Configure "
        "Highlighting\" dialog.
"));
  QWhatsThis::add(m_current, i18n("
Sets the background color of the currently "
        "active line, which means the line where your cursor is positioned.
"));
  QWhatsThis::add(m_bracket, i18n("
Sets the bracket matching color. This means, "
        "if you place the cursor e.g. at a (, the matching ) will "
        "be highlighted with this color.
"));
  QWhatsThis::add(m_wwmarker, i18n(
        "
Sets the color of Word Wrap-related markers:
"
        "

Static Word Wrap

A vertical line which shows the column where "
        "text is going to be wrapped
"
        "
Dynamic Word Wrap

An arrow shown to the left of "
        "visually-wrapped lines

"));
  QWhatsThis::add(m_tmarker, i18n(
        "
Sets the color of the tabulator marks:
"));
}

KateSchemaConfigColorTab::~KateSchemaConfigColorTab()
{
}

void KateSchemaConfigColorTab::readConfig (KConfig *config)
{
  QColor tmp0 (KGlobalSettings::baseColor());
  QColor tmp1 (KGlobalSettings::highlightColor());
  QColor tmp2 (KGlobalSettings::alternateBackgroundColor());
  QColor tmp3 ( "#FFFF99" );
  QColor tmp4 (tmp2.dark());
  QColor tmp5 ( KGlobalSettings::textColor() );
  QColor tmp6 ( "#EAE9E8" );

  m_back->setColor(config->readColorEntry("Color Background", &tmp0));
  m_selected->setColor(config->readColorEntry("Color Selection", &tmp1));
  m_current->setColor(config->readColorEntry("Color Highlighted Line", &tmp2));
  m_bracket->setColor(config->readColorEntry("Color Highlighted Bracket", &tmp3));
  m_wwmarker->setColor(config->readColorEntry("Color Word Wrap Marker", &tmp4));
  m_tmarker->setColor(config->readColorEntry("Color Tab Marker", &tmp5));
  m_iconborder->setColor(config->readColorEntry("Color Icon Bar", &tmp6));
}

void KateSchemaConfigColorTab::writeConfig (KConfig *config)
{
  config->writeEntry("Color Background", m_back->color());
  config->writeEntry("Color Selection", m_selected->color());
  config->writeEntry("Color Highlighted Line", m_current->color());
  config->writeEntry("Color Highlighted Bracket", m_bracket->color());
  config->writeEntry("Color Word Wrap Marker", m_wwmarker->color());
  config->writeEntry("Color Tab Marker", m_tmarker->color());
  config->writeEntry("Color Icon Bar", m_iconborder->color());
}

//END KateSchemaConfigColorTab

//BEGIN FontConfig
KateSchemaConfigFontTab::KateSchemaConfigFontTab( QWidget *parent, const char * )
  : QWidget (parent)
{
    // sizemanagment
  QGridLayout *grid = new QGridLayout( this, 1, 1 );

  m_fontchooser = new KFontChooser ( this, 0L, false, QStringList(), false );
  m_fontchooser->enableColumn(KFontChooser::StyleList, false);
  grid->addWidget( m_fontchooser, 0, 0);

  connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), this, SLOT (slotFontSelected( const QFont & )));
  connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), parent->parentWidget(), SLOT (slotChanged()));
}

KateSchemaConfigFontTab::~KateSchemaConfigFontTab()
{
}

void KateSchemaConfigFontTab::slotFontSelected( const QFont &font )
{
  myFont = font;
}

void KateSchemaConfigFontTab::readConfig (KConfig *config)
{
  QFont f (KGlobalSettings::fixedFont());

  m_fontchooser->setFont (config->readFontEntry("Font", &f));
}

void KateSchemaConfigFontTab::writeConfig (KConfig *config)
{
  config->writeEntry("Font", myFont);
}

//END FontConfig

KateSchemaConfigPage::KateSchemaConfigPage( QWidget *parent )
  : Kate::ConfigPage( parent ),
    m_lastSchema (-1)
{
  QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );

  // hl chooser
  QHBox *hbHl = new QHBox( this );
  layout->add (hbHl);
  hbHl->setSpacing( KDialog::spacingHint() );
  QLabel *lHl = new QLabel( i18n("&Schema:"), hbHl );
  schemaCombo = new QComboBox( false, hbHl );
  lHl->setBuddy( schemaCombo );
  connect( schemaCombo, SIGNAL(activated(int)),
           this, SLOT(schemaChanged(int)) );

  btndel = new QPushButton( i18n("&Delete"), hbHl );
  connect( btndel, SIGNAL(clicked()), this, SLOT(deleteSchema()) );

  QPushButton *btnnew = new QPushButton( i18n("&New"), hbHl );
  connect( btnnew, SIGNAL(clicked()), this, SLOT(newSchema()) );

  m_tabWidget = new QTabWidget ( this );
  layout->add (m_tabWidget);

  m_colorTab = new KateSchemaConfigColorTab (m_tabWidget);
  m_tabWidget->addTab (m_colorTab, i18n("Colors"));

  m_fontTab = new KateSchemaConfigFontTab (m_tabWidget);
  m_tabWidget->addTab (m_fontTab, i18n("Font"));

  reload();
}

KateSchemaConfigPage::~KateSchemaConfigPage ()
{
  // just reload config from disc
  KateFactory::schemaManager()->update ();
}

void KateSchemaConfigPage::apply()
{
  if (m_lastSchema > -1)
  {
    m_colorTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
    m_fontTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
  }

  // just sync the config
  KateFactory::schemaManager()->schema (0)->sync();
KateFactory::schemaManager()->update ();

  KateRendererConfig::global()->setSchema (KateRendererConfig::global()->schema());
}

void KateSchemaConfigPage::reload()
{
  // just reload the config from disc
  KateFactory::schemaManager()->update ();

  update ();
}

void KateSchemaConfigPage::reset()
{
  reload ();
}

void KateSchemaConfigPage::defaults()
{
  reload ();
}

void KateSchemaConfigPage::update ()
{
  // soft update, no load from disk
  KateFactory::schemaManager()->update (false);

  schemaCombo->clear ();
  schemaCombo->insertStringList (KateFactory::schemaManager()->list ());

  schemaCombo->setCurrentItem (0);
  schemaChanged (0);

  schemaCombo->setEnabled (schemaCombo->count() > 0);
}

void KateSchemaConfigPage::deleteSchema ()
{
  int t = schemaCombo->currentItem ();

  KateFactory::schemaManager()->removeSchema (t);

  update ();
}

void KateSchemaConfigPage::newSchema ()
{
  QString t = KLineEditDlg::getText (i18n("Name for new Schema"), i18n ("Name:"), i18n("New Schema"), 0, this);

  KateFactory::schemaManager()->addSchema (t);

  // soft update, no load from disk
  KateFactory::schemaManager()->update (false);
  int i = KateFactory::schemaManager()->list ().findIndex (t);

  update ();
  if (i > -1)
  {
    schemaCombo->setCurrentItem (i);
    schemaChanged (i);
  }
}

void KateSchemaConfigPage::schemaChanged (int schema)
{
  if (schema < 2)
  {
    btndel->setEnabled (false);
  }
  else
  {
    btndel->setEnabled (true);
  }

  if (m_lastSchema > -1)
  {
    m_colorTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
    m_fontTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
  }

  m_colorTab->readConfig (KateFactory::schemaManager()->schema(schema));
  m_fontTab->readConfig (KateFactory::schemaManager()->schema(schema));

  m_lastSchema = schema;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>using margin hint, more compliant to style guide andd even looks good ;)<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2001-2003 Christoph Cullmann <cullmann@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

// $Id$

#include "kateschema.h"
#include "kateschema.moc"

#include "kateconfig.h"
#include "katefactory.h"

#include <klocale.h>
#include <kdialog.h>
#include <kcolorbutton.h>
#include <kcombobox.h>
#include <klineeditdlg.h>
#include <kfontdialog.h>

#include <qbuttongroup.h>
#include <qcheckbox.h>
#include <qptrcollection.h>
#include <qdialog.h>
#include <qgrid.h>
#include <qgroupbox.h>
#include <qlabel.h>
#include <qtextcodec.h>
#include <qlayout.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qhbox.h>
#include <qobjectlist.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qstringlist.h>
#include <qtabwidget.h>
#include <qvbox.h>
#include <qvgroupbox.h>
#include <qwhatsthis.h>

KateSchemaManager::KateSchemaManager ()
  : m_config ("kateschemarc", false, false)
{
  update ();
}

KateSchemaManager::~KateSchemaManager ()
{
}

//
// read the types from config file and update the internal list
//
void KateSchemaManager::update (bool readfromfile)
{
  if (readfromfile)
    m_config.reparseConfiguration ();

  m_schemas = m_config.groupList();
  m_schemas.sort ();

  m_schemas.remove ("Kate Printing Schema");
  m_schemas.remove ("Kate Normal Schema");
  m_schemas.prepend (i18n("Printing"));
  m_schemas.prepend (i18n("Normal"));
}

//
// get the right group
// special handling of the default schemas ;)
//
KConfig *KateSchemaManager::schema (uint number)
{
  if ((number>1) && (number < m_schemas.count()))
    m_config.setGroup (m_schemas[number]);
  else if (number == 1)
    m_config.setGroup ("Kate Printing Schema");
  else
    m_config.setGroup ("Kate Normal Schema");

  return &m_config;
}

void KateSchemaManager::addSchema (const QString &t)
{
  m_config.setGroup (t);
  m_config.writeEntry("Color Background", KGlobalSettings::baseColor());

  update (false);
}

void KateSchemaManager::removeSchema (uint number)
{
  if (number >= m_schemas.count())
    return;

  if (number < 2)
    return;

  m_config.deleteGroup (name (number));

  update (false);
}

uint KateSchemaManager::number (const QString &name)
{
  int i;
  if ((i = m_schemas.findIndex(name)) > -1)
    return i;

  return 0;
}

QString KateSchemaManager::name (uint number)
{
  if ((number>1) && (number < m_schemas.count()))
    return m_schemas[number];
  else if (number == 1)
    return "Kate Printing Schema";

  return "Kate Normal Schema";
}

//
//
//
// DIALOGS !!!
//
//

//BEGIN KateSchemaConfigColorTab
KateSchemaConfigColorTab::KateSchemaConfigColorTab( QWidget *parent, const char * )
  : QWidget (parent)
{
  QHBox *b;
  QLabel *label;

  QVBoxLayout *blay=new QVBoxLayout(this, 0, KDialog::spacingHint());

  QVGroupBox *gbTextArea = new QVGroupBox(i18n("Text Area Background"), this);

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Normal text:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_back = new KColorButton(b);
  connect( m_back, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Selected text:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_selected = new KColorButton(b);
  connect( m_selected, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbTextArea);
  label = new QLabel( i18n("Current line:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_current = new KColorButton(b);
  connect( m_current, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  blay->addWidget(gbTextArea);

  QVGroupBox *gbBorder = new QVGroupBox(i18n("Additional Elements"), this);

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Left border background:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_iconborder = new KColorButton(b);
  connect( m_iconborder, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Bracket highlight:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_bracket = new KColorButton(b);
  connect( m_bracket, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Word wrap markers:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_wwmarker = new KColorButton(b);
  connect( m_wwmarker, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  b = new QHBox (gbBorder);
  label = new QLabel( i18n("Tab markers:"), b);
  label->setAlignment( AlignLeft|AlignVCenter);
  m_tmarker = new KColorButton(b);
  connect( m_tmarker, SIGNAL( changed( const QColor & ) ), parent->parentWidget(), SLOT( slotChanged() ) );

  blay->addWidget(gbBorder);

  blay->addStretch();

  // QWhatsThis help
  QWhatsThis::add(m_back, i18n("
Sets the background color of the editing area.
"));
  QWhatsThis::add(m_selected, i18n("
Sets the background color of the selection.
"
        "
To set the text color for selected text, use the \"Configure "
        "Highlighting\" dialog.
"));
  QWhatsThis::add(m_current, i18n("
Sets the background color of the currently "
        "active line, which means the line where your cursor is positioned.
"));
  QWhatsThis::add(m_bracket, i18n("
Sets the bracket matching color. This means, "
        "if you place the cursor e.g. at a (, the matching ) will "
        "be highlighted with this color.
"));
  QWhatsThis::add(m_wwmarker, i18n(
        "
Sets the color of Word Wrap-related markers:
"
        "

Static Word Wrap

A vertical line which shows the column where "
        "text is going to be wrapped
"
        "
Dynamic Word Wrap

An arrow shown to the left of "
        "visually-wrapped lines

"));
  QWhatsThis::add(m_tmarker, i18n(
        "
Sets the color of the tabulator marks:
"));
}

KateSchemaConfigColorTab::~KateSchemaConfigColorTab()
{
}

void KateSchemaConfigColorTab::readConfig (KConfig *config)
{
  QColor tmp0 (KGlobalSettings::baseColor());
  QColor tmp1 (KGlobalSettings::highlightColor());
  QColor tmp2 (KGlobalSettings::alternateBackgroundColor());
  QColor tmp3 ( "#FFFF99" );
  QColor tmp4 (tmp2.dark());
  QColor tmp5 ( KGlobalSettings::textColor() );
  QColor tmp6 ( "#EAE9E8" );

  m_back->setColor(config->readColorEntry("Color Background", &tmp0));
  m_selected->setColor(config->readColorEntry("Color Selection", &tmp1));
  m_current->setColor(config->readColorEntry("Color Highlighted Line", &tmp2));
  m_bracket->setColor(config->readColorEntry("Color Highlighted Bracket", &tmp3));
  m_wwmarker->setColor(config->readColorEntry("Color Word Wrap Marker", &tmp4));
  m_tmarker->setColor(config->readColorEntry("Color Tab Marker", &tmp5));
  m_iconborder->setColor(config->readColorEntry("Color Icon Bar", &tmp6));
}

void KateSchemaConfigColorTab::writeConfig (KConfig *config)
{
  config->writeEntry("Color Background", m_back->color());
  config->writeEntry("Color Selection", m_selected->color());
  config->writeEntry("Color Highlighted Line", m_current->color());
  config->writeEntry("Color Highlighted Bracket", m_bracket->color());
  config->writeEntry("Color Word Wrap Marker", m_wwmarker->color());
  config->writeEntry("Color Tab Marker", m_tmarker->color());
  config->writeEntry("Color Icon Bar", m_iconborder->color());
}

//END KateSchemaConfigColorTab

//BEGIN FontConfig
KateSchemaConfigFontTab::KateSchemaConfigFontTab( QWidget *parent, const char * )
  : QWidget (parent)
{
    // sizemanagment
  QGridLayout *grid = new QGridLayout( this, 1, 1 );

  m_fontchooser = new KFontChooser ( this, 0L, false, QStringList(), false );
  m_fontchooser->enableColumn(KFontChooser::StyleList, false);
  grid->addWidget( m_fontchooser, 0, 0);

  connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), this, SLOT (slotFontSelected( const QFont & )));
  connect (m_fontchooser, SIGNAL (fontSelected( const QFont & )), parent->parentWidget(), SLOT (slotChanged()));
}

KateSchemaConfigFontTab::~KateSchemaConfigFontTab()
{
}

void KateSchemaConfigFontTab::slotFontSelected( const QFont &font )
{
  myFont = font;
}

void KateSchemaConfigFontTab::readConfig (KConfig *config)
{
  QFont f (KGlobalSettings::fixedFont());

  m_fontchooser->setFont (config->readFontEntry("Font", &f));
}

void KateSchemaConfigFontTab::writeConfig (KConfig *config)
{
  config->writeEntry("Font", myFont);
}

//END FontConfig

KateSchemaConfigPage::KateSchemaConfigPage( QWidget *parent )
  : Kate::ConfigPage( parent ),
    m_lastSchema (-1)
{
  QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );

  // hl chooser
  QHBox *hbHl = new QHBox( this );
  layout->add (hbHl);
  hbHl->setSpacing( KDialog::spacingHint() );
  QLabel *lHl = new QLabel( i18n("&Schema:"), hbHl );
  schemaCombo = new QComboBox( false, hbHl );
  lHl->setBuddy( schemaCombo );
  connect( schemaCombo, SIGNAL(activated(int)),
           this, SLOT(schemaChanged(int)) );

  btndel = new QPushButton( i18n("&Delete"), hbHl );
  connect( btndel, SIGNAL(clicked()), this, SLOT(deleteSchema()) );

  QPushButton *btnnew = new QPushButton( i18n("&New"), hbHl );
  connect( btnnew, SIGNAL(clicked()), this, SLOT(newSchema()) );

  m_tabWidget = new QTabWidget ( this );
  m_tabWidget->setMargin (KDialog::marginHint());
  layout->add (m_tabWidget);

  m_colorTab = new KateSchemaConfigColorTab (m_tabWidget);
  m_tabWidget->addTab (m_colorTab, i18n("Colors"));

  m_fontTab = new KateSchemaConfigFontTab (m_tabWidget);
  m_tabWidget->addTab (m_fontTab, i18n("Font"));

  reload();
}

KateSchemaConfigPage::~KateSchemaConfigPage ()
{
  // just reload config from disc
  KateFactory::schemaManager()->update ();
}

void KateSchemaConfigPage::apply()
{
  if (m_lastSchema > -1)
  {
    m_colorTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
    m_fontTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
  }

  // just sync the config
  KateFactory::schemaManager()->schema (0)->sync();
KateFactory::schemaManager()->update ();

  KateRendererConfig::global()->setSchema (KateRendererConfig::global()->schema());
}

void KateSchemaConfigPage::reload()
{
  // just reload the config from disc
  KateFactory::schemaManager()->update ();

  update ();
}

void KateSchemaConfigPage::reset()
{
  reload ();
}

void KateSchemaConfigPage::defaults()
{
  reload ();
}

void KateSchemaConfigPage::update ()
{
  // soft update, no load from disk
  KateFactory::schemaManager()->update (false);

  schemaCombo->clear ();
  schemaCombo->insertStringList (KateFactory::schemaManager()->list ());

  schemaCombo->setCurrentItem (0);
  schemaChanged (0);

  schemaCombo->setEnabled (schemaCombo->count() > 0);
}

void KateSchemaConfigPage::deleteSchema ()
{
  int t = schemaCombo->currentItem ();

  KateFactory::schemaManager()->removeSchema (t);

  update ();
}

void KateSchemaConfigPage::newSchema ()
{
  QString t = KLineEditDlg::getText (i18n("Name for new Schema"), i18n ("Name:"), i18n("New Schema"), 0, this);

  KateFactory::schemaManager()->addSchema (t);

  // soft update, no load from disk
  KateFactory::schemaManager()->update (false);
  int i = KateFactory::schemaManager()->list ().findIndex (t);

  update ();
  if (i > -1)
  {
    schemaCombo->setCurrentItem (i);
    schemaChanged (i);
  }
}

void KateSchemaConfigPage::schemaChanged (int schema)
{
  if (schema < 2)
  {
    btndel->setEnabled (false);
  }
  else
  {
    btndel->setEnabled (true);
  }

  if (m_lastSchema > -1)
  {
    m_colorTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
    m_fontTab->writeConfig (KateFactory::schemaManager()->schema(m_lastSchema));
  }

  m_colorTab->readConfig (KateFactory::schemaManager()->schema(schema));
  m_fontTab->readConfig (KateFactory::schemaManager()->schema(schema));

  m_lastSchema = schema;
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>/*
Mailbox
Copyright (C) 2015 Will Penington

This library 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; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
USA
*/

#include <QString>
#include <QtTest>
#include <QSignalSpy>

#include "erlangshell.h"

#include "erlatom.h"
#include "erlvartypes.h"

#include "mailboxqt.h"
#include "client.h"

class MailboxTest : public QObject
{
    Q_OBJECT

public:
    MailboxTest();

private Q_SLOTS:
    void canCommunicateWithErlangShell_data();
    void canCommunicateWithErlangShell();

    void clientCanConnectToErlang_data();
    void clientCanConnectToErlang();

    void canSendMessageToErlang_data();
    void canSendMessageToErlang();

    void canRecieveMessagesFromErlang_data();
    void canRecieveMessagesFromErlang();

    void canSendMultipleMessagesToErlang();
    void canRecieveMultipleMessagesFromErlang();

    void unusedNodeDoesNotCrash();

};

QVariantMap simpleValues {
    {"int", 5},
    {"float", 4.3},
    {"round_float", 4.0},
    {"large_int", 1000000},
    {"atom", QVariant::fromValue(Mailbox::ErlAtom("testatom"))}
};

MailboxTest::MailboxTest()
{
    Mailbox::init();
}

void MailboxTest::canCommunicateWithErlangShell_data() {
  QTest::addColumn<QByteArray>("statement");
  QTest::addColumn<QByteArray>("expected");

  QTest::newRow("atom") << QByteArray("sample_atom.") << QByteArray("sample_atom\n");
  QTest::newRow("maths") << QByteArray("1 + 1.") << QByteArray("2\n");
  QTest::newRow("complex types") << QByteArray("[{foo, bar}, 1 + 3, baz].")
                                 << QByteArray("[{foo,bar},4,baz]\n");
}

void MailboxTest::canCommunicateWithErlangShell()
{
  ErlangShell erl("dummy", "cookie");

  QFETCH(QByteArray, statement);
  QTEST(erl.execStatement(statement), "expected");
}

void MailboxTest::clientCanConnectToErlang_data()
{
  QTest::addColumn<QByteArray>("erlangNodeName");
  QTest::addColumn<QByteArray>("cnodeNodeName");
  QTest::addColumn<QByteArray>("cnodeConnectTo");
  QTest::addColumn<QByteArray>("erlangCookie");
  QTest::addColumn<QByteArray>("cnodeCookie");
  QTest::addColumn<bool>("expected");

  QTest::newRow("normal") << QByteArray("conTest1") << QByteArray("conTest1Lib")
                          << QByteArray("conTest1") << QByteArray("cookie")
                          << QByteArray("cookie") << true;
  QTest::newRow("all_different") << QByteArray("conTest2")
                                 << QByteArray("conTest2Lib")
                                 << QByteArray("wrong") << QByteArray("cookie1")
                                 << QByteArray("cookie2") << false;
  QTest::newRow("names_different") << QByteArray("conTest2")
                                 << QByteArray("conTest2Lib")
                                 << QByteArray("wrong") << QByteArray("cookie")
                                 << QByteArray("cookie") << false;
  QTest::newRow("cookies_different") << QByteArray("conTest1")
                          << QByteArray("conTest1Lib") << QByteArray("conTest1")
                          << QByteArray("cookie1") << QByteArray("cookie2")
                          << false;
  QTest::newRow("all_same") << QByteArray("conTest3") << QByteArray("conTest3")
                            << QByteArray("conTest3") << QByteArray("cookie")
                            << QByteArray("cookie") << false;
}

void MailboxTest::clientCanConnectToErlang()
{
  QFETCH(QByteArray, erlangNodeName);
  QFETCH(QByteArray, cnodeNodeName);
  QFETCH(QByteArray, cnodeConnectTo);
  QFETCH(QByteArray, erlangCookie);
  QFETCH(QByteArray, cnodeCookie);

  ErlangShell erl(erlangNodeName, erlangCookie);

  Mailbox::Client *node = new Mailbox::Client();

  QTEST(node->connect(cnodeNodeName, cnodeConnectTo, cnodeCookie), "expected");

  delete(node);
}

void MailboxTest::canSendMessageToErlang_data()
{
//    QTest::addColumn<QVariant>("value");

//    QTest::newRow("int") <<  QVariant(1);

//    Mailbox::ErlAtom atom("testatom");

//    QTest::newRow("atom") << QVariant::fromValue(atom);

    QTest::addColumn<QVariant>("value");

    QVariantMap::const_iterator i = simpleValues.constBegin();

    while (i != simpleValues.constEnd()) {
        QTest::newRow(i.key().toLocal8Bit().data()) << i.value();
        i++;
    }
}

QString erl_output(QVariant value)
{
    QString raw = Mailbox::formatErlangTerm(value);

    QRegularExpression re;
    re.setPattern("(\\d+\\.\\d*?[1-9])0+");
    QRegularExpressionMatch match =  re.match(raw);
    if (match.hasMatch()) {
        QString result = match.captured(1);
        return result;
    }

    re.setPattern("(\\d+\\.0)0+");
    match =  re.match(raw);

    if (match.hasMatch()) {
        QString result = match.captured(1);
        return result;
    }

    return raw;
}

void MailboxTest::canSendMessageToErlang()
{
  QFETCH(QVariant, value);

  ErlangShell erl("sendmessage", "cookie");
  Mailbox::Client *node = new Mailbox::Client();
  QVERIFY(node->connect("sendmessagelib", "sendmessage", "cookie"));

  erl.execStatement("register(shell, self()).");

  QCOMPARE(erl.execStatement("flush()."), QByteArray("ok\n"));

  node->sendMessage("shell", value);

  QByteArray full_result = QByteArray("Shell got ") + erl_output(value).toLatin1() + QByteArray("\n");

  QCOMPARE(erl.execStatement("flush()."), full_result);

  delete(node);
}

void MailboxTest::canRecieveMessagesFromErlang_data()
{
    QTest::addColumn<QVariant>("value");

    QVariantMap::const_iterator i = simpleValues.constBegin();

    while (i != simpleValues.constEnd()) {
        QTest::newRow(i.key().toLocal8Bit().data()) << i.value();
        i++;
    }

}

void MailboxTest::canRecieveMessagesFromErlang()
{

    ErlangShell erl("recvmessage", "cookie");
    Mailbox::Client *node = new Mailbox::Client();
    QVERIFY(node->connect("recvmessagelib", "recvmessage", "cookie"));

    QSignalSpy recvSpy(node, &Mailbox::Client::messageRecieved);

    erl.execStatement("register(shell, self()).");
    node->sendPid("shell");

    QCOMPARE(recvSpy.count(), 0);

    QFETCH(QVariant, value);
    QByteArray val_str = Mailbox::formatErlangTerm(value).toUtf8();

    QString stmt = "receive\n Pid -> Pid ! " + val_str + "\n end.";

    erl.execStatement(stmt.toUtf8());

    QVERIFY(recvSpy.count() == 1 || recvSpy.wait(1000));
    QCOMPARE(recvSpy.takeFirst()[0], value);

    delete(node);
}

void MailboxTest::canSendMultipleMessagesToErlang()
{
  ErlangShell erl("sendmultimessage", "cookie");
  Mailbox::Client *node = new Mailbox::Client();
  QVERIFY(node->connect("sendmultimessagelib", "sendmultimessage", "cookie"));

  erl.execStatement("register(shell, self()).");

  QCOMPARE(erl.execStatement("flush()."), QByteArray("ok\n"));

  node->sendAtom("shell", "test1");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test1\n"));

  node->sendAtom("shell", "test2");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test2\n"));

  node->sendAtom("shell", "test3");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test3\n"));

  delete(node);
}

void MailboxTest::canRecieveMultipleMessagesFromErlang()
{

    ErlangShell erl("rmm", "cookie");
    Mailbox::Client *node = new Mailbox::Client();
    QVERIFY(node->connect("rmml", "rmm", "cookie"));

    QSignalSpy recvSpy(node, &Mailbox::Client::messageRecieved);

    erl.execStatement("register(shell, self()).");
    node->sendPid("shell");

    QCOMPARE(recvSpy.count(), 0);

    erl.execStatement("Pid = receive\n  Pid -> Pid\n end.");
    erl.execStatement("Pid ! hello.");

    QVERIFY(recvSpy.count() == 1 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 2 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 3 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 4 || recvSpy.wait(1000));

    delete(node);
}

void MailboxTest::unusedNodeDoesNotCrash()
{
    Mailbox::Client *node = new Mailbox::Client();
    delete(node);
}

QTEST_GUILESS_MAIN(MailboxTest)

#include "tst_mailboxtest.moc"
<commit_msg>Roundtrip test added<commit_after>/*
Mailbox
Copyright (C) 2015 Will Penington

This library 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; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
USA
*/

#include <QString>
#include <QtTest>
#include <QSignalSpy>

#include "erlangshell.h"

#include "erlatom.h"
#include "erlvartypes.h"

#include "mailboxqt.h"
#include "client.h"

class MailboxTest : public QObject
{
    Q_OBJECT

public:
    MailboxTest();

private Q_SLOTS:
    void canCommunicateWithErlangShell_data();
    void canCommunicateWithErlangShell();

    void clientCanConnectToErlang_data();
    void clientCanConnectToErlang();

    void canSendMessageToErlang_data();
    void canSendMessageToErlang();

    void canRecieveMessagesFromErlang_data();
    void canRecieveMessagesFromErlang();

    void canSendMultipleMessagesToErlang();
    void canRecieveMultipleMessagesFromErlang();

    void canRoundTripFromCNode_data();
    void canRoundTripFromCNode();

    void unusedNodeDoesNotCrash();

};

QVariantMap simpleValues {
    {"int", 5},
    {"float", 4.3},
    {"round_float", 4.0},
    {"large_int", 1000000},
    {"atom", QVariant::fromValue(Mailbox::ErlAtom("testatom"))}
};

MailboxTest::MailboxTest()
{
    Mailbox::init();
}

void MailboxTest::canCommunicateWithErlangShell_data() {
  QTest::addColumn<QByteArray>("statement");
  QTest::addColumn<QByteArray>("expected");

  QTest::newRow("atom") << QByteArray("sample_atom.") << QByteArray("sample_atom\n");
  QTest::newRow("maths") << QByteArray("1 + 1.") << QByteArray("2\n");
  QTest::newRow("complex types") << QByteArray("[{foo, bar}, 1 + 3, baz].")
                                 << QByteArray("[{foo,bar},4,baz]\n");
}

void MailboxTest::canCommunicateWithErlangShell()
{
  ErlangShell erl("dummy", "cookie");

  QFETCH(QByteArray, statement);
  QTEST(erl.execStatement(statement), "expected");
}

void MailboxTest::clientCanConnectToErlang_data()
{
  QTest::addColumn<QByteArray>("erlangNodeName");
  QTest::addColumn<QByteArray>("cnodeNodeName");
  QTest::addColumn<QByteArray>("cnodeConnectTo");
  QTest::addColumn<QByteArray>("erlangCookie");
  QTest::addColumn<QByteArray>("cnodeCookie");
  QTest::addColumn<bool>("expected");

  QTest::newRow("normal") << QByteArray("conTest1") << QByteArray("conTest1Lib")
                          << QByteArray("conTest1") << QByteArray("cookie")
                          << QByteArray("cookie") << true;
  QTest::newRow("all_different") << QByteArray("conTest2")
                                 << QByteArray("conTest2Lib")
                                 << QByteArray("wrong") << QByteArray("cookie1")
                                 << QByteArray("cookie2") << false;
  QTest::newRow("names_different") << QByteArray("conTest2")
                                 << QByteArray("conTest2Lib")
                                 << QByteArray("wrong") << QByteArray("cookie")
                                 << QByteArray("cookie") << false;
  QTest::newRow("cookies_different") << QByteArray("conTest1")
                          << QByteArray("conTest1Lib") << QByteArray("conTest1")
                          << QByteArray("cookie1") << QByteArray("cookie2")
                          << false;
  QTest::newRow("all_same") << QByteArray("conTest3") << QByteArray("conTest3")
                            << QByteArray("conTest3") << QByteArray("cookie")
                            << QByteArray("cookie") << false;
}

void MailboxTest::clientCanConnectToErlang()
{
  QFETCH(QByteArray, erlangNodeName);
  QFETCH(QByteArray, cnodeNodeName);
  QFETCH(QByteArray, cnodeConnectTo);
  QFETCH(QByteArray, erlangCookie);
  QFETCH(QByteArray, cnodeCookie);

  ErlangShell erl(erlangNodeName, erlangCookie);

  Mailbox::Client *node = new Mailbox::Client();

  QTEST(node->connect(cnodeNodeName, cnodeConnectTo, cnodeCookie), "expected");

  delete(node);
}

void MailboxTest::canSendMessageToErlang_data()
{
//    QTest::addColumn<QVariant>("value");

//    QTest::newRow("int") <<  QVariant(1);

//    Mailbox::ErlAtom atom("testatom");

//    QTest::newRow("atom") << QVariant::fromValue(atom);

    QTest::addColumn<QVariant>("value");

    QVariantMap::const_iterator i = simpleValues.constBegin();

    while (i != simpleValues.constEnd()) {
        QTest::newRow(i.key().toLocal8Bit().data()) << i.value();
        i++;
    }
}

QString erl_output(QVariant value)
{
    QString raw = Mailbox::formatErlangTerm(value);

    QRegularExpression re;
    re.setPattern("(\\d+\\.\\d*?[1-9])0+");
    QRegularExpressionMatch match =  re.match(raw);
    if (match.hasMatch()) {
        QString result = match.captured(1);
        return result;
    }

    re.setPattern("(\\d+\\.0)0+");
    match =  re.match(raw);

    if (match.hasMatch()) {
        QString result = match.captured(1);
        return result;
    }

    return raw;
}

void MailboxTest::canSendMessageToErlang()
{
  QFETCH(QVariant, value);

  ErlangShell erl("sendmessage", "cookie");
  Mailbox::Client *node = new Mailbox::Client();
  QVERIFY(node->connect("sendmessagelib", "sendmessage", "cookie"));

  erl.execStatement("register(shell, self()).");

  QCOMPARE(erl.execStatement("flush()."), QByteArray("ok\n"));

  node->sendMessage("shell", value);

  QByteArray full_result = QByteArray("Shell got ") + erl_output(value).toLatin1() + QByteArray("\n");

  QCOMPARE(erl.execStatement("flush()."), full_result);

  delete(node);
}

void MailboxTest::canRecieveMessagesFromErlang_data()
{
    QTest::addColumn<QVariant>("value");

    QVariantMap::const_iterator i = simpleValues.constBegin();

    while (i != simpleValues.constEnd()) {
        QTest::newRow(i.key().toLocal8Bit().data()) << i.value();
        i++;
    }

}

void MailboxTest::canRecieveMessagesFromErlang()
{

    ErlangShell erl("recvmessage", "cookie");
    Mailbox::Client *node = new Mailbox::Client();
    QVERIFY(node->connect("recvmessagelib", "recvmessage", "cookie"));

    QSignalSpy recvSpy(node, &Mailbox::Client::messageRecieved);

    erl.execStatement("register(shell, self()).");
    node->sendPid("shell");

    QCOMPARE(recvSpy.count(), 0);

    QFETCH(QVariant, value);
    QByteArray val_str = Mailbox::formatErlangTerm(value).toUtf8();

    QString stmt = "receive\n Pid -> Pid ! " + val_str + "\n end.";

    erl.execStatement(stmt.toUtf8());

    QVERIFY(recvSpy.count() == 1 || recvSpy.wait(1000));
    QCOMPARE(recvSpy.takeFirst()[0], value);

    delete(node);
}

void MailboxTest::canSendMultipleMessagesToErlang()
{
  ErlangShell erl("sendmultimessage", "cookie");
  Mailbox::Client *node = new Mailbox::Client();
  QVERIFY(node->connect("sendmultimessagelib", "sendmultimessage", "cookie"));

  erl.execStatement("register(shell, self()).");

  QCOMPARE(erl.execStatement("flush()."), QByteArray("ok\n"));

  node->sendAtom("shell", "test1");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test1\n"));

  node->sendAtom("shell", "test2");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test2\n"));

  node->sendAtom("shell", "test3");

  QThread::sleep(1);

  QCOMPARE(erl.execStatement("flush()."), QByteArray("Shell got test3\n"));

  delete(node);
}

void MailboxTest::canRecieveMultipleMessagesFromErlang()
{

    ErlangShell erl("rmm", "cookie");
    Mailbox::Client *node = new Mailbox::Client();
    QVERIFY(node->connect("rmml", "rmm", "cookie"));

    QSignalSpy recvSpy(node, &Mailbox::Client::messageRecieved);

    erl.execStatement("register(shell, self()).");
    node->sendPid("shell");

    QCOMPARE(recvSpy.count(), 0);

    erl.execStatement("Pid = receive\n  Pid -> Pid\n end.");
    erl.execStatement("Pid ! hello.");

    QVERIFY(recvSpy.count() == 1 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 2 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 3 || recvSpy.wait(1000));

    node->sendPid("shell");
    erl.execStatement("Pid ! hello.");
    QVERIFY(recvSpy.count() == 4 || recvSpy.wait(1000));

    delete(node);
}

void MailboxTest::canRoundTripFromCNode_data()
{

    QTest::addColumn<QVariant>("value");

    QVariantMap::const_iterator i = simpleValues.constBegin();

    while (i != simpleValues.constEnd()) {
        QTest::newRow(i.key().toLocal8Bit().data()) << i.value();
        i++;
    }
}

void MailboxTest::canRoundTripFromCNode()
{
    QFETCH(QVariant, value);

    ErlangShell erl("roundtrip", "cookie");
    Mailbox::Client *node = new Mailbox::Client();
    QVERIFY(node->connect("roundtriplib", "roundtrip", "cookie"));

    QSignalSpy recvSpy(node, &Mailbox::Client::messageRecieved);

    erl.execStatement("register(shell, self()).");
    node->sendPid("shell");

    QCOMPARE(recvSpy.count(), 0);

    erl.execStatement("Pid = receive\n  Pid -> Pid\n end.");
    node->sendMessage("shell", value);
    erl.execStatement("receive\n Val -> Pid ! Val\n end.");

    QVERIFY(recvSpy.count() == 1 || recvSpy.wait(1000));
    QCOMPARE(recvSpy.takeFirst()[0], value);
}

void MailboxTest::unusedNodeDoesNotCrash()
{
    Mailbox::Client *node = new Mailbox::Client();
    delete(node);
}

QTEST_GUILESS_MAIN(MailboxTest)

#include "tst_mailboxtest.moc"
<|endoftext|>


<commit_before>#include <unistd.h>

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>
#include <osquery/sql.h>

extern "C" {
#include <libcryptsetup.h>
}

namespace osquery {
namespace tables {

void genFDEStatusForBlockDevice(const std::string &name,
                                const std::string &uuid,
                                QueryData &results) {
  Row r;
  r["name"] = name;
  r["uuid"] = uuid;

  struct crypt_device *cd = nullptr;
  const char *opt_header_device = nullptr;
  struct crypt_active_device cad;
  crypt_status_info ci;
  std::string type;
  std::string cipher;
  std::string cipher_mode;

  ci = crypt_status(cd, name.c_str());
  switch (ci) {
  case CRYPT_ACTIVE:
  case CRYPT_BUSY:
    r["encrypted"] = "1";

    int crypt_init;
#ifdef CENTOS_CENTOS6
    crypt_init = crypt_init_by_name(&cd, name.c_str());
#else
    crypt_init =
      crypt_init_by_name_and_header(&cd, name.c_str(), opt_header_device);
#endif

    if (crypt_init < 0) {
      VLOG(1) << "Unable to initialize crypt device for " << name;
      crypt_free(cd);
      break;
    }

    type = crypt_get_type(cd);
    if (crypt_get_active_device(cd, name.c_str(), &cad) < 0) {
      VLOG(1) << "Unable to get active device for " << name;
      crypt_free(cd);
      break;
    }
    cipher = crypt_get_cipher(cd);
    cipher_mode = crypt_get_cipher_mode(cd);
    r["type"] = type + "-" + cipher + "-" + cipher_mode;
    break;
  default:
    r["encrypted"] = "0";
  }

  results.push_back(r);
}

QueryData genFDEStatus(QueryContext &context) {
  QueryData results;

  if (getuid() || geteuid()) {
    VLOG(1) << "Not running as root, disk encryption status not available.";
    return results;
  }

  auto block_devices = SQL::selectAllFrom("block_devices");
  for (const auto &row : block_devices) {
    const auto name = (row.count("name") > 0) ? row.at("name") : "";
    const auto uuid = (row.count("uuid") > 0) ? row.at("uuid") : "";
    genFDEStatusForBlockDevice(name, uuid, results);
  }
  return results;
}
}
}
<commit_msg>Support RHEL6<commit_after>#include <unistd.h>

#include <osquery/core.h>
#include <osquery/logger.h>
#include <osquery/tables.h>
#include <osquery/sql.h>

extern "C" {
#include <libcryptsetup.h>
}

namespace osquery {
namespace tables {

void genFDEStatusForBlockDevice(const std::string &name,
                                const std::string &uuid,
                                QueryData &results) {
  Row r;
  r["name"] = name;
  r["uuid"] = uuid;

  struct crypt_device *cd = nullptr;
  struct crypt_active_device cad;
  crypt_status_info ci;
  std::string type;
  std::string cipher;
  std::string cipher_mode;

  ci = crypt_status(cd, name.c_str());
  switch (ci) {
  case CRYPT_ACTIVE:
  case CRYPT_BUSY:
    r["encrypted"] = "1";

    int crypt_init;
#if defined(CENTOS_CENTOS6) || defined(RHEL_RHEL6)
    crypt_init = crypt_init_by_name(&cd, name.c_str());
#else
    crypt_init =
      crypt_init_by_name_and_header(&cd, name.c_str(), nullptr);
#endif

    if (crypt_init < 0) {
      VLOG(1) << "Unable to initialize crypt device for " << name;
      crypt_free(cd);
      break;
    }

    type = crypt_get_type(cd);
    if (crypt_get_active_device(cd, name.c_str(), &cad) < 0) {
      VLOG(1) << "Unable to get active device for " << name;
      crypt_free(cd);
      break;
    }
    cipher = crypt_get_cipher(cd);
    cipher_mode = crypt_get_cipher_mode(cd);
    r["type"] = type + "-" + cipher + "-" + cipher_mode;
    break;
  default:
    r["encrypted"] = "0";
  }

  results.push_back(r);
}

QueryData genFDEStatus(QueryContext &context) {
  QueryData results;

  if (getuid() || geteuid()) {
    VLOG(1) << "Not running as root, disk encryption status not available.";
    return results;
  }

  auto block_devices = SQL::selectAllFrom("block_devices");
  for (const auto &row : block_devices) {
    const auto name = (row.count("name") > 0) ? row.at("name") : "";
    const auto uuid = (row.count("uuid") > 0) ? row.at("uuid") : "";
    genFDEStatusForBlockDevice(name, uuid, results);
  }
  return results;
}
}
}
<|endoftext|>


<commit_before>/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2018 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

#include "Lagrangian2d2DR.hpp"
#include "Interaction.hpp"
#include "BlockVector.hpp"

#include <boost/math/quaternion.hpp>

// #define DEBUG_NOCOLOR
// #define DEBUG_STDOUT
// #define DEBUG_MESSAGES
#include "debug.h"

void Lagrangian2d2DR::initialize(Interaction& inter)
{
  LagrangianR::initialize(inter);
  //proj_with_q  _jachqProj.reset(new SimpleMatrix(_jachq->size(0),_jachq->size(1)));

  if((inter.getSizeOfDS() !=3) and (inter.getSizeOfDS() !=6))
  {
    RuntimeException::selfThrow("Lagrangian2d2DR::initialize(Interaction& inter). The size of ds must of size 3");
  }
  unsigned int qSize = 3 * (inter.getSizeOfDS() / 3);
  _jachq.reset(new SimpleMatrix(2, qSize));
}

void Lagrangian2d2DR::computeJachq(SiconosVector& q, SiconosVector& z)
{
  DEBUG_BEGIN("Lagrangian2d2DR::computeJachq(Interaction& inter, SP::BlockVector q0 \n");

  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double G1x = q.getValue(0);
  double G1y = q.getValue(1);

  /* construct tangent vector */
  double Tx = Ny;
  double Ty = - Nx;

  double lever_arm_x = G1x-Px ;
  double lever_arm_y = G1y-Py ;
  DEBUG_PRINTF("lever_arm_x = %4.2e,\t lever_arm_ y = %4.2e\n", lever_arm_x, lever_arm_y);

  _jachq->setValue(0,0,Nx);
  _jachq->setValue(0,1,Ny);
  _jachq->setValue(0,2,lever_arm_y*Nx - lever_arm_x*Ny);

  _jachq->setValue(1,0,Tx);
  _jachq->setValue(1,1,Ty);
  _jachq->setValue(1,2,lever_arm_y*Tx - lever_arm_x*Ty);

  if(q.size() ==6)
  {
    DEBUG_PRINT("take into account second ds\n");
    double G2x = q.getValue(3);
    double G2y = q.getValue(4);

    _jachq->setValue(0,3,-Nx);
    _jachq->setValue(0,4,-Ny);
    _jachq->setValue(0,5,- ((G2y-Py)*Nx - (G2x-Px)*Ny));

    _jachq->setValue(1,3,-Tx);
    _jachq->setValue(1,4,-Ty);
    _jachq->setValue(1,5,-(G1y-Py)*Tx + (G1x-Px)*Ty);

  }
  DEBUG_EXPR(_jachq->display(););
  DEBUG_END("Lagrangian2d2DR::computeJachq(Interaction& inter, SP::BlockVector q0) \n");

}

double Lagrangian2d2DR::distance() const
{
  DEBUG_BEGIN("Lagrangian2d2DR::distance(...)\n")
  SiconosVector dpc(*_Pc2 - *_Pc1);
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_EXPR(_Pc2->display(););
  DEBUG_EXPR(dpc.display(););
  DEBUG_END("Lagrangian2d2DR::distance(...)\n")
  return dpc.norm2() * (inner_prod(*_Nc, dpc) >= 0 ? -1 : 1);

}

void Lagrangian2d2DR::computeh(SiconosVector& q, SiconosVector& z, SiconosVector& y)
{
  DEBUG_BEGIN("Lagrangian2d2DR::computeh(...)\n");
  DEBUG_EXPR(q.display());
  // Contact points and normal are stored as relative to q1 and q2, if
  // no q2 then pc2 and normal are absolute.

  // Update pc1 based on q and relPc1

  double angle= q(2);
  DEBUG_PRINTF("angle (ds1)= %e\n", angle);
  (*_Pc1)(0) = q(0) + cos(angle) * (*_relPc1)(0)- sin(angle) * (*_relPc1)(1);
  (*_Pc1)(1) = q(1) + sin(angle) * (*_relPc1)(0)+ cos(angle) * (*_relPc1)(1);
  if(q.size() == 6)
  {
    // To be checked
    DEBUG_PRINT("take into account second ds\n");
    angle = q(5);
    DEBUG_PRINTF("angle (ds2) = %e\n", angle);
    (*_Pc2)(0) = q(3) + cos(angle) * (*_relPc2)(0)- sin(angle) * (*_relPc2)(1);
    (*_Pc2)(1) = q(4) + sin(angle) * (*_relPc2)(0)+ cos(angle) * (*_relPc2)(1);
    (*_Nc)(0) =  cos(angle) * (*_relNc)(0)- sin(angle) * (*_relNc)(1);
    (*_Nc)(1) =  sin(angle) * (*_relNc)(0)+ cos(angle) * (*_relNc)(1);
  }
  else
  {
    *_Pc2 = *_relPc2;
    *_Nc = *_relNc;
  }
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_EXPR(_Pc2->display(););
  DEBUG_EXPR(_Nc->display(););
  // SP::SiconosVector q1 = (q0.getAllVect())[0];
  // ::boost::math::quaternion<double> qq1((*q1)(3), (*q1)(4), (*q1)(5), (*q1)(6));
  // ::boost::math::quaternion<double> qpc1(0,(*_relPc1)(0),(*_relPc1)(1),(*_relPc1)(2));

  // // apply q1 rotation and add
  // qpc1 = qq1 * qpc1 / qq1;
  // (*_Pc1)(0) = qpc1.R_component_2() + (*q1)(0);
  // (*_Pc1)(1) = qpc1.R_component_3() + (*q1)(1);
  // (*_Pc1)(2) = qpc1.R_component_4() + (*q1)(2);

  // if (q0.numberOfBlocks() > 1)
  // {
  //   // Update pc2 based on q0 and relPc2
  //   SP::SiconosVector q2 = (q0.getAllVect())[1];
  //   ::boost::math::quaternion<double> qq2((*q2)(3), (*q2)(4), (*q2)(5), (*q2)(6));
  //   ::boost::math::quaternion<double> qpc2(0,(*_relPc2)(0),(*_relPc2)(1),(*_relPc2)(2));

  //   // apply q2 rotation and add
  //   qpc2 = qq2 * qpc2 / qq2;
  //   (*_Pc2)(0) = qpc2.R_component_2() + (*q2)(0);
  //   (*_Pc2)(1) = qpc2.R_component_3() + (*q2)(1);
  //   (*_Pc2)(2) = qpc2.R_component_4() + (*q2)(2);

  //   // same for normal
  //   ::boost::math::quaternion<double> qnc(0, (*_relNc)(0), (*_relNc)(1), (*_relNc)(2));
  //   qnc = qq2 * qnc / qq2;
  //   (*_Nc)(0) = qnc.R_component_2();
  //   (*_Nc)(1) = qnc.R_component_3();
  //   (*_Nc)(2) = qnc.R_component_4();
  // }
  // else
  // {
  //   *_Pc2 = *_relPc2;
  //   *_Nc = *_relNc;
  // }

  LagrangianScleronomousR::computeh(q, z, y);
  y.setValue(0, distance());
  DEBUG_EXPR(y.display(););
  DEBUG_EXPR(display(););
  DEBUG_END("Lagrangian2d2DR::computeh(...)\n")
}
void Lagrangian2d2DR::display() const
{
  LagrangianR::display();

  std::cout << " _Pc1 :" << std::endl;
  if(_Pc1)
    _Pc1->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _Pc2 :" << std::endl;
  if(_Pc2)
    _Pc2->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _relPc1 :" << std::endl;
  if(_relPc1)
    _relPc1->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _relPc2 :" << std::endl;
  if(_relPc2)
    _relPc2->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _Nc :" << std::endl;
  if(_Nc)
    _Nc->display();
  else
    std::cout << " NULL :" << std::endl;
  std::cout << " _relNc :" << std::endl;
  if(_relNc)
    _relNc->display();
  else
    std::cout << " NULL :" << std::endl;

}
<commit_msg>[kernel] correct bug in the 2D computation of the relative velocity<commit_after>/* Siconos is a program dedicated to modeling, simulation and control
 * of non smooth dynamical systems.
 *
 * Copyright 2018 INRIA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/
#include "Lagrangian2d2DR.hpp"
#include "Interaction.hpp"
#include "BlockVector.hpp"

#include <boost/math/quaternion.hpp>

// #define DEBUG_NOCOLOR
// #define DEBUG_STDOUT
// #define DEBUG_MESSAGES
#include "debug.h"

void Lagrangian2d2DR::initialize(Interaction& inter)
{
  LagrangianR::initialize(inter);
  //proj_with_q  _jachqProj.reset(new SimpleMatrix(_jachq->size(0),_jachq->size(1)));

  if((inter.getSizeOfDS() !=3) and (inter.getSizeOfDS() !=6))
  {
    RuntimeException::selfThrow("Lagrangian2d2DR::initialize(Interaction& inter). The size of ds must of size 3");
  }
  unsigned int qSize = 3 * (inter.getSizeOfDS() / 3);
  _jachq.reset(new SimpleMatrix(2, qSize));
}

void Lagrangian2d2DR::computeJachq(SiconosVector& q, SiconosVector& z)
{
  DEBUG_BEGIN("Lagrangian2d2DR::computeJachq(Interaction& inter, SP::BlockVector q0 \n");

  double Nx = _Nc->getValue(0);
  double Ny = _Nc->getValue(1);
  double Px = _Pc1->getValue(0);
  double Py = _Pc1->getValue(1);
  double G1x = q.getValue(0);
  double G1y = q.getValue(1);

  /* construct tangent vector */
  double Tx = Ny;
  double Ty = - Nx;

  double lever_arm_x = G1x-Px ;
  double lever_arm_y = G1y-Py ;
  DEBUG_PRINTF("lever_arm_x = %4.2e,\t lever_arm_ y = %4.2e\n", lever_arm_x, lever_arm_y);

  _jachq->setValue(0,0,Nx);
  _jachq->setValue(0,1,Ny);
  _jachq->setValue(0,2,lever_arm_y*Nx - lever_arm_x*Ny);

  _jachq->setValue(1,0,Tx);
  _jachq->setValue(1,1,Ty);
  _jachq->setValue(1,2,lever_arm_y*Tx - lever_arm_x*Ty);

  if(q.size() ==6)
  {
    DEBUG_PRINT("take into account second ds\n");
    double G2x = q.getValue(3);
    double G2y = q.getValue(4);

    _jachq->setValue(0,3,-Nx);
    _jachq->setValue(0,4,-Ny);
    _jachq->setValue(0,5,- ((G2y-Py)*Nx - (G2x-Px)*Ny));

    _jachq->setValue(1,3,-Tx);
    _jachq->setValue(1,4,-Ty);
    _jachq->setValue(1,5,-((G2y-Py)*Tx - (G2x-Px)*Ty));

  }
  DEBUG_EXPR(_jachq->display(););
  DEBUG_END("Lagrangian2d2DR::computeJachq(Interaction& inter, SP::BlockVector q0) \n");

}

double Lagrangian2d2DR::distance() const
{
  DEBUG_BEGIN("Lagrangian2d2DR::distance(...)\n")
  SiconosVector dpc(*_Pc2 - *_Pc1);
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_EXPR(_Pc2->display(););
  DEBUG_EXPR(dpc.display(););
  DEBUG_END("Lagrangian2d2DR::distance(...)\n")
  return dpc.norm2() * (inner_prod(*_Nc, dpc) >= 0 ? -1 : 1);

}

void Lagrangian2d2DR::computeh(SiconosVector& q, SiconosVector& z, SiconosVector& y)
{
  DEBUG_BEGIN("Lagrangian2d2DR::computeh(...)\n");
  DEBUG_EXPR(q.display());
  // Contact points and normal are stored as relative to q1 and q2, if
  // no q2 then pc2 and normal are absolute.

  // Update pc1 based on q and relPc1

  double angle= q(2);
  DEBUG_PRINTF("angle (ds1)= %e\n", angle);
  (*_Pc1)(0) = q(0) + cos(angle) * (*_relPc1)(0)- sin(angle) * (*_relPc1)(1);
  (*_Pc1)(1) = q(1) + sin(angle) * (*_relPc1)(0)+ cos(angle) * (*_relPc1)(1);
  if(q.size() == 6)
  {
    // To be checked
    DEBUG_PRINT("take into account second ds\n");
    angle = q(5);
    DEBUG_PRINTF("angle (ds2) = %e\n", angle);
    (*_Pc2)(0) = q(3) + cos(angle) * (*_relPc2)(0)- sin(angle) * (*_relPc2)(1);
    (*_Pc2)(1) = q(4) + sin(angle) * (*_relPc2)(0)+ cos(angle) * (*_relPc2)(1);
    (*_Nc)(0) =  cos(angle) * (*_relNc)(0)- sin(angle) * (*_relNc)(1);
    (*_Nc)(1) =  sin(angle) * (*_relNc)(0)+ cos(angle) * (*_relNc)(1);
  }
  else
  {
    *_Pc2 = *_relPc2;
    *_Nc = *_relNc;
  }
  DEBUG_EXPR(_Pc1->display(););
  DEBUG_EXPR(_Pc2->display(););
  DEBUG_EXPR(_Nc->display(););

  LagrangianScleronomousR::computeh(q, z, y);
  y.setValue(0, distance());
  DEBUG_EXPR(y.display(););
  DEBUG_EXPR(display(););
  DEBUG_END("Lagrangian2d2DR::computeh(...)\n")
}
void Lagrangian2d2DR::display() const
{
  LagrangianR::display();

  std::cout << " _Pc1 :" << std::endl;
  if(_Pc1)
    _Pc1->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _Pc2 :" << std::endl;
  if(_Pc2)
    _Pc2->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _relPc1 :" << std::endl;
  if(_relPc1)
    _relPc1->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _relPc2 :" << std::endl;
  if(_relPc2)
    _relPc2->display();
  else
    std::cout << " NULL :" << std::endl;

  std::cout << " _Nc :" << std::endl;
  if(_Nc)
    _Nc->display();
  else
    std::cout << " NULL :" << std::endl;
  std::cout << " _relNc :" << std::endl;
  if(_relNc)
    _relNc->display();
  else
    std::cout << " NULL :" << std::endl;

}
<|endoftext|>


<commit_before>/*------------ant.cpp---------------------------------------------------------//
*
*             ants -- We have them
*
* Purpose: Figure out ant pathing to food. I want food.
*
*-----------------------------------------------------------------------------*/

#include <array>
#include <iostream>
#include <vector>
#include <random>
#include <fstream>

/*----------------------------------------------------------------------------//
* STRUCTS
*-----------------------------------------------------------------------------*/

// grid size
const int n = 5;

// structs for ant movement
struct coord{
    int x, y;
};

// Template for 2d boolean arrays
template <typename T, size_t rows, size_t cols>
using array2d = std::array<std::array<T, cols>, rows>;

// defines operators for definitions above
inline bool operator==(const coord& lhs, const coord& rhs) {
    return lhs.x == rhs.x && lhs.y == rhs.y;
}

inline bool operator!=(const coord& lhs, const coord& rhs) {
    return !(lhs == rhs);
}

struct ant{
    array2d<bool, n, n> phetus;
    coord pos;
    std::vector<coord> phepath, antpath;
    int stepnum, phenum, pernum;
};

struct grid{
    array2d<bool, n, n> wall;
    coord prize;
};

// Functions for ant movement
// Chooses step
ant step(ant curr, grid landscape, int gen_flag);

// Generates ants
std::vector<ant> gen_ants(std::vector<ant> ants, ant plate);

// Changes template ant
ant plate_toss(ant winner);

// Moves simulation every timestep
std::vector<ant> move(std::vector <ant> ants, grid landscape, coord spawn,
                      int pernum, int final_time, std::ofstream &output);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    // defining output file
    std::ofstream output("out.dat", std::ofstream::out);

    // defining initial ant vector and grid
    std::vector<ant> ants;
    grid landscape;
    landscape.wall = {};
    landscape.prize.x = n;   landscape.prize.y = n;

    // defining spawn point
    coord spawn;
    spawn.x = n - 1;
    spawn.y = 0;

    // defining misc characters
    int final_time = 100;
    int pernum = 10;

    move(ants, landscape, spawn, pernum, final_time, output);

    //output.close();

}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Chooses step
ant step(ant curr, grid landscape, int gen_flag){

    coord next_step[4];
    coord up, down, left, right, next;
    int pcount = 0;

    std::cout << curr.pos.x << '\t' << curr.pos.y << '\n' << '\n';

    up.x = curr.pos.x;          up.y = curr.pos.y + 1;
    down.x = curr.pos.x;        down.y = curr.pos.y - 1;
    left.x = curr.pos.x - 1;    left.y = curr.pos.y;
    right.x = curr.pos.x + 1;   right.y = curr.pos.y;

    //std::cout << up.x << '\t' << up.y << '\n';

    coord last;
    if (curr.stepnum == 0){
        last.x = -1;
        last.y = -1;
    }
    else{
        last = curr.antpath.back();
    }

    // determine possible movement
    // up case
    if (last != up) {
        if (up.y < n && landscape.wall[up.x][up.y] == 0){
            next_step[pcount] = up;
            pcount++;
        }
    }

    // down case
    if (last != down) {
        if (down.y > 0 && landscape.wall[down.x][down.y] == 0){
            next_step[pcount] = down;
            pcount++;
        }
    }

    if (last != left) {
        if (left.x > 0 && landscape.wall[left.x][left.y] == 0){
            next_step[pcount] = left;
            pcount++;
        }
    }

    // right case
    if (last != right) {
        if (right.x < n && landscape.wall[right.x][right.y] == 0){
            next_step[pcount] = right;
            pcount++;
        }
    }

    static std::random_device rd;
    auto seed = rd();
    static std::mt19937 gen(seed);

    if (gen_flag == 0 && curr.phetus[curr.pos.x][curr.pos.y] == 0){
        std::uniform_int_distribution<int> ant_distribution(0,pcount - 1);

        next = next_step[ant_distribution(gen)];

        curr.antpath.push_back(curr.pos);
        curr.pos = next;
    }

    else{

        double prob = curr.pernum / curr.phenum, aprob[4], rn, psum = 0;
        int choice = -1, cthulu;
        std::uniform_real_distribution<double> ant_distribution(0,1);

        // search through phepath to find ant's curr location
        for (size_t q = 0; q < curr.phepath.size(); q++){
            if (curr.pos.x == curr.phepath[q].x &&
                curr.pos.y == curr.phepath[q].y){
                cthulu = q;
            }
        }

        std::uniform_real_distribution<double> ant_ddist(0,1);

        rn = ant_ddist(gen);

        for (size_t q = 0; q < pcount; q++){
            if (next_step[q].x == curr.phepath[cthulu +1].x &&
                next_step[q].y == curr.phepath[cthulu +1].y){
                aprob[q] = prob;
            }
            else{
                aprob[q] = (1 - prob) / (pcount - 1);
            }

            psum += aprob[q];

            if (rn < psum && choice < 0){
                choice = q;
            }

        }

        next = next_step[choice];

        curr.antpath.push_back(curr.pos);
        curr.pos = next;

    }

    curr.stepnum++;

    return curr;
}

// Generates ants
std::vector<ant> gen_ants(std::vector<ant> ants, ant plate){
    ant curr;
    curr = plate;

    ants.push_back(curr);

    return ants;
}

// Changes template ant
ant plate_toss(ant winner){

    ant plate = winner;
    plate.phenum = winner.stepnum;
    plate.stepnum = 0;

    // generate a new phetus
    plate.phetus = {};

    for (size_t i = 0; i < winner.antpath.size(); i++){
        plate.phetus[winner.antpath[i].x][winner.antpath[i].y] = 1;
    }

    plate.antpath = {};

    return plate;
}

// Moves simulation every timestep
// step 1: create ants
// step 2: move ants
// step 3: profit?
//         redefine all paths = to shortest path
std::vector<ant> move(std::vector <ant> ants, grid landscape, coord spawn,
                      int pernum, int final_time, std::ofstream &output){

    std::vector<int> killlist;

    // setting template for first generate
    ant plate;

    plate.pos.x = spawn.x;
    plate.pos.y = spawn.y;
    plate.stepnum = 0;
    plate.phenum = n*n;
    plate.phetus = {};

    // to be defined later
    plate.pernum = pernum;

/*
    // define walls and prize at random spot
    grid landscape;
    landscape.wall = {};
    landscape.prize.x = n;   landscape.prize.y = n;
*/

    for (size_t i = 0; i < final_time; i++){
        std::cout << i << '\n';
        int flag = 0;
        // step 1: generate ant
        ants = gen_ants(ants, plate);

        // step 2: Move ants
        for (size_t j = 0; j < ants.size(); j++){
            ants[j] = step(ants[j], landscape, flag);
            if (ants[j].stepnum > ants[j].phenum){
                killlist.push_back(j);
            }

            if (ants[j].pos.x == landscape.prize.x &&
                ants[j].pos.y == landscape.prize.y){
                plate = plate_toss(ants[j]);
            }

        }

        for (size_t k = 0; k < killlist.size(); k++){
            ants.erase(ants.begin() + killlist[k]);
        }

        for (size_t l = 0; l < ants[0].phepath.size(); l++){
            output << ants[0].phepath[l].x << '\t'
                   << ants[0].phepath[l].y << '\n';
        }
        output << '\n' << '\n';
    }

    return ants;
}
<commit_msg>need to sort out the killlist.<commit_after>/*------------ant.cpp---------------------------------------------------------//
*
*             ants -- We have them
*
* Purpose: Figure out ant pathing to food. I want food.
*
*-----------------------------------------------------------------------------*/

#include <array>
#include <iostream>
#include <vector>
#include <random>
#include <fstream>
#include <algorithm>

/*----------------------------------------------------------------------------//
* STRUCTS
*-----------------------------------------------------------------------------*/

// grid size
const int n = 5;

// structs for ant movement
struct coord{
    int x, y;
};

// Template for 2d boolean arrays
template <typename T, size_t rows, size_t cols>
using array2d = std::array<std::array<T, cols>, rows>;

// defines operators for definitions above
inline bool operator==(const coord& lhs, const coord& rhs) {
    return lhs.x == rhs.x && lhs.y == rhs.y;
}

inline bool operator!=(const coord& lhs, const coord& rhs) {
    return !(lhs == rhs);
}

struct ant{
    array2d<bool, n, n> phetus;
    coord pos;
    std::vector<coord> phepath, antpath;
    int stepnum, phenum, pernum;
};

struct grid{
    array2d<bool, n, n> wall;
    coord prize;
};

// Functions for ant movement
// Chooses step
ant step(ant curr, grid landscape, int gen_flag);

// Generates ants
std::vector<ant> gen_ants(std::vector<ant> ants, ant plate);

// Changes template ant
ant plate_toss(ant winner);

// Moves simulation every timestep
std::vector<ant> move(std::vector <ant> ants, grid landscape, coord spawn,
                      int pernum, int final_time, std::ofstream &output);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    // defining output file
    std::ofstream output("out.dat", std::ofstream::out);

    // defining initial ant vector and grid
    std::vector<ant> ants;
    grid landscape;
    landscape.wall = {};
    landscape.prize.x = n;   landscape.prize.y = n;

    // defining spawn point
    coord spawn;
    spawn.x = n - 1;
    spawn.y = 0;

    // defining misc characters
    int final_time = 100;
    int pernum = 10;

    move(ants, landscape, spawn, pernum, final_time, output);

    //output.close();

}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// Chooses step
ant step(ant curr, grid landscape, int gen_flag){

    coord next_step[4];
    coord up, down, left, right, next;
    int pcount = 0;

    std::cout << curr.pos.x << '\t' << curr.pos.y << '\n' << '\n';

    up.x = curr.pos.x;          up.y = curr.pos.y + 1;
    down.x = curr.pos.x;        down.y = curr.pos.y - 1;
    left.x = curr.pos.x - 1;    left.y = curr.pos.y;
    right.x = curr.pos.x + 1;   right.y = curr.pos.y;

    //std::cout << up.x << '\t' << up.y << '\n';

    coord last;
    if (curr.stepnum == 0){
        last.x = -1;
        last.y = -1;
    }
    else{
        last = curr.antpath.back();
    }

    // determine possible movement
    // up case
    if (last != up) {
        if (up.y < n && landscape.wall[up.x][up.y] == 0){
            next_step[pcount] = up;
            pcount++;
        }
    }

    // down case
    if (last != down) {
        if (down.y > 0 && landscape.wall[down.x][down.y] == 0){
            next_step[pcount] = down;
            pcount++;
        }
    }

    if (last != left) {
        if (left.x > 0 && landscape.wall[left.x][left.y] == 0){
            next_step[pcount] = left;
            pcount++;
        }
    }

    // right case
    if (last != right) {
        if (right.x < n && landscape.wall[right.x][right.y] == 0){
            next_step[pcount] = right;
            pcount++;
        }
    }

    static std::random_device rd;
    auto seed = rd();
    static std::mt19937 gen(seed);

    if (gen_flag == 0 && curr.phetus[curr.pos.x][curr.pos.y] == 0){
        std::uniform_int_distribution<int> ant_distribution(0,pcount - 1);

        next = next_step[ant_distribution(gen)];

        curr.antpath.push_back(curr.pos);
        curr.pos = next;
    }

    else{

        double prob = curr.pernum / curr.phenum, aprob[4], rn, psum = 0;
        int choice = -1, cthulu;
        std::uniform_real_distribution<double> ant_distribution(0,1);

        // search through phepath to find ant's curr location
        for (size_t q = 0; q < curr.phepath.size(); q++){
            if (curr.pos.x == curr.phepath[q].x &&
                curr.pos.y == curr.phepath[q].y){
                cthulu = q;
            }
        }

        std::uniform_real_distribution<double> ant_ddist(0,1);

        rn = ant_ddist(gen);

        for (size_t q = 0; q < pcount; q++){
            if (next_step[q].x == curr.phepath[cthulu +1].x &&
                next_step[q].y == curr.phepath[cthulu +1].y){
                aprob[q] = prob;
            }
            else{
                aprob[q] = (1 - prob) / (pcount - 1);
            }

            psum += aprob[q];

            if (rn < psum && choice < 0){
                choice = q;
            }

        }

        next = next_step[choice];

        curr.antpath.push_back(curr.pos);
        curr.pos = next;

    }

    curr.stepnum++;

    return curr;
}

// Generates ants
std::vector<ant> gen_ants(std::vector<ant> ants, ant plate){
    ant curr;
    curr = plate;

    ants.push_back(curr);

    return ants;
}

// Changes template ant
ant plate_toss(ant winner){

    ant plate = winner;
    plate.phenum = winner.stepnum;
    plate.stepnum = 0;

    // generate a new phetus
    plate.phetus = {};

    for (size_t i = 0; i < winner.antpath.size(); i++){
        plate.phetus[winner.antpath[i].x][winner.antpath[i].y] = 1;
    }

    plate.antpath = {};

    return plate;
}

// Moves simulation every timestep
// step 1: create ants
// step 2: move ants
// step 3: profit?
//         redefine all paths = to shortest path
std::vector<ant> move(std::vector <ant> ants, grid landscape, coord spawn,
                      int pernum, int final_time, std::ofstream &output){

    std::vector<int> killlist;

    // setting template for first generate
    ant plate;

    plate.pos.x = spawn.x;
    plate.pos.y = spawn.y;
    plate.stepnum = 0;
    plate.phenum = n*n;
    plate.phetus = {};

    // to be defined later
    plate.pernum = pernum;

/*
    // define walls and prize at random spot
    grid landscape;
    landscape.wall = {};
    landscape.prize.x = n;   landscape.prize.y = n;
*/

    for (size_t i = 0; i < final_time; i++){
        std::cout << i << '\n';
        int flag = 0;
        // step 1: generate ant
        ants = gen_ants(ants, plate);

        // step 2: Move ants
        for (size_t j = 0; j < ants.size(); j++){
            ants[j] = step(ants[j], landscape, flag);
            if (ants[j].stepnum > ants[j].phenum){
                killlist.push_back(j);
            }

            if (ants[j].pos.x == landscape.prize.x &&
                ants[j].pos.y == landscape.prize.y){
                plate = plate_toss(ants[j]);
                flag = 1;
            }

        }

        std::sort(std::begin(killlist), std::end(killlist),
                  [](int &dum1, int &dum2)
                     {return dum1 > dum2;});

/*
        std::cout << "size: " << killlist.size() << '\n';
        for (size_t k = 0; k < killlist.size(); k++){
            ants.erase(ants.begin() + killlist[k]);
        }
*/

        if (flag == 1){
            for (size_t l = 0; l < ants[0].phepath.size(); l++){
                output << ants[0].phepath[l].x << '\t'
                       << ants[0].phepath[l].y << '\n';
            }
        }
        output << '\n' << '\n';
    }

    return ants;
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLException.hpp>
#include <xercesc/util/Mutexes.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Local, static data
// ---------------------------------------------------------------------------
static XMLMsgLoader* sMsgLoader = 0;
static XMLRegisterCleanup msgLoaderCleanup;
static bool sScannerMutexRegistered = false;
static XMLMutex* sMsgMutex = 0;
static XMLRegisterCleanup msgMutexCleanup;

// ---------------------------------------------------------------------------
//  Local, static functions
// ---------------------------------------------------------------------------

//
//  We need to fault in this mutex. But, since its used for synchronization
//  itself, we have to do this the low level way using a compare and swap.
//
static XMLMutex& gMsgMutex()
{
    if (!sScannerMutexRegistered)
    {
        XMLMutexLock lockInit(XMLPlatformUtils::fgAtomicMutex);

        if (!sScannerMutexRegistered)
        {
            sMsgMutex = new XMLMutex;
            msgMutexCleanup.registerCleanup(XMLException::reinitMsgMutex);
            sScannerMutexRegistered = true;
        }
    }

    return *sMsgMutex;
}

//
//  This method is a lazy evaluator for the message loader for exception
//  messages.
//
static XMLMsgLoader& gGetMsgLoader()
{
    if (!sMsgLoader)
    {
        // Lock the message loader mutex and load the text
	    XMLMutexLock lockInit(&gMsgMutex());

        // Fault it in on first request
        if (!sMsgLoader)
        {
            sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgExceptDomain);
            if (!sMsgLoader)
                XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);

            //
            // Register this XMLMsgLoader for cleanup at Termination.
            //
            msgLoaderCleanup.registerCleanup(XMLException::reinitMsgLoader);
        }
    }

    // We got it, so return it
    return *sMsgLoader;
}

// ---------------------------------------------------------------------------
//  XMLException: Virtual destructor
// ---------------------------------------------------------------------------
XMLException::~XMLException()
{
    fMemoryManager->deallocate(fMsg);
    fMemoryManager->deallocate(fSrcFile);
}

// ---------------------------------------------------------------------------
//  XMLException: Setter methods
// ---------------------------------------------------------------------------
void XMLException::setPosition(const char* const file, const unsigned int line)
{
    fSrcLine = line;
	fMemoryManager->deallocate(fSrcFile);
    fSrcFile = XMLString::replicate(file, fMemoryManager);
}

// ---------------------------------------------------------------------------
//  XMLException: Hidden constructors and operators
// ---------------------------------------------------------------------------
XMLException::XMLException() :

    fCode(XMLExcepts::NoError)
    , fSrcFile(0)
    , fSrcLine(0)
    , fMsg(0)
    , fMemoryManager(0)
{
}

XMLException::XMLException( const   char* const     srcFile
                            , const unsigned int    srcLine
                            , MemoryManager* const  memoryManager) :

    fCode(XMLExcepts::NoError)
    , fSrcFile(0)
    , fSrcLine(srcLine)
    , fMsg(0)
    , fMemoryManager(memoryManager)
{
    if (!memoryManager)
        fMemoryManager = XMLPlatformUtils::fgMemoryManager;
    fSrcFile = XMLString::replicate(srcFile, fMemoryManager);
}

XMLException::XMLException(const XMLException& toCopy) :

    fCode(toCopy.fCode)
    , fSrcFile(0)
    , fSrcLine(toCopy.fSrcLine)
    , fMsg(XMLString::replicate(toCopy.fMsg, toCopy.fMemoryManager))
    , fMemoryManager(toCopy.fMemoryManager)
{
    if (toCopy.fSrcFile) {
        fSrcFile = XMLString::replicate
        (
            toCopy.fSrcFile
            , fMemoryManager
        );
    }
}

XMLException& XMLException::operator=(const XMLException& toAssign)
{
    if (this != &toAssign)
    {
        //use the original memory manager to deallocate
        fMemoryManager->deallocate(fSrcFile);
        fSrcFile = 0;
        fMemoryManager->deallocate(fMsg);
        fMsg = 0;

        fMemoryManager = toAssign.fMemoryManager;
        fSrcLine = toAssign.fSrcLine;
        fCode = toAssign.fCode;

        if (toAssign.fMsg) {
            fMsg = XMLString::replicate
            (
                toAssign.fMsg
                , fMemoryManager
            );
        }

        if (toAssign.fSrcFile) {
            fSrcFile = XMLString::replicate
            (
                toAssign.fSrcFile
                , fMemoryManager
            );
        }
    }
    return *this;
}

// ---------------------------------------------------------------------------
//  XMLException: Protected methods
// ---------------------------------------------------------------------------
void XMLException::loadExceptText(const XMLExcepts::Codes toLoad)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 2047;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

void
XMLException::loadExceptText(const  XMLExcepts::Codes toLoad
                            , const XMLCh* const        text1
                            , const XMLCh* const        text2
                            , const XMLCh* const        text3
                            , const XMLCh* const        text4)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 4095;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize, text1, text2, text3, text4, fMemoryManager))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

void
XMLException::loadExceptText(const  XMLExcepts::Codes toLoad
                            , const char* const         text1
                            , const char* const         text2
                            , const char* const         text3
                            , const char* const         text4)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 4095;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize, text1, text2, text3, text4, fMemoryManager))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

// -----------------------------------------------------------------------
//  Reinitialise the message mutex
// -----------------------------------------------------------------------
void XMLException::reinitMsgMutex()
{
    delete sMsgMutex;
    sMsgMutex = 0;
    sScannerMutexRegistered = false;
}

// -----------------------------------------------------------------------
//  Reinitialise the message loader
// -----------------------------------------------------------------------
void XMLException::reinitMsgLoader()
{
    delete sMsgLoader;
    sMsgLoader = 0;
}

XERCES_CPP_NAMESPACE_END
<commit_msg>Initialize memory manager to default.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLException.hpp>
#include <xercesc/util/Mutexes.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLMsgLoader.hpp>
#include <xercesc/util/XMLRegisterCleanup.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_BEGIN

// ---------------------------------------------------------------------------
//  Local, static data
// ---------------------------------------------------------------------------
static XMLMsgLoader* sMsgLoader = 0;
static XMLRegisterCleanup msgLoaderCleanup;
static bool sScannerMutexRegistered = false;
static XMLMutex* sMsgMutex = 0;
static XMLRegisterCleanup msgMutexCleanup;

// ---------------------------------------------------------------------------
//  Local, static functions
// ---------------------------------------------------------------------------

//
//  We need to fault in this mutex. But, since its used for synchronization
//  itself, we have to do this the low level way using a compare and swap.
//
static XMLMutex& gMsgMutex()
{
    if (!sScannerMutexRegistered)
    {
        XMLMutexLock lockInit(XMLPlatformUtils::fgAtomicMutex);

        if (!sScannerMutexRegistered)
        {
            sMsgMutex = new XMLMutex;
            msgMutexCleanup.registerCleanup(XMLException::reinitMsgMutex);
            sScannerMutexRegistered = true;
        }
    }

    return *sMsgMutex;
}

//
//  This method is a lazy evaluator for the message loader for exception
//  messages.
//
static XMLMsgLoader& gGetMsgLoader()
{
    if (!sMsgLoader)
    {
        // Lock the message loader mutex and load the text
	    XMLMutexLock lockInit(&gMsgMutex());

        // Fault it in on first request
        if (!sMsgLoader)
        {
            sMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgExceptDomain);
            if (!sMsgLoader)
                XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);

            //
            // Register this XMLMsgLoader for cleanup at Termination.
            //
            msgLoaderCleanup.registerCleanup(XMLException::reinitMsgLoader);
        }
    }

    // We got it, so return it
    return *sMsgLoader;
}

// ---------------------------------------------------------------------------
//  XMLException: Virtual destructor
// ---------------------------------------------------------------------------
XMLException::~XMLException()
{
    fMemoryManager->deallocate(fMsg);
    fMemoryManager->deallocate(fSrcFile);
}

// ---------------------------------------------------------------------------
//  XMLException: Setter methods
// ---------------------------------------------------------------------------
void XMLException::setPosition(const char* const file, const unsigned int line)
{
    fSrcLine = line;
	fMemoryManager->deallocate(fSrcFile);
    fSrcFile = XMLString::replicate(file, fMemoryManager);
}

// ---------------------------------------------------------------------------
//  XMLException: Hidden constructors and operators
// ---------------------------------------------------------------------------
XMLException::XMLException() :

    fCode(XMLExcepts::NoError)
    , fSrcFile(0)
    , fSrcLine(0)
    , fMsg(0)
    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
}

XMLException::XMLException( const   char* const     srcFile
                            , const unsigned int    srcLine
                            , MemoryManager* const  memoryManager) :

    fCode(XMLExcepts::NoError)
    , fSrcFile(0)
    , fSrcLine(srcLine)
    , fMsg(0)
    , fMemoryManager(memoryManager)
{
    if (!memoryManager)
        fMemoryManager = XMLPlatformUtils::fgMemoryManager;
    fSrcFile = XMLString::replicate(srcFile, fMemoryManager);
}

XMLException::XMLException(const XMLException& toCopy) :

    fCode(toCopy.fCode)
    , fSrcFile(0)
    , fSrcLine(toCopy.fSrcLine)
    , fMsg(XMLString::replicate(toCopy.fMsg, toCopy.fMemoryManager))
    , fMemoryManager(toCopy.fMemoryManager)
{
    if (toCopy.fSrcFile) {
        fSrcFile = XMLString::replicate
        (
            toCopy.fSrcFile
            , fMemoryManager
        );
    }
}

XMLException& XMLException::operator=(const XMLException& toAssign)
{
    if (this != &toAssign)
    {
        //use the original memory manager to deallocate
        fMemoryManager->deallocate(fSrcFile);
        fSrcFile = 0;
        fMemoryManager->deallocate(fMsg);
        fMsg = 0;

        fMemoryManager = toAssign.fMemoryManager;
        fSrcLine = toAssign.fSrcLine;
        fCode = toAssign.fCode;

        if (toAssign.fMsg) {
            fMsg = XMLString::replicate
            (
                toAssign.fMsg
                , fMemoryManager
            );
        }

        if (toAssign.fSrcFile) {
            fSrcFile = XMLString::replicate
            (
                toAssign.fSrcFile
                , fMemoryManager
            );
        }
    }
    return *this;
}

// ---------------------------------------------------------------------------
//  XMLException: Protected methods
// ---------------------------------------------------------------------------
void XMLException::loadExceptText(const XMLExcepts::Codes toLoad)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 2047;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

void
XMLException::loadExceptText(const  XMLExcepts::Codes toLoad
                            , const XMLCh* const        text1
                            , const XMLCh* const        text2
                            , const XMLCh* const        text3
                            , const XMLCh* const        text4)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 4095;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize, text1, text2, text3, text4, fMemoryManager))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

void
XMLException::loadExceptText(const  XMLExcepts::Codes toLoad
                            , const char* const         text1
                            , const char* const         text2
                            , const char* const         text3
                            , const char* const         text4)
{
    // Store the error code
    fCode = toLoad;

    // Load up the text into a local buffer
    const unsigned int msgSize = 4095;
    XMLCh errText[msgSize + 1];

    // load the text
	if (!gGetMsgLoader().loadMsg(toLoad, errText, msgSize, text1, text2, text3, text4, fMemoryManager))
	{
		fMsg = XMLString::replicate
        (
        XMLUni::fgDefErrMsg
            , fMemoryManager
        );
		return;
	}

    // We got the text so replicate it into the message member
    fMsg = XMLString::replicate(errText, fMemoryManager);
}

// -----------------------------------------------------------------------
//  Reinitialise the message mutex
// -----------------------------------------------------------------------
void XMLException::reinitMsgMutex()
{
    delete sMsgMutex;
    sMsgMutex = 0;
    sScannerMutexRegistered = false;
}

// -----------------------------------------------------------------------
//  Reinitialise the message loader
// -----------------------------------------------------------------------
void XMLException::reinitMsgLoader()
{
    delete sMsgLoader;
    sMsgLoader = 0;
}

XERCES_CPP_NAMESPACE_END
<|endoftext|>