<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "sessiondialog.h"
#include "session.h"

#include <QtGui/QInputDialog>
#include <QtGui/QValidator>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace ProjectExplorer {
namespace Internal {

class SessionValidator : public QValidator
{
public:
    SessionValidator(QObject *parent, QStringList sessions);
    void fixup(QString & input) const;
    QValidator::State validate(QString & input, int & pos) const;
private:
    QStringList m_sessions;
};

SessionValidator::SessionValidator(QObject *parent, QStringList sessions)
    : QValidator(parent), m_sessions(sessions)
{
}

QValidator::State SessionValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos)
    if (m_sessions.contains(input))
        return QValidator::Intermediate;
    else
        return QValidator::Acceptable;
}

void SessionValidator::fixup(QString &input) const
{
    int i = 2;
    QString copy;
    do {
        copy = input + QString(" (%1)").arg(i);
        ++i;
    } while (m_sessions.contains(copy));
    input = copy;
}

class SessionNameInputDialog : public QDialog
{
    Q_OBJECT
public:
    SessionNameInputDialog(const QStringList &sessions, QWidget *parent = 0);

    void setValue(const QString &value);
    QString value() const;

private:
    QLineEdit *m_newSessionLineEdit;
};

SessionNameInputDialog::SessionNameInputDialog(const QStringList &sessions, QWidget *parent)
    : QDialog(parent)
{
    QVBoxLayout *hlayout = new QVBoxLayout(this);
    QLabel *label = new QLabel(tr("Enter the name of the session:"), this);
    hlayout->addWidget(label);
    m_newSessionLineEdit = new QLineEdit(this);
    m_newSessionLineEdit->setValidator(new SessionValidator(this, sessions));
    hlayout->addWidget(m_newSessionLineEdit);
    QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
    connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
    hlayout->addWidget(buttons);
    setLayout(hlayout);
}

void SessionNameInputDialog::setValue(const QString &value)
{
    m_newSessionLineEdit->setText(value);
}

QString SessionNameInputDialog::value() const
{
    return m_newSessionLineEdit->text();
}

SessionDialog::SessionDialog(SessionManager *sessionManager)
    : m_sessionManager(sessionManager)
{
    m_ui.setupUi(this);

    connect(m_ui.btCreateNew, SIGNAL(clicked()),
            this, SLOT(createNew()));
    connect(m_ui.btClone, SIGNAL(clicked()),
            this, SLOT(clone()));
    connect(m_ui.btDelete, SIGNAL(clicked()),
            this, SLOT(remove()));

    connect(m_ui.btSwitch, SIGNAL(clicked()), this, SLOT(switchToSession()));
    connect(m_ui.btRename, SIGNAL(clicked()), this, SLOT(rename()));

    connect(m_ui.sessionList, SIGNAL(itemDoubleClicked (QListWidgetItem *)),
            this, SLOT(switchToSession()));

    connect(m_ui.sessionList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
            this, SLOT(updateActions()));

    m_ui.whatsASessionLabel->setOpenExternalLinks(true);
    addItems(true);
    markItems();
}

void SessionDialog::addItems(bool setDefaultSession)
{
    QStringList sessions = m_sessionManager->sessions();
    foreach (const QString &session, sessions) {
        m_ui.sessionList->addItem(session);
        if (setDefaultSession && session == m_sessionManager->activeSession())
            m_ui.sessionList->setCurrentRow(m_ui.sessionList->count() - 1);
    }
}
void SessionDialog::markItems()
{
    for(int i = 0; i < m_ui.sessionList->count(); ++i) {
        QListWidgetItem *item = m_ui.sessionList->item(i);
        QFont f = item->font();
        QString session = item->data(Qt::DisplayRole).toString();
        if (m_sessionManager->isDefaultSession(session))
            f.setItalic(true);
        else
            f.setItalic(false);
        if (m_sessionManager->activeSession() == session && !m_sessionManager->isDefaultVirgin())
            f.setBold(true);
        else
            f.setBold(false);
        item->setFont(f);
    }
}

void SessionDialog::updateActions()
{
    bool isDefault = false;
    bool isActive = false;

    if (m_ui.sessionList->currentItem()) {
        isDefault = (m_ui.sessionList->currentItem()->text() == QLatin1String("default"));
        isActive = (m_ui.sessionList->currentItem()->text() == m_sessionManager->activeSession());
    }

    m_ui.btDelete->setDisabled(isActive || isDefault);
    m_ui.btRename->setDisabled(isDefault);
}

void SessionDialog::createNew()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setWindowTitle(tr("New session name"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        QString newSession = newSessionInputDialog.value();
        if (newSession.isEmpty() || m_sessionManager->sessions().contains(newSession))
            return;

        m_sessionManager->createSession(newSession);
        m_ui.sessionList->clear();
        QStringList sessions = m_sessionManager->sessions();
        m_ui.sessionList->addItems(sessions);
        m_ui.sessionList->setCurrentRow(sessions.indexOf(newSession));
    }
}

void SessionDialog::clone()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setValue(m_ui.sessionList->currentItem()->text());
    newSessionInputDialog.setWindowTitle(tr("New session name"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        QString newSession = newSessionInputDialog.value();
        if (m_sessionManager->cloneSession(m_ui.sessionList->currentItem()->text(), newSession)) {
            m_ui.sessionList->clear();
            QStringList sessions = m_sessionManager->sessions();
            m_ui.sessionList->addItems(sessions);
            m_ui.sessionList->setCurrentRow(sessions.indexOf(newSession));
        }
    }
}

void SessionDialog::remove()
{
    m_sessionManager->deleteSession(m_ui.sessionList->currentItem()->text());
    m_ui.sessionList->clear();
    addItems(false);
    markItems();
}

void SessionDialog::rename()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setValue(m_ui.sessionList->currentItem()->text());
    newSessionInputDialog.setWindowTitle(tr("Rename session"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        m_sessionManager->renameSession(m_ui.sessionList->currentItem()->text(), newSessionInputDialog.value());
        m_ui.sessionList->clear();
        addItems(false);
        markItems();
    }
}

void SessionDialog::switchToSession()
{
    if (m_ui.sessionList->currentItem()) {
        QString session = m_ui.sessionList->currentItem()->text();
        m_sessionManager->loadSession(session);
        markItems();
    }
    updateActions();
}

} // namespace Internal
} // namespace ProjectExplorer

#include "sessiondialog.moc"
<commit_msg>Session Dialog: Fixes italic/bold after adding new/cloning sessions<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "sessiondialog.h"
#include "session.h"

#include <QtGui/QInputDialog>
#include <QtGui/QValidator>

using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;

namespace ProjectExplorer {
namespace Internal {

class SessionValidator : public QValidator
{
public:
    SessionValidator(QObject *parent, QStringList sessions);
    void fixup(QString & input) const;
    QValidator::State validate(QString & input, int & pos) const;
private:
    QStringList m_sessions;
};

SessionValidator::SessionValidator(QObject *parent, QStringList sessions)
    : QValidator(parent), m_sessions(sessions)
{
}

QValidator::State SessionValidator::validate(QString &input, int &pos) const
{
    Q_UNUSED(pos)
    if (m_sessions.contains(input))
        return QValidator::Intermediate;
    else
        return QValidator::Acceptable;
}

void SessionValidator::fixup(QString &input) const
{
    int i = 2;
    QString copy;
    do {
        copy = input + QString(" (%1)").arg(i);
        ++i;
    } while (m_sessions.contains(copy));
    input = copy;
}

class SessionNameInputDialog : public QDialog
{
    Q_OBJECT
public:
    SessionNameInputDialog(const QStringList &sessions, QWidget *parent = 0);

    void setValue(const QString &value);
    QString value() const;

private:
    QLineEdit *m_newSessionLineEdit;
};

SessionNameInputDialog::SessionNameInputDialog(const QStringList &sessions, QWidget *parent)
    : QDialog(parent)
{
    QVBoxLayout *hlayout = new QVBoxLayout(this);
    QLabel *label = new QLabel(tr("Enter the name of the session:"), this);
    hlayout->addWidget(label);
    m_newSessionLineEdit = new QLineEdit(this);
    m_newSessionLineEdit->setValidator(new SessionValidator(this, sessions));
    hlayout->addWidget(m_newSessionLineEdit);
    QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
    connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
    hlayout->addWidget(buttons);
    setLayout(hlayout);
}

void SessionNameInputDialog::setValue(const QString &value)
{
    m_newSessionLineEdit->setText(value);
}

QString SessionNameInputDialog::value() const
{
    return m_newSessionLineEdit->text();
}

SessionDialog::SessionDialog(SessionManager *sessionManager)
    : m_sessionManager(sessionManager)
{
    m_ui.setupUi(this);

    connect(m_ui.btCreateNew, SIGNAL(clicked()),
            this, SLOT(createNew()));
    connect(m_ui.btClone, SIGNAL(clicked()),
            this, SLOT(clone()));
    connect(m_ui.btDelete, SIGNAL(clicked()),
            this, SLOT(remove()));

    connect(m_ui.btSwitch, SIGNAL(clicked()), this, SLOT(switchToSession()));
    connect(m_ui.btRename, SIGNAL(clicked()), this, SLOT(rename()));

    connect(m_ui.sessionList, SIGNAL(itemDoubleClicked (QListWidgetItem *)),
            this, SLOT(switchToSession()));

    connect(m_ui.sessionList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
            this, SLOT(updateActions()));

    m_ui.whatsASessionLabel->setOpenExternalLinks(true);
    addItems(true);
    markItems();
}

void SessionDialog::addItems(bool setDefaultSession)
{
    QStringList sessions = m_sessionManager->sessions();
    foreach (const QString &session, sessions) {
        m_ui.sessionList->addItem(session);
        if (setDefaultSession && session == m_sessionManager->activeSession())
            m_ui.sessionList->setCurrentRow(m_ui.sessionList->count() - 1);
    }
}
void SessionDialog::markItems()
{
    for(int i = 0; i < m_ui.sessionList->count(); ++i) {
        QListWidgetItem *item = m_ui.sessionList->item(i);
        QFont f = item->font();
        QString session = item->data(Qt::DisplayRole).toString();
        if (m_sessionManager->isDefaultSession(session))
            f.setItalic(true);
        else
            f.setItalic(false);
        if (m_sessionManager->activeSession() == session && !m_sessionManager->isDefaultVirgin())
            f.setBold(true);
        else
            f.setBold(false);
        item->setFont(f);
    }
}

void SessionDialog::updateActions()
{
    bool isDefault = false;
    bool isActive = false;

    if (m_ui.sessionList->currentItem()) {
        isDefault = (m_ui.sessionList->currentItem()->text() == QLatin1String("default"));
        isActive = (m_ui.sessionList->currentItem()->text() == m_sessionManager->activeSession());
    }

    m_ui.btDelete->setDisabled(isActive || isDefault);
    m_ui.btRename->setDisabled(isDefault);
}

void SessionDialog::createNew()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setWindowTitle(tr("New session name"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        QString newSession = newSessionInputDialog.value();
        if (newSession.isEmpty() || m_sessionManager->sessions().contains(newSession))
            return;

        m_sessionManager->createSession(newSession);
        m_ui.sessionList->clear();
        QStringList sessions = m_sessionManager->sessions();
        m_ui.sessionList->addItems(sessions);
        m_ui.sessionList->setCurrentRow(sessions.indexOf(newSession));
        markItems();
    }
}

void SessionDialog::clone()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setValue(m_ui.sessionList->currentItem()->text());
    newSessionInputDialog.setWindowTitle(tr("New session name"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        QString newSession = newSessionInputDialog.value();
        if (m_sessionManager->cloneSession(m_ui.sessionList->currentItem()->text(), newSession)) {
            m_ui.sessionList->clear();
            QStringList sessions = m_sessionManager->sessions();
            m_ui.sessionList->addItems(sessions);
            m_ui.sessionList->setCurrentRow(sessions.indexOf(newSession));
            markItems();
        }
    }
}

void SessionDialog::remove()
{
    m_sessionManager->deleteSession(m_ui.sessionList->currentItem()->text());
    m_ui.sessionList->clear();
    addItems(false);
    markItems();
}

void SessionDialog::rename()
{
    SessionNameInputDialog newSessionInputDialog(m_sessionManager->sessions(), this);
    newSessionInputDialog.setValue(m_ui.sessionList->currentItem()->text());
    newSessionInputDialog.setWindowTitle(tr("Rename session"));

    if (newSessionInputDialog.exec() == QDialog::Accepted) {
        m_sessionManager->renameSession(m_ui.sessionList->currentItem()->text(), newSessionInputDialog.value());
        m_ui.sessionList->clear();
        addItems(false);
        markItems();
    }
}

void SessionDialog::switchToSession()
{
    if (m_ui.sessionList->currentItem()) {
        QString session = m_ui.sessionList->currentItem()->text();
        m_sessionManager->loadSession(session);
        markItems();
    }
    updateActions();
}

} // namespace Internal
} // namespace ProjectExplorer

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


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljseditorplugin.h"
#include "qmljshighlighter.h"
#include "qmljseditor.h"
#include "qmljseditorconstants.h"
#include "qmljseditorfactory.h"
#include "qmljscodecompletion.h"
#include "qmljshoverhandler.h"
#include "qmljsmodelmanager.h"
#include "qmlfilewizard.h"
#include "qmljspreviewrunner.h"

#include <qmldesigner/qmldesignerconstants.h>

#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/fontsettings.h>
#include <texteditor/storagesettings.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/textfilewizard.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/completionsupport.h>
#include <utils/qtcassert.h>

#include <QtCore/QtPlugin>
#include <QtCore/QDebug>
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
#include <QtGui/QMenu>
#include <QtGui/QAction>

using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
using namespace QmlJSEditor::Constants;

QmlJSEditorPlugin *QmlJSEditorPlugin::m_instance = 0;

QmlJSEditorPlugin::QmlJSEditorPlugin() :
        m_modelManager(0),
    m_wizard(0),
    m_editor(0),
    m_actionHandler(0)
{
    m_instance = this;
}

QmlJSEditorPlugin::~QmlJSEditorPlugin()
{
    removeObject(m_editor);
    delete m_actionHandler;
    m_instance = 0;
}

bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *error_message)
{
    Core::ICore *core = Core::ICore::instance();
    if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/qmljseditor/QmlJSEditor.mimetypes.xml"), error_message))
        return false;

    m_modelManager = new ModelManager(this);
    addAutoReleasedObject(m_modelManager);

    QList<int> context;
    context << core->uniqueIDManager()->uniqueIdentifier(QmlJSEditor::Constants::C_QMLJSEDITOR_ID)
            << core->uniqueIDManager()->uniqueIdentifier(QmlDesigner::Constants::C_QT_QUICK_TOOLS_MENU);

    m_editor = new QmlJSEditorFactory(this);
    addObject(m_editor);

    Core::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard);
    wizardParameters.setCategory(QLatin1String(Core::Constants::WIZARD_CATEGORY_QT));
    wizardParameters.setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::WIZARD_TR_CATEGORY_QT));
    wizardParameters.setDescription(tr("Creates a Qt QML file."));
    wizardParameters.setDisplayName(tr("Qt QML File"));
    wizardParameters.setId(QLatin1String("Q.Qml"));
    addAutoReleasedObject(new QmlFileWizard(wizardParameters, core));

    m_actionHandler = new TextEditor::TextEditorActionHandler(QmlJSEditor::Constants::C_QMLJSEDITOR_ID,
          TextEditor::TextEditorActionHandler::Format
        | TextEditor::TextEditorActionHandler::UnCommentSelection
        | TextEditor::TextEditorActionHandler::UnCollapseAll);
    m_actionHandler->initializeActions();

    Core::ActionManager *am =  core->actionManager();
    Core::ActionContainer *contextMenu = am->createMenu(QmlJSEditor::Constants::M_CONTEXT);

    Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);
    Core::ActionContainer *menuQtQuick = am->createMenu(Constants::M_QTQUICK);
    menuQtQuick->menu()->setTitle(tr("Qt Quick"));
    mtools->addMenu(menuQtQuick);
    m_actionPreview = new QAction("&Preview", this);

    QList<int> toolsMenuContext = QList<int>()
                                  << core->uniqueIDManager()->uniqueIdentifier(QmlDesigner::Constants::C_QT_QUICK_TOOLS_MENU);
    Core::Command *cmd = addToolAction(m_actionPreview,  am, toolsMenuContext,
                   QLatin1String("QtQuick.Preview"), menuQtQuick, tr("Ctrl+Alt+R"));
    connect(cmd->action(), SIGNAL(triggered()), SLOT(openPreview()));

    m_previewRunner = new QmlJSPreviewRunner(this);
    m_actionPreview->setEnabled(m_previewRunner->isReady());

    QAction *followSymbolUnderCursorAction = new QAction(tr("Follow Symbol Under Cursor"), this);
    cmd = am->registerAction(followSymbolUnderCursorAction, Constants::FOLLOW_SYMBOL_UNDER_CURSOR, context);
    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
    connect(followSymbolUnderCursorAction, SIGNAL(triggered()), this, SLOT(followSymbolUnderCursor()));
    contextMenu->addAction(cmd);

    cmd = am->command(TextEditor::Constants::AUTO_INDENT_SELECTION);
    contextMenu->addAction(cmd);

    cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
    contextMenu->addAction(cmd);

    CodeCompletion *completion = new CodeCompletion(m_modelManager);
    addAutoReleasedObject(completion);

    addAutoReleasedObject(new HoverHandler);

    // Set completion settings and keep them up to date
    TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
    completion->setCompletionSettings(textEditorSettings->completionSettings());
    connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
            completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));

    error_message->clear();

    Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
    iconProvider->registerIconOverlayForSuffix(QIcon(":/qmljseditor/images/qmlfile.png"), "qml");

    return true;
}

void QmlJSEditorPlugin::extensionsInitialized()
{
}

void QmlJSEditorPlugin::openPreview()
{
    Core::EditorManager *em = Core::EditorManager::instance();

    if (em->currentEditor() && em->currentEditor()->id() == Constants::C_QMLJSEDITOR_ID)
        m_previewRunner->run(em->currentEditor()->file()->fileName());

}

void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor *editor)
{
    QTC_ASSERT(m_instance, /**/);

    m_actionHandler->setupActions(editor);

    TextEditor::TextEditorSettings::instance()->initializeEditor(editor);

    // auto completion
    connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
            TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
}

void QmlJSEditorPlugin::followSymbolUnderCursor()
{
    Core::EditorManager *em = Core::EditorManager::instance();

    if (QmlJSTextEditor *editor = qobject_cast<QmlJSTextEditor*>(em->currentEditor()->widget()))
        editor->followSymbolUnderCursor();
}

Core::Command *QmlJSEditorPlugin::addToolAction(QAction *a, Core::ActionManager *am,
                                          const QList<int> &context, const QString &name,
                                          Core::ActionContainer *c1, const QString &keySequence)
{
    Core::Command *command = am->registerAction(a, name, context);
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
    c1->addAction(command);
    return command;
}

Q_EXPORT_PLUGIN(QmlJSEditorPlugin)
<commit_msg>Fixed untranslated string<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmljseditorplugin.h"
#include "qmljshighlighter.h"
#include "qmljseditor.h"
#include "qmljseditorconstants.h"
#include "qmljseditorfactory.h"
#include "qmljscodecompletion.h"
#include "qmljshoverhandler.h"
#include "qmljsmodelmanager.h"
#include "qmlfilewizard.h"
#include "qmljspreviewrunner.h"

#include <qmldesigner/qmldesignerconstants.h>

#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/uniqueidmanager.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/fontsettings.h>
#include <texteditor/storagesettings.h>
#include <texteditor/texteditorconstants.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/textfilewizard.h>
#include <texteditor/texteditoractionhandler.h>
#include <texteditor/completionsupport.h>
#include <utils/qtcassert.h>

#include <QtCore/QtPlugin>
#include <QtCore/QDebug>
#include <QtCore/QSettings>
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
#include <QtGui/QMenu>
#include <QtGui/QAction>

using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
using namespace QmlJSEditor::Constants;

QmlJSEditorPlugin *QmlJSEditorPlugin::m_instance = 0;

QmlJSEditorPlugin::QmlJSEditorPlugin() :
        m_modelManager(0),
    m_wizard(0),
    m_editor(0),
    m_actionHandler(0)
{
    m_instance = this;
}

QmlJSEditorPlugin::~QmlJSEditorPlugin()
{
    removeObject(m_editor);
    delete m_actionHandler;
    m_instance = 0;
}

bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *error_message)
{
    Core::ICore *core = Core::ICore::instance();
    if (!core->mimeDatabase()->addMimeTypes(QLatin1String(":/qmljseditor/QmlJSEditor.mimetypes.xml"), error_message))
        return false;

    m_modelManager = new ModelManager(this);
    addAutoReleasedObject(m_modelManager);

    QList<int> context;
    context << core->uniqueIDManager()->uniqueIdentifier(QmlJSEditor::Constants::C_QMLJSEDITOR_ID)
            << core->uniqueIDManager()->uniqueIdentifier(QmlDesigner::Constants::C_QT_QUICK_TOOLS_MENU);

    m_editor = new QmlJSEditorFactory(this);
    addObject(m_editor);

    Core::BaseFileWizardParameters wizardParameters(Core::IWizard::FileWizard);
    wizardParameters.setCategory(QLatin1String(Core::Constants::WIZARD_CATEGORY_QT));
    wizardParameters.setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::WIZARD_TR_CATEGORY_QT));
    wizardParameters.setDescription(tr("Creates a Qt QML file."));
    wizardParameters.setDisplayName(tr("Qt QML File"));
    wizardParameters.setId(QLatin1String("Q.Qml"));
    addAutoReleasedObject(new QmlFileWizard(wizardParameters, core));

    m_actionHandler = new TextEditor::TextEditorActionHandler(QmlJSEditor::Constants::C_QMLJSEDITOR_ID,
          TextEditor::TextEditorActionHandler::Format
        | TextEditor::TextEditorActionHandler::UnCommentSelection
        | TextEditor::TextEditorActionHandler::UnCollapseAll);
    m_actionHandler->initializeActions();

    Core::ActionManager *am =  core->actionManager();
    Core::ActionContainer *contextMenu = am->createMenu(QmlJSEditor::Constants::M_CONTEXT);

    Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);
    Core::ActionContainer *menuQtQuick = am->createMenu(Constants::M_QTQUICK);
    menuQtQuick->menu()->setTitle(tr("Qt Quick"));
    mtools->addMenu(menuQtQuick);
    m_actionPreview = new QAction(tr("&Preview"), this);

    QList<int> toolsMenuContext = QList<int>()
                                  << core->uniqueIDManager()->uniqueIdentifier(QmlDesigner::Constants::C_QT_QUICK_TOOLS_MENU);
    Core::Command *cmd = addToolAction(m_actionPreview,  am, toolsMenuContext,
                   QLatin1String("QtQuick.Preview"), menuQtQuick, tr("Ctrl+Alt+R"));
    connect(cmd->action(), SIGNAL(triggered()), SLOT(openPreview()));

    m_previewRunner = new QmlJSPreviewRunner(this);
    m_actionPreview->setEnabled(m_previewRunner->isReady());

    QAction *followSymbolUnderCursorAction = new QAction(tr("Follow Symbol Under Cursor"), this);
    cmd = am->registerAction(followSymbolUnderCursorAction, Constants::FOLLOW_SYMBOL_UNDER_CURSOR, context);
    cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2));
    connect(followSymbolUnderCursorAction, SIGNAL(triggered()), this, SLOT(followSymbolUnderCursor()));
    contextMenu->addAction(cmd);

    cmd = am->command(TextEditor::Constants::AUTO_INDENT_SELECTION);
    contextMenu->addAction(cmd);

    cmd = am->command(TextEditor::Constants::UN_COMMENT_SELECTION);
    contextMenu->addAction(cmd);

    CodeCompletion *completion = new CodeCompletion(m_modelManager);
    addAutoReleasedObject(completion);

    addAutoReleasedObject(new HoverHandler);

    // Set completion settings and keep them up to date
    TextEditor::TextEditorSettings *textEditorSettings = TextEditor::TextEditorSettings::instance();
    completion->setCompletionSettings(textEditorSettings->completionSettings());
    connect(textEditorSettings, SIGNAL(completionSettingsChanged(TextEditor::CompletionSettings)),
            completion, SLOT(setCompletionSettings(TextEditor::CompletionSettings)));

    error_message->clear();

    Core::FileIconProvider *iconProvider = Core::FileIconProvider::instance();
    iconProvider->registerIconOverlayForSuffix(QIcon(":/qmljseditor/images/qmlfile.png"), "qml");

    return true;
}

void QmlJSEditorPlugin::extensionsInitialized()
{
}

void QmlJSEditorPlugin::openPreview()
{
    Core::EditorManager *em = Core::EditorManager::instance();

    if (em->currentEditor() && em->currentEditor()->id() == Constants::C_QMLJSEDITOR_ID)
        m_previewRunner->run(em->currentEditor()->file()->fileName());

}

void QmlJSEditorPlugin::initializeEditor(QmlJSEditor::Internal::QmlJSTextEditor *editor)
{
    QTC_ASSERT(m_instance, /**/);

    m_actionHandler->setupActions(editor);

    TextEditor::TextEditorSettings::instance()->initializeEditor(editor);

    // auto completion
    connect(editor, SIGNAL(requestAutoCompletion(TextEditor::ITextEditable*, bool)),
            TextEditor::Internal::CompletionSupport::instance(), SLOT(autoComplete(TextEditor::ITextEditable*, bool)));
}

void QmlJSEditorPlugin::followSymbolUnderCursor()
{
    Core::EditorManager *em = Core::EditorManager::instance();

    if (QmlJSTextEditor *editor = qobject_cast<QmlJSTextEditor*>(em->currentEditor()->widget()))
        editor->followSymbolUnderCursor();
}

Core::Command *QmlJSEditorPlugin::addToolAction(QAction *a, Core::ActionManager *am,
                                          const QList<int> &context, const QString &name,
                                          Core::ActionContainer *c1, const QString &keySequence)
{
    Core::Command *command = am->registerAction(a, name, context);
    if (!keySequence.isEmpty())
        command->setDefaultKeySequence(QKeySequence(keySequence));
    c1->addAction(command);
    return command;
}

Q_EXPORT_PLUGIN(QmlJSEditorPlugin)
<|endoftext|>


<commit_before>#include <possumwood_sdk/node_implementation.h>
#include <possumwood_sdk/app.h>

#include <GL/glew.h>
#include <GL/glu.h>

#include "datatypes/uniforms.inl"

namespace {

dependency_graph::InAttr<std::string> a_name;
dependency_graph::InAttr<std::shared_ptr<const QPixmap>> a_value;
dependency_graph::InAttr<std::shared_ptr<const possumwood::Uniforms>> a_inUniforms;
dependency_graph::OutAttr<std::shared_ptr<const possumwood::Uniforms>> a_outUniforms;

dependency_graph::State compute(dependency_graph::Values& data) {
	dependency_graph::State result;

	std::unique_ptr<possumwood::Uniforms> uniforms;

	std::shared_ptr<const possumwood::Uniforms> inUniforms = data.get(a_inUniforms);
	if(inUniforms != nullptr)
		uniforms = std::unique_ptr<possumwood::Uniforms>(new possumwood::Uniforms(*inUniforms));
	else
		uniforms = std::unique_ptr<possumwood::Uniforms>(new possumwood::Uniforms());

	std::shared_ptr<const QPixmap> value = data.get(a_value);

	if(value) {
		uniforms->addTexture(
			data.get(a_name),
			*value
		);
	}

	data.set(a_outUniforms, std::shared_ptr<const possumwood::Uniforms>(uniforms.release()));

	return result;
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_name, "name", std::string("texture"));
	meta.addAttribute(a_value, "value");
	meta.addAttribute(a_inUniforms, "in_uniforms");
	meta.addAttribute(a_outUniforms, "out_uniforms");

	meta.addInfluence(a_name, a_outUniforms);
	meta.addInfluence(a_value, a_outUniforms);
	meta.addInfluence(a_inUniforms, a_outUniforms);

	meta.setCompute(&compute);
}

possumwood::NodeImplementation s_impl("render/uniforms/texture", init);

}
<commit_msg>Changed the default name of texture uniform to "image", not to conflict with GLSL texture keyword<commit_after>#include <possumwood_sdk/node_implementation.h>
#include <possumwood_sdk/app.h>

#include <GL/glew.h>
#include <GL/glu.h>

#include "datatypes/uniforms.inl"

namespace {

dependency_graph::InAttr<std::string> a_name;
dependency_graph::InAttr<std::shared_ptr<const QPixmap>> a_value;
dependency_graph::InAttr<std::shared_ptr<const possumwood::Uniforms>> a_inUniforms;
dependency_graph::OutAttr<std::shared_ptr<const possumwood::Uniforms>> a_outUniforms;

dependency_graph::State compute(dependency_graph::Values& data) {
	dependency_graph::State result;

	std::unique_ptr<possumwood::Uniforms> uniforms;

	std::shared_ptr<const possumwood::Uniforms> inUniforms = data.get(a_inUniforms);
	if(inUniforms != nullptr)
		uniforms = std::unique_ptr<possumwood::Uniforms>(new possumwood::Uniforms(*inUniforms));
	else
		uniforms = std::unique_ptr<possumwood::Uniforms>(new possumwood::Uniforms());

	std::shared_ptr<const QPixmap> value = data.get(a_value);

	if(value) {
		uniforms->addTexture(
			data.get(a_name),
			*value
		);
	}

	data.set(a_outUniforms, std::shared_ptr<const possumwood::Uniforms>(uniforms.release()));

	return result;
}

void init(possumwood::Metadata& meta) {
	meta.addAttribute(a_name, "name", std::string("image"));
	meta.addAttribute(a_value, "value");
	meta.addAttribute(a_inUniforms, "in_uniforms");
	meta.addAttribute(a_outUniforms, "out_uniforms");

	meta.addInfluence(a_name, a_outUniforms);
	meta.addInfluence(a_value, a_outUniforms);
	meta.addInfluence(a_inUniforms, a_outUniforms);

	meta.setCompute(&compute);
}

possumwood::NodeImplementation s_impl("render/uniforms/texture", init);

}
<|endoftext|>


<commit_before>#include "board.hpp"

#include <cstring>

#include <boost/lexical_cast.hpp>

#include "exception.hpp"
#include "walk_move.hpp"

namespace Quoridor {

Board::Board(int row_num, int col_num)
    : sides_(), pawn_sides_(), walls_(), occ_nodes_(), pawn_nodes_(), bg_()
{
    set_size(row_num, col_num);

    sides_.push_back(std::pair<int, int>(0, 0));
    sides_.push_back(std::pair<int, int>(2, 0));
    sides_.push_back(std::pair<int, int>(1, 0));
    sides_.push_back(std::pair<int, int>(3, 0));
}

Board::~Board()
{
}

void Board::set_size(int row_num, int col_num)
{
    if (row_num <= 0) {
        throw Exception("illegal row number: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num <= 0) {
        throw Exception("illegal column number: "
                + boost::lexical_cast<std::string>(col_num));
    }
    if (row_num % 2 == 0) {
        throw Exception("row number must be odd: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num % 2 == 0) {
        throw Exception("column number must be odd: "
                + boost::lexical_cast<std::string>(col_num));
    }

    row_num_ = row_num;
    col_num_ = col_num;

    bg_.set_size(row_num_, col_num_);
}

int Board::next_side() const
{
    for (auto &side : sides_) {
        if (side.second == 0) {
            side.second = 1;
            return side.first;
        }
    }
    return -1;
}

int Board::add_pawn(std::shared_ptr<Pawn> pawn)
{
    pawn_sides_[pawn] = next_side();
    int n;

    switch (pawn_sides_[pawn]) {
    case 0:
        n = col_num_ / 2;
        break;
    case 1:
        n = (row_num_ / 2) * col_num_;
        break;
    case 2:
        n = (row_num_ - 1) * col_num_ + col_num_ / 2;
        break;
    case 3:
        n = (row_num_ / 2) * col_num_ + col_num_ - 1;
        break;
    default:
        throw Exception("invalid pawn side: "
                + boost::lexical_cast<std::string>(pawn_sides_[pawn]));
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;

    return 0;
}

bool Board::is_occupied(int node) const
{
    return occ_nodes_.find(node) != occ_nodes_.end();
}

pos_t Board::pawn_pos(std::shared_ptr<Pawn> pawn) const
{
    int node = pawn_nodes_.at(pawn);
    pos_t pos;
    pos.row = row(node);
    pos.col = col(node);
    return pos;
}

bool Board::is_at_opposite_side(std::shared_ptr<Pawn> pawn) const
{
    int n = pawn_nodes_.at(pawn);
    switch (pawn_sides_.at(pawn)) {
    case 0:
        return row(n) == row_num_ - 1;
    case 1:
        return col(n) == col_num_ - 1;
    case 2:
        return row(n) == 0;
    case 3:
        return col(n) == 0;
    default:
        throw Exception("invalid board side: "
                + boost::lexical_cast<std::string>(pawn_sides_.at(pawn)));
    }
}

int Board::make_walking_move(std::shared_ptr<Pawn> pawn, int goal_node)
{
    int cur_node = pawn_nodes_[pawn];

    if (!is_possible_move(cur_node, goal_node)) {
        return -1;
    }

    // update pawn's position
    occ_nodes_.erase(pawn_nodes_[pawn]);
    bg_.unblock_neighbours(pawn_nodes_[pawn]);
    pawn_nodes_[pawn] = goal_node;
    occ_nodes_[goal_node] = pawn;
    bg_.block_neighbours(goal_node);

    return 0;
}

int Board::add_wall(const Wall &wall)
{
    if (try_add_wall(wall) < 0) {
        return -1;
    }

    walls_[wall.orientation()][wall.line()].insert(std::map<int, Wall>::value_type(wall.start_pos(), Wall(wall)));

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * col_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * col_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }
        bg_.remove_edges(node1, node2);
    }

    return 0;
}

int Board::try_add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() > start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    bg_.reset_filters();

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * col_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * col_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }

        bg_.filter_edges(node1, node2);
    }

    bool path_blocked = false;

    for (auto pawn_node : pawn_nodes_) {
        std::vector<int> nodes;
        int side = (pawn_sides_[pawn_node.first] + 2) % 4;
        path_blocked = true;

        side_nodes(side, &nodes);
        for (auto node : nodes) {
            if (bg_.is_path_exists(pawn_node.second, node)) {
                path_blocked = false;
                break;
            }
        }

        /* wall blocks all pathes to the opposite side for one of pawns */
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

bool Board::is_possible_move(int cur_node, int goal_node) const
{
    return bg_.is_neighbours(cur_node, goal_node);
}

bool Board::wall_intersects(const Wall &wall) const
{
    // check intersections
    if (walls_.count(1 - wall.orientation()) > 0) {
        for (int i = 0; i < wall.cnt() - 1; ++i) {
            // there are walls on the intersected line
            if (walls_.at(1 - wall.orientation()).count(wall.start_pos()) != 0) {
                auto line_walls = walls_.at(1 - wall.orientation()).at(wall.start_pos() + i);
                auto it = line_walls.upper_bound(wall.line());

                // all walls on the line are settled before new wall
                if (it == line_walls.end()) {
                    auto rit = line_walls.rbegin();
                    if (rit->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
                else if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
            }
        }
    }

    // check overlaps
    if (walls_.count(wall.orientation()) > 0) {
        if (walls_.at(wall.orientation()).count(wall.line()) != 0) {
            auto line_walls = walls_.at(wall.orientation()).at(wall.line());
            auto it = line_walls.upper_bound(wall.start_pos());

            // all walls on the line are settled before new wall
            if (it == line_walls.end()) {
                auto rit = line_walls.rbegin();
                if (rit->second.end_pos() >= wall.start_pos()) {
                    return true;
                }
            }
            else {
                // check if new wall overlaps over next wall on the line
                if (wall.end_pos() >= it->second.start_pos()) {
                    return true;
                }

                if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.start_pos()) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

void Board::side_nodes(int side, std::vector<int> *nodes) const
{
    switch (side) {
    case 0:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back(i);
        }
        break;
    case 1:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_);
        }
        break;
    case 2:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back((row_num_ - 1 ) * col_num_ + i);
        }
        break;
    case 3:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_ + col_num_ - 1);
        }
        break;
    default:
        break;
    }
}

}  /* namespace Quoridor */
<commit_msg>Block neighbours of pawn init nodes.<commit_after>#include "board.hpp"

#include <cstring>

#include <boost/lexical_cast.hpp>

#include "exception.hpp"
#include "walk_move.hpp"

namespace Quoridor {

Board::Board(int row_num, int col_num)
    : sides_(), pawn_sides_(), walls_(), occ_nodes_(), pawn_nodes_(), bg_()
{
    set_size(row_num, col_num);

    sides_.push_back(std::pair<int, int>(0, 0));
    sides_.push_back(std::pair<int, int>(2, 0));
    sides_.push_back(std::pair<int, int>(1, 0));
    sides_.push_back(std::pair<int, int>(3, 0));
}

Board::~Board()
{
}

void Board::set_size(int row_num, int col_num)
{
    if (row_num <= 0) {
        throw Exception("illegal row number: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num <= 0) {
        throw Exception("illegal column number: "
                + boost::lexical_cast<std::string>(col_num));
    }
    if (row_num % 2 == 0) {
        throw Exception("row number must be odd: "
                + boost::lexical_cast<std::string>(row_num));
    }
    if (col_num % 2 == 0) {
        throw Exception("column number must be odd: "
                + boost::lexical_cast<std::string>(col_num));
    }

    row_num_ = row_num;
    col_num_ = col_num;

    bg_.set_size(row_num_, col_num_);
}

int Board::next_side() const
{
    for (auto &side : sides_) {
        if (side.second == 0) {
            side.second = 1;
            return side.first;
        }
    }
    return -1;
}

int Board::add_pawn(std::shared_ptr<Pawn> pawn)
{
    pawn_sides_[pawn] = next_side();
    int n;

    switch (pawn_sides_[pawn]) {
    case 0:
        n = col_num_ / 2;
        break;
    case 1:
        n = (row_num_ / 2) * col_num_;
        break;
    case 2:
        n = (row_num_ - 1) * col_num_ + col_num_ / 2;
        break;
    case 3:
        n = (row_num_ / 2) * col_num_ + col_num_ - 1;
        break;
    default:
        throw Exception("invalid pawn side: "
                + boost::lexical_cast<std::string>(pawn_sides_[pawn]));
    }

    occ_nodes_[n] = pawn;
    pawn_nodes_[pawn] = n;

    bg_.block_neighbours(n);

    return 0;
}

bool Board::is_occupied(int node) const
{
    return occ_nodes_.find(node) != occ_nodes_.end();
}

pos_t Board::pawn_pos(std::shared_ptr<Pawn> pawn) const
{
    int node = pawn_nodes_.at(pawn);
    pos_t pos;
    pos.row = row(node);
    pos.col = col(node);
    return pos;
}

bool Board::is_at_opposite_side(std::shared_ptr<Pawn> pawn) const
{
    int n = pawn_nodes_.at(pawn);
    switch (pawn_sides_.at(pawn)) {
    case 0:
        return row(n) == row_num_ - 1;
    case 1:
        return col(n) == col_num_ - 1;
    case 2:
        return row(n) == 0;
    case 3:
        return col(n) == 0;
    default:
        throw Exception("invalid board side: "
                + boost::lexical_cast<std::string>(pawn_sides_.at(pawn)));
    }
}

int Board::make_walking_move(std::shared_ptr<Pawn> pawn, int goal_node)
{
    int cur_node = pawn_nodes_[pawn];

    if (!is_possible_move(cur_node, goal_node)) {
        return -1;
    }

    // update pawn's position
    occ_nodes_.erase(pawn_nodes_[pawn]);
    bg_.unblock_neighbours(pawn_nodes_[pawn]);
    pawn_nodes_[pawn] = goal_node;
    occ_nodes_[goal_node] = pawn;
    bg_.block_neighbours(goal_node);

    return 0;
}

int Board::add_wall(const Wall &wall)
{
    if (try_add_wall(wall) < 0) {
        return -1;
    }

    walls_[wall.orientation()][wall.line()].insert(std::map<int, Wall>::value_type(wall.start_pos(), Wall(wall)));

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * col_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * col_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }
        bg_.remove_edges(node1, node2);
    }

    return 0;
}

int Board::try_add_wall(const Wall &wall)
{
    int line_lim = (wall.orientation() ? col_num() : row_num()) - 1;
    int start_pos_lim = (wall.orientation() ? row_num() : col_num()) - 1;
    if ((wall.line() >= line_lim)
            || (wall.end_pos() > start_pos_lim)) {
        return -1;
    }

    if (wall_intersects(wall)) {
        return -1;
    }

    bg_.reset_filters();

    int node1;
    int node2;
    for (int i = 0; i < wall.cnt(); ++i) {
        if (wall.orientation() == 0) {
            node1 = wall.line() * col_num_ + wall.start_pos() + i;
            node2 = (wall.line() + 1) * col_num_ + wall.start_pos() + i;
        }
        else {
            node1 = (wall.start_pos() + i) * row_num_ + wall.line();
            node2 = (wall.start_pos() + i) * row_num_ + wall.line() + 1;
        }

        bg_.filter_edges(node1, node2);
    }

    bool path_blocked = false;

    for (auto pawn_node : pawn_nodes_) {
        std::vector<int> nodes;
        int side = (pawn_sides_[pawn_node.first] + 2) % 4;
        path_blocked = true;

        side_nodes(side, &nodes);
        for (auto node : nodes) {
            if (bg_.is_path_exists(pawn_node.second, node)) {
                path_blocked = false;
                break;
            }
        }

        /* wall blocks all pathes to the opposite side for one of pawns */
        if (path_blocked) {
            break;
        }
    }

    if (path_blocked) {
        return -1;
    }

    return 0;
}

bool Board::is_possible_move(int cur_node, int goal_node) const
{
    return bg_.is_neighbours(cur_node, goal_node);
}

bool Board::wall_intersects(const Wall &wall) const
{
    // check intersections
    if (walls_.count(1 - wall.orientation()) > 0) {
        for (int i = 0; i < wall.cnt() - 1; ++i) {
            // there are walls on the intersected line
            if (walls_.at(1 - wall.orientation()).count(wall.start_pos()) != 0) {
                auto line_walls = walls_.at(1 - wall.orientation()).at(wall.start_pos() + i);
                auto it = line_walls.upper_bound(wall.line());

                // all walls on the line are settled before new wall
                if (it == line_walls.end()) {
                    auto rit = line_walls.rbegin();
                    if (rit->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
                else if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.line()) {
                        return true;
                    }
                }
            }
        }
    }

    // check overlaps
    if (walls_.count(wall.orientation()) > 0) {
        if (walls_.at(wall.orientation()).count(wall.line()) != 0) {
            auto line_walls = walls_.at(wall.orientation()).at(wall.line());
            auto it = line_walls.upper_bound(wall.start_pos());

            // all walls on the line are settled before new wall
            if (it == line_walls.end()) {
                auto rit = line_walls.rbegin();
                if (rit->second.end_pos() >= wall.start_pos()) {
                    return true;
                }
            }
            else {
                // check if new wall overlaps over next wall on the line
                if (wall.end_pos() >= it->second.start_pos()) {
                    return true;
                }

                if (it != line_walls.begin()) {
                    --it;
                    if (it->second.end_pos() >= wall.start_pos()) {
                        return true;
                    }
                }
            }
        }
    }

    return false;
}

void Board::side_nodes(int side, std::vector<int> *nodes) const
{
    switch (side) {
    case 0:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back(i);
        }
        break;
    case 1:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_);
        }
        break;
    case 2:
        for (int i = 0; i < col_num_; ++i) {
            nodes->push_back((row_num_ - 1 ) * col_num_ + i);
        }
        break;
    case 3:
        for (int i = 0; i < row_num_; ++i) {
            nodes->push_back(i * col_num_ + col_num_ - 1);
        }
        break;
    default:
        break;
    }
}

}  /* namespace Quoridor */
<|endoftext|>


<commit_before>#include "party.h"
#include "user.h"
#include "ccharserver.h"
#include "logconsole.h"

#include "srv_party_req.h"
#include "srv_party_reply.h"

std::shared_ptr<Party> cache_fetch_party(uint32_t charId) {
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};
  Core::PartyMembersTable partyMembersTable{};

  auto res = conn(sqlpp::select(sqlpp::all_of(partyTable)).from(
    partyMembersTable.join(partyTable).on(partyMembersTable.id == partyTable.id))
                  .where(partyMembersTable.memberId == charId));

  if (res.empty()) {
    return {};
  }
  auto& result = res.front();

  Party party;
  party.id = result.id;
  party.name = result.name;
  party.leader = result.leaderId;
  party.options = result.options;
  party.level = result.level;
  party.last_got_item_index = result.lastGotItemIndex;
  party.last_got_zuly_index = result.lastGotZulyIndex;
  party.last_got_etc_index = result.lastGotEtcIndex;

  // now we fetch all party members
  auto res2 = conn(sqlpp::select(partyMembersTable.memberId).from(partyMembersTable)
                   .where(partyMembersTable.id == party.id).order_by(partyMembersTable.rank.desc()));

  if (res2.empty()) {
    return {};
  }

  for (const auto& r : res2) {
    party.members.push_back(r.memberId);
  }

  return std::make_shared<Party>(party);
}

void cache_create_party(std::shared_ptr<Party> party) {
  if (!party) return;

  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::insert_into(partyTable)
       .set(partyTable.name = party->name,
       partyTable.leaderId = party->leader,
       partyTable.options = party->options,
       partyTable.level = party->level,
       partyTable.lastGotItemIndex = party->last_got_item_index,
       partyTable.lastGotEtcIndex = party->last_got_etc_index,
       partyTable.lastGotZulyIndex = party->last_got_zuly_index));

  auto res = conn(sqlpp::select(partyTable.id).from(partyTable)
          .where(partyTable.leaderId == party->leader));

  if (res.empty()) {
      return;
  }

  party->id = res.front().id;
}

void cache_write_party(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::update(partyTable)
       .set(partyTable.name = party->name,
       partyTable.leaderId = party->leader,
       partyTable.options = party->options,
       partyTable.level = party->level,
       partyTable.lastGotItemIndex = party->last_got_item_index,
       partyTable.lastGotEtcIndex = party->last_got_etc_index,
       partyTable.lastGotZulyIndex = party->last_got_zuly_index)
       .where(partyTable.id == party->id));
}

void cache_write_party_members(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyMembersTable partyMembersTable{};

  conn(sqlpp::remove_from(partyMembersTable).where(partyMembersTable.id == party->id));
  auto insert = sqlpp::insert_into(partyMembersTable).columns(partyMembersTable.id, partyMembersTable.memberId);
  for (auto m : party-> members) {
    insert.values.add(partyMembersTable.id = party->id, partyMembersTable.memberId = m);
  }
  conn(insert);
}

void cache_remove_party(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::remove_from(partyTable).where(partyTable.id == party->id));
}

std::shared_ptr<Party> PartyManager::get_party(uint32_t charId) {
    if (partys.count(charId) != 0) {
        return partys.at(charId);
    }
    auto party = cache_fetch_party(charId);
    if (!party) { // no party!
        return {};
    }
    partys.insert({charId, party});

    for (auto m : party->members) {
        partys.insert({m, party});
    }
    return party;
}

std::shared_ptr<Party> PartyManager::create_party(uint32_t charId) {
    auto party = std::make_shared<Party>();
    party->members.push_back(charId);
    party->leader = charId;
    cache_create_party(party);
    cache_write_party_members(party);
    party->members.push_back(charId);
    partys[charId] = party;
    return party;
}

void PartyManager::add_member_to_party(std::shared_ptr<Party> party, uint32_t member) {
    party->members.push_back(member);
    partys.insert({member, party});

    cache_write_party_members(party);
}

void PartyManager::remove_member_from_party(std::shared_ptr<Party> party, uint32_t member) {
    party->members.erase(std::remove(party->members.begin(), party->members.end(), member), party->members.end());
    partys.erase(member);

    if (party->members.empty()) {
        cache_remove_party(party);
    } else {
        cache_write_party_members(party);
    }
}

void PartyManager::remove_party(std::shared_ptr<Party> party) {
    for (auto member : party->members) {
        partys.erase(member);
    }
    cache_remove_party(party);
}

PartyManager::~PartyManager() {
    for (const auto& [_, party] : partys) {
        remove_party(party);
    }
}

void party_request(const RoseCommon::Packet::CliPartyReq& packet, CCharServer& server, User& user) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("party_request({})", user.get_name());

    using namespace RoseCommon::Packet;
    switch (packet.get_type()) {
        case CliPartyReq::CREATE: // idXorTag == id
        {
            auto other = server.get_user(packet.get_target(), user.get_mapId());
            if (!other) {
              logger->warn("User ({}, {}) doesn't exist", packet.get_target(), user.get_mapId());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to make a party with {}", user.get_name(), other.value()->get_name());
            if (user.get_party()) {
                logger->error("{} wants to make a party but is already in a party", user.get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, user.get_entityId()));
                return;
            }
            if (user.get_requested_party()) {
                logger->warn("user {} got another pending party request", user.get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::BUSY, user.get_entityId()));
                return;
            }
            if (other.value()->get_requested_party()) {
                logger->warn("user {} got another pending party request", other.value()->get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::BUSY, other.value()->get_entityId()));
                return;
            }
            if (other.value()->get_party()) {
                logger->debug("{} wants to make a party with {} which is already in a party", user.get_name(), other.value()->get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, other.value()->get_entityId()));
                return;
            }
            // TODO: check for level difference
            other.value()->set_requested_party(server.create_party(user));
            server.send_char(*other.value(), SrvPartyReq::create(SrvPartyReq::CREATE, user.get_entityId()));
            break;
        }
        case CliPartyReq::JOIN: // idXorTag == id
        {
            auto other = server.get_user(packet.get_target(), user.get_mapId());
            if (!other) {
              logger->warn("User ({}, {}) doesn't exist", packet.get_target(), user.get_mapId());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to join {}'s party", user.get_name(), other.value()->get_name());
            break;
        }
        case CliPartyReq::LEAVE: // idXorTag == tag
        {
            logger->debug("{} left the party", user.get_name());
            break;
        }
        case CliPartyReq::CHANGE_OWNER: // idXorTag == tag
        {
            auto other = server.get_user(packet.get_target());
            if (!other) {
              logger->warn("User {} doesn't exist", packet.get_target());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to make {} the owner", user.get_name(), other.value()->get_name());
            break;
        }
        case CliPartyReq::BAN: // idXorTag == tag
        {
            auto other = server.get_user(packet.get_target());
            if (!other) {
              logger->warn("User {} doesn't exist", packet.get_target());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to kick {}", user.get_name(), other.value()->get_name());
            break;
        }
        default:
            logger->warn("Client {} sent a non valid request code {}", user.get_name(), packet.get_target());
    }
}

void party_reply(const RoseCommon::Packet::CliPartyReply& packet, CCharServer& server, User& user) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("party_reply({})", user.get_name());

    auto tmp = server.get_user(packet.get_target(), user.get_mapId());
    if (!tmp) {
        logger->warn("Client {} replied to a party request of the non existing char {}", user.get_name(), packet.get_target());
        server.send_char(user, RoseCommon::Packet::SrvPartyReply::create(RoseCommon::Packet::SrvPartyReply::NOT_FOUND, packet.get_target()));
        return;
    }
    User*const other = tmp.value();
    if (!other->get_party()) {
        logger->warn("no party found for character {}", other->get_name());
        return;
    }

    using namespace RoseCommon::Packet;
    switch (packet.get_type()) {
        case CliPartyReply::BUSY:
            logger->debug("{} is too busy to accept {}'s party", user.get_name(), other->get_name());
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::BUSY, user.get_entityId()));
            break;
        case CliPartyReply::REJECT_JOIN:
            logger->debug("{} refused {}'s party", user.get_name(), other->get_name());
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, user.get_entityId()));
            break;
        case CliPartyReply::ACCEPT_CREATE:
        case CliPartyReply::ACCEPT_JOIN:
            logger->debug("{} accepted {}'s party", user.get_name(), other->get_name());
            if (user.get_requested_party() != other->get_party()) {
                logger->warn("{} tried to answer to a different party request from {}", user.get_name(), other->get_name());
                user.set_requested_party({}); // we reset the party request
                return;
            }
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::ACCEPT_JOIN, user.get_entityId()));
            server.add_user_to_party(user, other->get_party());
            break;
        default:
            logger->debug("{} replied {} to {}", user.get_name(), packet.get_type(), other->get_name());
            break;
    }
}
<commit_msg>Fix small segfault<commit_after>#include "party.h"
#include "user.h"
#include "ccharserver.h"
#include "logconsole.h"

#include "srv_party_req.h"
#include "srv_party_reply.h"

#include <unordered_set>

std::shared_ptr<Party> cache_fetch_party(uint32_t charId) {
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};
  Core::PartyMembersTable partyMembersTable{};

  auto res = conn(sqlpp::select(sqlpp::all_of(partyTable)).from(
    partyMembersTable.join(partyTable).on(partyMembersTable.id == partyTable.id))
                  .where(partyMembersTable.memberId == charId));

  if (res.empty()) {
    return {};
  }
  auto& result = res.front();

  Party party;
  party.id = result.id;
  party.name = result.name;
  party.leader = result.leaderId;
  party.options = result.options;
  party.level = result.level;
  party.last_got_item_index = result.lastGotItemIndex;
  party.last_got_zuly_index = result.lastGotZulyIndex;
  party.last_got_etc_index = result.lastGotEtcIndex;

  // now we fetch all party members
  auto res2 = conn(sqlpp::select(partyMembersTable.memberId).from(partyMembersTable)
                   .where(partyMembersTable.id == party.id).order_by(partyMembersTable.rank.desc()));

  if (res2.empty()) {
    return {};
  }

  for (const auto& r : res2) {
    party.members.push_back(r.memberId);
  }

  return std::make_shared<Party>(party);
}

void cache_create_party(std::shared_ptr<Party> party) {
  if (!party) return;

  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::insert_into(partyTable)
       .set(partyTable.name = party->name,
       partyTable.leaderId = party->leader,
       partyTable.options = party->options,
       partyTable.level = party->level,
       partyTable.lastGotItemIndex = party->last_got_item_index,
       partyTable.lastGotEtcIndex = party->last_got_etc_index,
       partyTable.lastGotZulyIndex = party->last_got_zuly_index));

  auto res = conn(sqlpp::select(partyTable.id).from(partyTable)
          .where(partyTable.leaderId == party->leader));

  if (res.empty()) {
      return;
  }

  party->id = res.front().id;
}

void cache_write_party(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::update(partyTable)
       .set(partyTable.name = party->name,
       partyTable.leaderId = party->leader,
       partyTable.options = party->options,
       partyTable.level = party->level,
       partyTable.lastGotItemIndex = party->last_got_item_index,
       partyTable.lastGotEtcIndex = party->last_got_etc_index,
       partyTable.lastGotZulyIndex = party->last_got_zuly_index)
       .where(partyTable.id == party->id));
}

void cache_write_party_members(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyMembersTable partyMembersTable{};

  conn(sqlpp::remove_from(partyMembersTable).where(partyMembersTable.id == party->id));
  auto insert = sqlpp::insert_into(partyMembersTable).columns(partyMembersTable.id, partyMembersTable.memberId);
  for (auto m : party-> members) {
    insert.values.add(partyMembersTable.id = party->id, partyMembersTable.memberId = m);
  }
  conn(insert);
}

void cache_remove_party(std::shared_ptr<Party> party) {
  if (!party) return;
  auto conn = Core::connectionPool.getConnection<Core::Osirose>();
  Core::PartyTable partyTable{};

  conn(sqlpp::remove_from(partyTable).where(partyTable.id == party->id));
}

std::shared_ptr<Party> PartyManager::get_party(uint32_t charId) {
    if (partys.count(charId) != 0) {
        return partys.at(charId);
    }
    auto party = cache_fetch_party(charId);
    if (!party) { // no party!
        return {};
    }
    partys.insert({charId, party});

    for (auto m : party->members) {
        partys.insert({m, party});
    }
    return party;
}

std::shared_ptr<Party> PartyManager::create_party(uint32_t charId) {
    auto party = std::make_shared<Party>();
    party->members.push_back(charId);
    party->leader = charId;
    cache_create_party(party);
    cache_write_party_members(party);
    party->members.push_back(charId);
    partys[charId] = party;
    return party;
}

void PartyManager::add_member_to_party(std::shared_ptr<Party> party, uint32_t member) {
    party->members.push_back(member);
    partys.insert({member, party});

    cache_write_party_members(party);
}

void PartyManager::remove_member_from_party(std::shared_ptr<Party> party, uint32_t member) {
    party->members.erase(std::remove(party->members.begin(), party->members.end(), member), party->members.end());
    partys.erase(member);

    if (party->members.empty()) {
        cache_remove_party(party);
    } else {
        cache_write_party_members(party);
    }
}

void PartyManager::remove_party(std::shared_ptr<Party> party) {
    for (auto member : party->members) {
        partys.erase(member);
    }
    cache_remove_party(party);
}

PartyManager::~PartyManager() {
    std::unordered_set<std::shared_ptr<Party>> tmp;
    for (const auto& [_, party] : partys) {
        tmp.insert(party);
    }
    for (const auto& party : tmp) {
        cache_remove_party(party);
    }
}

void party_request(const RoseCommon::Packet::CliPartyReq& packet, CCharServer& server, User& user) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("party_request({})", user.get_name());

    using namespace RoseCommon::Packet;
    switch (packet.get_type()) {
        case CliPartyReq::CREATE: // idXorTag == id
        {
            auto other = server.get_user(packet.get_target(), user.get_mapId());
            if (!other) {
              logger->warn("User ({}, {}) doesn't exist", packet.get_target(), user.get_mapId());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to make a party with {}", user.get_name(), other.value()->get_name());
            if (user.get_party()) {
                logger->error("{} wants to make a party but is already in a party", user.get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, user.get_entityId()));
                return;
            }
            if (user.get_requested_party()) {
                logger->warn("user {} got another pending party request", user.get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::BUSY, user.get_entityId()));
                return;
            }
            if (other.value()->get_requested_party()) {
                logger->warn("user {} got another pending party request", other.value()->get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::BUSY, other.value()->get_entityId()));
                return;
            }
            if (other.value()->get_party()) {
                logger->debug("{} wants to make a party with {} which is already in a party", user.get_name(), other.value()->get_name());
                server.send_char(user, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, other.value()->get_entityId()));
                return;
            }
            // TODO: check for level difference
            other.value()->set_requested_party(server.create_party(user));
            server.send_char(*other.value(), SrvPartyReq::create(SrvPartyReq::CREATE, user.get_entityId()));
            break;
        }
        case CliPartyReq::JOIN: // idXorTag == id
        {
            auto other = server.get_user(packet.get_target(), user.get_mapId());
            if (!other) {
              logger->warn("User ({}, {}) doesn't exist", packet.get_target(), user.get_mapId());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to join {}'s party", user.get_name(), other.value()->get_name());
            break;
        }
        case CliPartyReq::LEAVE: // idXorTag == tag
        {
            logger->debug("{} left the party", user.get_name());
            break;
        }
        case CliPartyReq::CHANGE_OWNER: // idXorTag == tag
        {
            auto other = server.get_user(packet.get_target());
            if (!other) {
              logger->warn("User {} doesn't exist", packet.get_target());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to make {} the owner", user.get_name(), other.value()->get_name());
            break;
        }
        case CliPartyReq::BAN: // idXorTag == tag
        {
            auto other = server.get_user(packet.get_target());
            if (!other) {
              logger->warn("User {} doesn't exist", packet.get_target());
              server.send_char(user, SrvPartyReply::create(SrvPartyReply::NOT_FOUND, packet.get_target()));
              return;
            }
            logger->debug("{} wants to kick {}", user.get_name(), other.value()->get_name());
            break;
        }
        default:
            logger->warn("Client {} sent a non valid request code {}", user.get_name(), packet.get_target());
    }
}

void party_reply(const RoseCommon::Packet::CliPartyReply& packet, CCharServer& server, User& user) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("party_reply({})", user.get_name());

    auto tmp = server.get_user(packet.get_target(), user.get_mapId());
    if (!tmp) {
        logger->warn("Client {} replied to a party request of the non existing char {}", user.get_name(), packet.get_target());
        server.send_char(user, RoseCommon::Packet::SrvPartyReply::create(RoseCommon::Packet::SrvPartyReply::NOT_FOUND, packet.get_target()));
        return;
    }
    User*const other = tmp.value();
    if (!other->get_party()) {
        logger->warn("no party found for character {}", other->get_name());
        return;
    }

    using namespace RoseCommon::Packet;
    switch (packet.get_type()) {
        case CliPartyReply::BUSY:
            logger->debug("{} is too busy to accept {}'s party", user.get_name(), other->get_name());
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::BUSY, user.get_entityId()));
            break;
        case CliPartyReply::REJECT_JOIN:
            logger->debug("{} refused {}'s party", user.get_name(), other->get_name());
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::REJECT_JOIN, user.get_entityId()));
            break;
        case CliPartyReply::ACCEPT_CREATE:
        case CliPartyReply::ACCEPT_JOIN:
            logger->debug("{} accepted {}'s party", user.get_name(), other->get_name());
            if (user.get_requested_party() != other->get_party()) {
                logger->warn("{} tried to answer to a different party request from {}", user.get_name(), other->get_name());
                user.set_requested_party({}); // we reset the party request
                return;
            }
            server.send_char(*other, SrvPartyReply::create(SrvPartyReply::ACCEPT_JOIN, user.get_entityId()));
            server.add_user_to_party(user, other->get_party());
            break;
        default:
            logger->debug("{} replied {} to {}", user.get_name(), packet.get_type(), other->get_name());
            break;
    }
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief chip::lowLevelInitialization() implementation for STM32F4
 *
 * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/lowLevelInitialization.hpp"

#include "distortos/chip/STM32F4-FLASH.hpp"
#include "distortos/chip/STM32F4-PWR.hpp"
#include "distortos/chip/STM32F4-RCC.hpp"
#include "distortos/chip/STM32F4-RCC-bits.h"

#include "distortos/architecture/ARMv6-M-ARMv7-M-configureSysTick.hpp"

#include "distortos/chip/CMSIS-proxy.h"

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

void lowLevelInitialization()
{
#ifdef CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE
	static_assert(CONFIG_CHIP_STM32F4_VDD_MV >= 2100,
			"Instruction prefetch must not be enabled when supply voltage is below 2.1V!");
	configureInstructionPrefetch(true);
#else	// !def CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE
	configureInstructionPrefetch(false);
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE

#ifdef CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE
	enableDataCache();
#else	// !def CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE
	disableDataCache();
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE
	enableInstructionCache();
#else	// !def CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE
	disableInstructionCache();
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	RCC_APB1ENR_PWREN_bb = 1;

	configureVoltageScaling(CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE);

#if (defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) || \
		defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) && \
		defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

	static_assert(CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE == 1, "Over-drive mode requires voltage scale 1 mode!");
	static_assert(CONFIG_CHIP_STM32F4_VDD_MV >= 2100,
			"Over-drive mode must not be enabled when supply voltage is below 2.1V!");
	enableOverDriveMode();
	constexpr uint8_t voltageScaleIndex {0};

#else	// !(defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) ||
		// defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) ||
		// !defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

	constexpr uint8_t voltageScaleIndex {CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE};

#endif	// !(defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) ||
		// defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) ||
		// !defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

#ifdef CONFIG_CHIP_STM32F4_RCC_HSE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	constexpr bool hseClockBypass {true};
#else	// !def CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	constexpr bool hseClockBypass {};
#endif	// !def CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	enableHse(hseClockBypass);

#endif	// def CONFIG_CHIP_STM32F4_RCC_HSE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_RCC_PLL_ENABLE

#if defined(CONFIG_CHIP_STM32F4_RCC_PLLSRC_HSI)
	constexpr bool pllClockSourceHse {};
	constexpr uint32_t pllInFrequency {hsiFrequency};
#elif defined(CONFIG_CHIP_STM32F4_RCC_PLLSRC_HSE)
	constexpr bool pllClockSourceHse {true};
	constexpr uint32_t pllInFrequency {CONFIG_CHIP_STM32F4_RCC_HSE_FREQUENCY};
#endif
	configurePllClockSource(pllClockSourceHse);

	constexpr uint32_t vcoInFrequency {pllInFrequency / CONFIG_CHIP_STM32F4_RCC_PLLM};
	static_assert(minVcoInFrequency <= vcoInFrequency && vcoInFrequency <= maxVcoInFrequency,
			"Invalid VCO input frequency!");
	configurePllInputClockDivider(CONFIG_CHIP_STM32F4_RCC_PLLM);

	constexpr uint32_t vcoOutFrequency {vcoInFrequency * CONFIG_CHIP_STM32F4_RCC_PLLN};
	static_assert(minVcoOutFrequency <= vcoOutFrequency && vcoOutFrequency <= maxVcoOutFrequency,
			"Invalid VCO output frequency!");

#if defined(CONFIG_CHIP_STM32F4_RCC_PLLP_DIV2)
	constexpr uint8_t pllp {pllpDiv2};
#elif defined(CONFIG_CHIP_STM32F4_RCC_PLLP_DIV4)
	constexpr uint8_t pllp {pllpDiv4};
#elif defined(CONFIG_CHIP_STM32F4_RCC_PLLP_DIV6)
	constexpr uint8_t pllp {pllpDiv6};
#elif defined(CONFIG_CHIP_STM32F4_RCC_PLLP_DIV8)
	constexpr uint8_t pllp {pllpDiv8};
#endif

	constexpr uint32_t pllOutFrequency {vcoOutFrequency / pllp};
	static_assert(pllOutFrequency <= maxPllOutFrequency[voltageScaleIndex], "Invalid PLL output frequency!");

	constexpr uint32_t pllqOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32F4_RCC_PLLQ};
	static_assert(pllqOutFrequency <= maxPllqOutFrequency, "Invalid PLL \"/Q\" output frequency!");

#if defined(CONFIG_CHIP_STM32F446) || defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)

	constexpr uint32_t pllrOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32F4_RCC_PLLR};

	enablePll(CONFIG_CHIP_STM32F4_RCC_PLLN, pllp, CONFIG_CHIP_STM32F4_RCC_PLLQ, CONFIG_CHIP_STM32F4_RCC_PLLR);

#else // !defined(CONFIG_CHIP_STM32F446) && !defined(CONFIG_CHIP_STM32F469) && !defined(CONFIG_CHIP_STM32F479)

	enablePll(CONFIG_CHIP_STM32F4_RCC_PLLN, pllp, CONFIG_CHIP_STM32F4_RCC_PLLQ);

#endif // !defined(CONFIG_CHIP_STM32F446) && !defined(CONFIG_CHIP_STM32F469) && !defined(CONFIG_CHIP_STM32F479)

#endif	// def CONFIG_CHIP_STM32F4_RCC_PLL_ENABLE

#if defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_HSI)
	constexpr uint32_t sysclkFrequency {hsiFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::hsi};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_HSE)
	constexpr uint32_t sysclkFrequency {CONFIG_CHIP_STM32F4_RCC_HSE_FREQUENCY};
	constexpr SystemClockSource systemClockSource {SystemClockSource::hse};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLL)
	constexpr uint32_t sysclkFrequency {pllOutFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::pll};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLLR)
	constexpr uint32_t sysclkFrequency {pllrOutFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::pllr};
#endif	// defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLLR)

#if defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV1)
	constexpr auto hpre = hpreDiv1;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV2)
	constexpr auto hpre = hpreDiv2;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV4)
	constexpr auto hpre = hpreDiv4;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV8)
	constexpr auto hpre = hpreDiv8;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV16)
	constexpr auto hpre = hpreDiv16;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV64)
	constexpr auto hpre = hpreDiv64;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV128)
	constexpr auto hpre = hpreDiv128;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV256)
	constexpr auto hpre = hpreDiv256;
#elif defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV512)
	constexpr auto hpre = hpreDiv512;
#endif	// defined(CONFIG_CHIP_STM32F4_RCC_AHB_DIV512)

	constexpr uint32_t ahbFrequency {sysclkFrequency / hpre};
	configureAhbClockDivider(hpre);

#if defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV1)
	constexpr auto ppre1 = ppreDiv1;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV2)
	constexpr auto ppre1 = ppreDiv2;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV4)
	constexpr auto ppre1 = ppreDiv4;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV8)
	constexpr auto ppre1 = ppreDiv8;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV16)
	constexpr auto ppre1 = ppreDiv16;
#endif	// defined(CONFIG_CHIP_STM32F4_RCC_APB1_DIV16)

	constexpr uint32_t apb1Frequency {ahbFrequency / ppre1};
	static_assert(apb1Frequency <= maxApb1Frequency, "Invalid APB1 (low speed) frequency!");
	configureApbClockDivider(false, ppre1);

#if defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV1)
	constexpr auto ppre2 = ppreDiv1;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV2)
	constexpr auto ppre2 = ppreDiv2;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV4)
	constexpr auto ppre2 = ppreDiv4;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV8)
	constexpr auto ppre2 = ppreDiv8;
#elif defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV16)
	constexpr auto ppre2 = ppreDiv16;
#endif	// defined(CONFIG_CHIP_STM32F4_RCC_APB2_DIV16)

	constexpr uint32_t apb2Frequency {ahbFrequency / ppre2};
	static_assert(apb2Frequency <= maxApb2Frequency, "Invalid APB2 (high speed) frequency!");
	configureApbClockDivider(true, ppre2);

#if CONFIG_CHIP_STM32F4_VDD_MV < 2100
#	if defined(CONFIG_CHIP_STM32F401) || defined(CONFIG_CHIP_STM32F410) || defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {16000000};
#	else	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {20000000};
#	endif	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
#elif CONFIG_CHIP_STM32F4_VDD_MV < 2400
#	if defined(CONFIG_CHIP_STM32F401) || defined(CONFIG_CHIP_STM32F410) || defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {18000000};
#	else	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {22000000};
#	endif	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
#elif CONFIG_CHIP_STM32F4_VDD_MV < 2700
	constexpr uint32_t frequencyThreshold {24000000};
#else
	constexpr uint32_t frequencyThreshold {30000000};
#endif

	constexpr uint8_t flashLatency {(ahbFrequency - 1) / frequencyThreshold};
	static_assert(flashLatency <= maxFlashLatency, "Invalid flash latency!");
	configureFlashLatency(flashLatency);

	switchSystemClock(systemClockSource);

#else	// !def CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	constexpr uint32_t ahbFrequency {CONFIG_CHIP_STM32F4_RCC_AHB_FREQUENCY};

#endif	// !def CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	constexpr uint32_t period {ahbFrequency / CONFIG_TICK_FREQUENCY};
	constexpr uint32_t periodDividedBy8 {period / 8};
	constexpr bool divideBy8 {period > architecture::maxSysTickPeriod};
	// at least one of the periods must be valid
	static_assert(period <= architecture::maxSysTickPeriod || periodDividedBy8 <= architecture::maxSysTickPeriod,
			"Invalid SysTick configuration!");
	architecture::configureSysTick(divideBy8 == false ? period : periodDividedBy8, divideBy8);
}

}	// namespace chip

}	// namespace distortos
<commit_msg>Use new numeric values in low-level initialization of STM32F4<commit_after>/**
 * \file
 * \brief chip::lowLevelInitialization() implementation for STM32F4
 *
 * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "distortos/chip/lowLevelInitialization.hpp"

#include "distortos/chip/STM32F4-FLASH.hpp"
#include "distortos/chip/STM32F4-PWR.hpp"
#include "distortos/chip/STM32F4-RCC.hpp"
#include "distortos/chip/STM32F4-RCC-bits.h"

#include "distortos/architecture/ARMv6-M-ARMv7-M-configureSysTick.hpp"

#include "distortos/chip/CMSIS-proxy.h"

namespace distortos
{

namespace chip
{

/*---------------------------------------------------------------------------------------------------------------------+
| global functions
+---------------------------------------------------------------------------------------------------------------------*/

void lowLevelInitialization()
{
#ifdef CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE
	static_assert(CONFIG_CHIP_STM32F4_VDD_MV >= 2100,
			"Instruction prefetch must not be enabled when supply voltage is below 2.1V!");
	configureInstructionPrefetch(true);
#else	// !def CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE
	configureInstructionPrefetch(false);
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_PREFETCH_ENABLE

#ifdef CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE
	enableDataCache();
#else	// !def CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE
	disableDataCache();
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_DATA_CACHE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE
	enableInstructionCache();
#else	// !def CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE
	disableInstructionCache();
#endif	// !def CONFIG_CHIP_STM32F4_FLASH_INSTRUCTION_CACHE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	RCC_APB1ENR_PWREN_bb = 1;

	configureVoltageScaling(CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE);

#if (defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) || \
		defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) && \
		defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

	static_assert(CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE == 1, "Over-drive mode requires voltage scale 1 mode!");
	static_assert(CONFIG_CHIP_STM32F4_VDD_MV >= 2100,
			"Over-drive mode must not be enabled when supply voltage is below 2.1V!");
	enableOverDriveMode();
	constexpr uint8_t voltageScaleIndex {0};

#else	// !(defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) ||
		// defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) ||
		// !defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

	constexpr uint8_t voltageScaleIndex {CONFIG_CHIP_STM32F4_PWR_VOLTAGE_SCALE_MODE};

#endif	// !(defined(CONFIG_CHIP_STM32F42) || defined(CONFIG_CHIP_STM32F43) || defined(CONFIG_CHIP_STM32F446) ||
		// defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)) ||
		// !defined(CONFIG_CHIP_STM32F4_PWR_OVER_DRIVE_ENABLE)

#ifdef CONFIG_CHIP_STM32F4_RCC_HSE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	constexpr bool hseClockBypass {true};
#else	// !def CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	constexpr bool hseClockBypass {};
#endif	// !def CONFIG_CHIP_STM32F4_RCC_HSE_CLOCK_BYPASS
	enableHse(hseClockBypass);

#endif	// def CONFIG_CHIP_STM32F4_RCC_HSE_ENABLE

#ifdef CONFIG_CHIP_STM32F4_RCC_PLL_ENABLE

#if defined(CONFIG_CHIP_STM32F4_RCC_PLLSRC_HSI)
	constexpr bool pllClockSourceHse {};
	constexpr uint32_t pllInFrequency {hsiFrequency};
#elif defined(CONFIG_CHIP_STM32F4_RCC_PLLSRC_HSE)
	constexpr bool pllClockSourceHse {true};
	constexpr uint32_t pllInFrequency {CONFIG_CHIP_STM32F4_RCC_HSE_FREQUENCY};
#endif
	configurePllClockSource(pllClockSourceHse);

	constexpr uint32_t vcoInFrequency {pllInFrequency / CONFIG_CHIP_STM32F4_RCC_PLLM};
	static_assert(minVcoInFrequency <= vcoInFrequency && vcoInFrequency <= maxVcoInFrequency,
			"Invalid VCO input frequency!");
	configurePllInputClockDivider(CONFIG_CHIP_STM32F4_RCC_PLLM);

	constexpr uint32_t vcoOutFrequency {vcoInFrequency * CONFIG_CHIP_STM32F4_RCC_PLLN};
	static_assert(minVcoOutFrequency <= vcoOutFrequency && vcoOutFrequency <= maxVcoOutFrequency,
			"Invalid VCO output frequency!");

	constexpr uint32_t pllOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32F4_RCC_PLLP};
	static_assert(pllOutFrequency <= maxPllOutFrequency[voltageScaleIndex], "Invalid PLL output frequency!");

	constexpr uint32_t pllqOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32F4_RCC_PLLQ};
	static_assert(pllqOutFrequency <= maxPllqOutFrequency, "Invalid PLL \"/Q\" output frequency!");

#if defined(CONFIG_CHIP_STM32F446) || defined(CONFIG_CHIP_STM32F469) || defined(CONFIG_CHIP_STM32F479)

	constexpr uint32_t pllrOutFrequency {vcoOutFrequency / CONFIG_CHIP_STM32F4_RCC_PLLR};

	enablePll(CONFIG_CHIP_STM32F4_RCC_PLLN, CONFIG_CHIP_STM32F4_RCC_PLLP, CONFIG_CHIP_STM32F4_RCC_PLLQ,
			CONFIG_CHIP_STM32F4_RCC_PLLR);

#else // !defined(CONFIG_CHIP_STM32F446) && !defined(CONFIG_CHIP_STM32F469) && !defined(CONFIG_CHIP_STM32F479)

	enablePll(CONFIG_CHIP_STM32F4_RCC_PLLN, CONFIG_CHIP_STM32F4_RCC_PLLP, CONFIG_CHIP_STM32F4_RCC_PLLQ);

#endif // !defined(CONFIG_CHIP_STM32F446) && !defined(CONFIG_CHIP_STM32F469) && !defined(CONFIG_CHIP_STM32F479)

#endif	// def CONFIG_CHIP_STM32F4_RCC_PLL_ENABLE

#if defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_HSI)
	constexpr uint32_t sysclkFrequency {hsiFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::hsi};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_HSE)
	constexpr uint32_t sysclkFrequency {CONFIG_CHIP_STM32F4_RCC_HSE_FREQUENCY};
	constexpr SystemClockSource systemClockSource {SystemClockSource::hse};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLL)
	constexpr uint32_t sysclkFrequency {pllOutFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::pll};
#elif defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLLR)
	constexpr uint32_t sysclkFrequency {pllrOutFrequency};
	constexpr SystemClockSource systemClockSource {SystemClockSource::pllr};
#endif	// defined(CONFIG_CHIP_STM32F4_RCC_SYSCLK_PLLR)

	constexpr uint32_t ahbFrequency {sysclkFrequency / CONFIG_CHIP_STM32F4_RCC_HPRE};
	configureAhbClockDivider(CONFIG_CHIP_STM32F4_RCC_HPRE);

	constexpr uint32_t apb1Frequency {ahbFrequency / CONFIG_CHIP_STM32F4_RCC_PPRE1};
	static_assert(apb1Frequency <= maxApb1Frequency, "Invalid APB1 (low speed) frequency!");
	configureApbClockDivider(false, CONFIG_CHIP_STM32F4_RCC_PPRE1);

	constexpr uint32_t apb2Frequency {ahbFrequency / CONFIG_CHIP_STM32F4_RCC_PPRE2};
	static_assert(apb2Frequency <= maxApb2Frequency, "Invalid APB2 (high speed) frequency!");
	configureApbClockDivider(true, CONFIG_CHIP_STM32F4_RCC_PPRE2);

#if CONFIG_CHIP_STM32F4_VDD_MV < 2100
#	if defined(CONFIG_CHIP_STM32F401) || defined(CONFIG_CHIP_STM32F410) || defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {16000000};
#	else	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {20000000};
#	endif	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
#elif CONFIG_CHIP_STM32F4_VDD_MV < 2400
#	if defined(CONFIG_CHIP_STM32F401) || defined(CONFIG_CHIP_STM32F410) || defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {18000000};
#	else	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
	constexpr uint32_t frequencyThreshold {22000000};
#	endif	// !defined(CONFIG_CHIP_STM32F401) && !defined(CONFIG_CHIP_STM32F410) && !defined(CONFIG_CHIP_STM32F411)
#elif CONFIG_CHIP_STM32F4_VDD_MV < 2700
	constexpr uint32_t frequencyThreshold {24000000};
#else
	constexpr uint32_t frequencyThreshold {30000000};
#endif

	constexpr uint8_t flashLatency {(ahbFrequency - 1) / frequencyThreshold};
	static_assert(flashLatency <= maxFlashLatency, "Invalid flash latency!");
	configureFlashLatency(flashLatency);

	switchSystemClock(systemClockSource);

#else	// !def CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	constexpr uint32_t ahbFrequency {CONFIG_CHIP_STM32F4_RCC_AHB_FREQUENCY};

#endif	// !def CONFIG_CHIP_STM32F4_STANDARD_CLOCK_CONFIGURATION_ENABLE

	constexpr uint32_t period {ahbFrequency / CONFIG_TICK_FREQUENCY};
	constexpr uint32_t periodDividedBy8 {period / 8};
	constexpr bool divideBy8 {period > architecture::maxSysTickPeriod};
	// at least one of the periods must be valid
	static_assert(period <= architecture::maxSysTickPeriod || periodDividedBy8 <= architecture::maxSysTickPeriod,
			"Invalid SysTick configuration!");
	architecture::configureSysTick(divideBy8 == false ? period : periodDividedBy8, divideBy8);
}

}	// namespace chip

}	// namespace distortos
<|endoftext|>