<commit_before>#include "browser.h"

Browser::Browser(QWidget *parent) :
    QWidget(parent)
{
    progress = 0;
    this->parent = parent;

    //View
    view = new QWebView(this);
    view->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
    view->settings()->setAttribute(QWebSettings::JavaEnabled, true);
    view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);

    //Commandbar
    command_bar = new CommandBar(this);
    connect(command_bar, SIGNAL(returnPressed()), SLOT(changeLocation()));
    connect(view, SIGNAL(loadFinished(bool)), this, SLOT(finishLoading(bool)));

    connect(view,SIGNAL(loadProgress(int)),this,SLOT(showProgress(int)));

    QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this);
    connect(shortcut, SIGNAL(activated()), this, SLOT(showLocation()));
    command_bar->setVisible(false);

    //Layout
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);

    mainLayout->addWidget(view);

    mainLayout->addWidget(command_bar);
    command_bar->setSizePolicy(QSizePolicy::Expanding, command_bar->sizePolicy().verticalPolicy());

    setLayout(mainLayout);

    //Startup
    view->load(QUrl("https://www.google.com"));
}

void Browser::setWindowTitle(QString title){
    parent->setWindowTitle("Kaktus - " + title);
}

void Browser::showProgress(int progress){
    setWindowTitle( QString("Loading: %1 %").arg(progress,0,10) );
}

void Browser::showLocation()
{
    command_bar->setVisible(!command_bar->isVisible());
    command_bar->selectAll();
    command_bar->setFocus();
}

void Browser::changeLocation()
{
    QUrl url = QUrl(command_bar->text());
    command_bar->setVisible(false);
    view->setFocus();
    view->load(url);
}

//Kod ska flyttas till commandbar
void Browser::finishLoading(bool success){
    if (success == true){
	setWindowTitle(view->title());
    }
    else{
        bool is_http = command_bar->text().startsWith("http:");
        bool is_https = command_bar->text().startsWith("https:");

        //If no http(s) try htpps
        if (!(is_http || is_https))
        {
            command_bar->setText(command_bar->text().prepend("https://"));
            changeLocation();
        }
        //Try http
        else if (is_https)
        {
            command_bar->setText(command_bar->text().remove(0, QString("https:").length()).prepend("http:"));
            changeLocation();
        }
        else
        {
            command_bar->setVisible(true);
            command_bar->setFocus();
            command_bar->selectAll();
        }
    }
}
<commit_msg>Detect pagetitle change<commit_after>#include "browser.h"

Browser::Browser(QWidget *parent) :
    QWidget(parent)
{
    progress = 0;
    this->parent = parent;

    //View
    view = new QWebView(this);
    view->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
    view->settings()->setAttribute(QWebSettings::JavaEnabled, true);
    view->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);

    //Commandbar
    command_bar = new CommandBar(this);
    connect(command_bar, SIGNAL(returnPressed()), SLOT(changeLocation()));
    connect(view, SIGNAL(loadFinished(bool)), this, SLOT(finishLoading(bool)));

    QShortcut *shortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this);
    connect(shortcut, SIGNAL(activated()), this, SLOT(showLocation()));
    command_bar->setVisible(false);

    /* Show loading progress */
    connect(view,SIGNAL(loadProgress(int)),this,SLOT(showProgress(int)));

    /* Update title */
    connect(view,SIGNAL(titleChanged(QString)),this,SLOT(setWindowTitle(QString)));

    //Layout
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);

    mainLayout->addWidget(view);

    mainLayout->addWidget(command_bar);
    command_bar->setSizePolicy(QSizePolicy::Expanding, command_bar->sizePolicy().verticalPolicy());

    setLayout(mainLayout);

    //Startup
    view->load(QUrl("https://www.google.com"));
}

void Browser::setWindowTitle(QString title){
    parent->setWindowTitle("Kaktus - " + title);
}

void Browser::showProgress(int progress){
    setWindowTitle( QString("Loading: %1 %").arg(progress,0,10) );
}

void Browser::showLocation()
{
    command_bar->setVisible(!command_bar->isVisible());
    command_bar->selectAll();
    command_bar->setFocus();
}

void Browser::changeLocation()
{
    QUrl url = QUrl(command_bar->text());
    command_bar->setVisible(false);
    view->setFocus();
    view->load(url);
}

//Kod ska flyttas till commandbar
void Browser::finishLoading(bool success){
    if (success == true){
	setWindowTitle(view->title());
    }
    else{
        bool is_http = command_bar->text().startsWith("http:");
        bool is_https = command_bar->text().startsWith("https:");

        //If no http(s) try htpps
        if (!(is_http || is_https))
        {
            command_bar->setText(command_bar->text().prepend("https://"));
            changeLocation();
        }
        //Try http
        else if (is_https)
        {
            command_bar->setText(command_bar->text().remove(0, QString("https:").length()).prepend("http:"));
            changeLocation();
        }
        else
        {
            command_bar->setVisible(true);
            command_bar->setFocus();
            command_bar->selectAll();
        }
    }
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ShapeDrawable>
#include <osg/GL>
#include <osg/Notify>

using namespace osg;

ShapeDrawable::ShapeDrawable()
{
}

ShapeDrawable::ShapeDrawable(Shape* shape,TessellationHints* hints):
    _tessellationHints(hints)
{
    setShape(shape);
}

ShapeDrawable::ShapeDrawable(const ShapeDrawable& sd,const CopyOp& copyop):
    Geometry(sd,copyop),
    _color(sd._color),
    _tessellationHints(sd._tessellationHints)
{
}

ShapeDrawable::~ShapeDrawable()
{
}

void ShapeDrawable::setShape(Shape* shape)
{
    if (_shape==shape) return;

    _shape = shape;

    build();
}

void ShapeDrawable::setColor(const Vec4& color)
{
    if (color==_color) return;

    _color = color;

    Vec4Array* colors = dynamic_cast<Vec4Array*>(_colorArray.get());
    if (!colors || colors->empty() || colors->getBinding()!=Array::BIND_OVERALL)
    {
        _colorArray = colors = new Vec4Array(Array::BIND_OVERALL, 1);
    }

    (*colors)[0] = color;
    colors->dirty();

    dirtyGLObjects();
}

void ShapeDrawable::setTessellationHints(TessellationHints* hints)
{
    if (_tessellationHints!=hints)
    {
        _tessellationHints = hints;
        build();
    }
}

void ShapeDrawable::build()
{
    // reset all the properties.
    setVertexArray(0);
    setNormalArray(0);
    setColorArray(0);
    setSecondaryColorArray(0);
    setFogCoordArray(0);
    getTexCoordArrayList().clear();
    getVertexAttribArrayList().clear();
    getPrimitiveSetList().clear();

    if (_shape)
    {
        BuildShapeGeometryVisitor dsv(this, _tessellationHints.get());
        _shape->accept(dsv);
    }
}
<commit_msg>Fixed missing initializer for _color and assignment of color to ShapeDrawable<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
#include <osg/ShapeDrawable>
#include <osg/GL>
#include <osg/Notify>

using namespace osg;

ShapeDrawable::ShapeDrawable():
    _color(1.0f, 1.0f, 1.0f, 1.0f)
{
}

ShapeDrawable::ShapeDrawable(Shape* shape,TessellationHints* hints):
    _color(1.0f, 1.0f, 1.0f, 1.0f),
    _tessellationHints(hints)
{
    setShape(shape);
}

ShapeDrawable::ShapeDrawable(const ShapeDrawable& sd,const CopyOp& copyop):
    Geometry(sd,copyop),
    _color(sd._color),
    _tessellationHints(sd._tessellationHints)
{
}

ShapeDrawable::~ShapeDrawable()
{
}

void ShapeDrawable::setShape(Shape* shape)
{
    if (_shape==shape) return;

    _shape = shape;

    build();
}

void ShapeDrawable::setColor(const Vec4& color)
{
    _color = color;

    Vec4Array* colors = dynamic_cast<Vec4Array*>(_colorArray.get());
    if (!colors || colors->empty() || colors->getBinding()!=Array::BIND_OVERALL)
    {
        _colorArray = colors = new Vec4Array(Array::BIND_OVERALL, 1);
    }

    (*colors)[0] = color;
    colors->dirty();

    dirtyGLObjects();
}

void ShapeDrawable::setTessellationHints(TessellationHints* hints)
{
    if (_tessellationHints!=hints)
    {
        _tessellationHints = hints;
        build();
    }
}

void ShapeDrawable::build()
{
    // reset all the properties.
    setVertexArray(0);
    setNormalArray(0);
    setColorArray(0);
    setSecondaryColorArray(0);
    setFogCoordArray(0);
    getTexCoordArrayList().clear();
    getVertexAttribArrayList().clear();
    getPrimitiveSetList().clear();

    if (_shape)
    {
        BuildShapeGeometryVisitor dsv(this, _tessellationHints.get());
        _shape->accept(dsv);
    }

    setColor(_color);
}
<|endoftext|>


<commit_before><commit_msg>Better db-zero handling<commit_after><|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgDB/ObjectCache>

using namespace osgDB;

////////////////////////////////////////////////////////////////////////////////////////////
//
// ObjectCache
//
ObjectCache::ObjectCache():
    osg::Referenced(true)
{
//    OSG_NOTICE<<"Constructed ObjectCach"<<std::endl;
}

ObjectCache::~ObjectCache()
{
//    OSG_NOTICE<<"Destructed ObjectCach"<<std::endl;
}

void ObjectCache::addObjectCache(ObjectCache* objectCache)
{
    // don't allow a cache to be added to itself.
    if (objectCache==this) return;

    // lock both ObjectCache to prevent their contents from being modified by other threads while we merge.
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_objectCacheMutex);
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(objectCache->_objectCacheMutex);

    // OSG_NOTICE<<"Inserting objects to main ObjectCache "<<objectCache->_objectCache.size()<<std::endl;

    _objectCache.insert(objectCache->_objectCache.begin(), objectCache->_objectCache.end());
}

void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
}

osg::Object* ObjectCache::getFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end()) return itr->second.first.get();
    else return 0;
}

osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end())
    {
        // OSG_NOTICE<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        return itr->second.first;
    }
    else return 0;
}

void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // look for objects with external references and update their time stamp.
    for(ObjectCacheMap::iterator itr=_objectCache.begin();
        itr!=_objectCache.end();
        ++itr)
    {
        // if ref count is greater the 1 the object has an external reference.
        if (itr->second.first->referenceCount()>1)
        {
            // so update it time stamp.
            itr->second.second = referenceTime;
        }
    }
}

void ObjectCache::removeExpiredObjectsInCache(double expiryTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // Remove expired entries from object cache
    ObjectCacheMap::iterator oitr = _objectCache.begin();
    while(oitr != _objectCache.end())
    {
        if (oitr->second.second<=expiryTime)
        {
            _objectCache.erase(oitr++);
        }
        else
        {
            ++oitr;
        }
    }
}

void ObjectCache::removeFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end()) _objectCache.erase(itr);
}

void ObjectCache::clear()
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache.clear();
}

void ObjectCache::releaseGLObjects(osg::State* state)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    for(ObjectCacheMap::iterator itr = _objectCache.begin();
        itr != _objectCache.end();
        ++itr)
    {
        osg::Object* object = itr->second.first.get();
        object->releaseGLObjects(state);
    }
}
<commit_msg>Fixed typo in comment<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgDB/ObjectCache>

using namespace osgDB;

////////////////////////////////////////////////////////////////////////////////////////////
//
// ObjectCache
//
ObjectCache::ObjectCache():
    osg::Referenced(true)
{
//    OSG_NOTICE<<"Constructed ObjectCache"<<std::endl;
}

ObjectCache::~ObjectCache()
{
//    OSG_NOTICE<<"Destructed ObjectCache"<<std::endl;
}

void ObjectCache::addObjectCache(ObjectCache* objectCache)
{
    // don't allow a cache to be added to itself.
    if (objectCache==this) return;

    // lock both ObjectCache to prevent their contents from being modified by other threads while we merge.
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock1(_objectCacheMutex);
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock2(objectCache->_objectCacheMutex);

    // OSG_NOTICE<<"Inserting objects to main ObjectCache "<<objectCache->_objectCache.size()<<std::endl;

    _objectCache.insert(objectCache->_objectCache.begin(), objectCache->_objectCache.end());
}

void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache[filename]=ObjectTimeStampPair(object,timestamp);
}

osg::Object* ObjectCache::getFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end()) return itr->second.first.get();
    else return 0;
}

osg::ref_ptr<osg::Object> ObjectCache::getRefFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end())
    {
        // OSG_NOTICE<<"Found "<<fileName<<" in ObjectCache "<<this<<std::endl;
        return itr->second.first;
    }
    else return 0;
}

void ObjectCache::updateTimeStampOfObjectsInCacheWithExternalReferences(double referenceTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // look for objects with external references and update their time stamp.
    for(ObjectCacheMap::iterator itr=_objectCache.begin();
        itr!=_objectCache.end();
        ++itr)
    {
        // if ref count is greater the 1 the object has an external reference.
        if (itr->second.first->referenceCount()>1)
        {
            // so update it time stamp.
            itr->second.second = referenceTime;
        }
    }
}

void ObjectCache::removeExpiredObjectsInCache(double expiryTime)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    // Remove expired entries from object cache
    ObjectCacheMap::iterator oitr = _objectCache.begin();
    while(oitr != _objectCache.end())
    {
        if (oitr->second.second<=expiryTime)
        {
            _objectCache.erase(oitr++);
        }
        else
        {
            ++oitr;
        }
    }
}

void ObjectCache::removeFromObjectCache(const std::string& fileName)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    ObjectCacheMap::iterator itr = _objectCache.find(fileName);
    if (itr!=_objectCache.end()) _objectCache.erase(itr);
}

void ObjectCache::clear()
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);
    _objectCache.clear();
}

void ObjectCache::releaseGLObjects(osg::State* state)
{
    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_objectCacheMutex);

    for(ObjectCacheMap::iterator itr = _objectCache.begin();
        itr != _objectCache.end();
        ++itr)
    {
        osg::Object* object = itr->second.first.get();
        object->releaseGLObjects(state);
    }
}
<|endoftext|>


<commit_before>// -*-c++-*-

/*
 * $Id$
 *
 * Loader for DirectX .x files.
 * Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif

#include "mesh.h"
#include "directx.h"

#include <iostream>
#include <string.h>
#include <stdlib.h>

#include <osg/Notify>

using namespace DX;
using namespace std;

/**********************************************************************
 *
 * DirectX mesh.
 *
 **********************************************************************/

Mesh::Mesh(Object * obj)
{
    _obj = obj;
    _normals = 0;
    _textureCoords = 0;
    _materialList = 0;
}

void Mesh::clear()
{
    if (_normals) {
        delete _normals;
        _normals = 0;
    }

    if (_textureCoords) {
        delete _textureCoords;
        _textureCoords = 0;
    }

    if (_materialList) {
        delete _materialList;
        _materialList = 0;
    }
}

bool Mesh::generateNormals(float /*creaseAngle*/)
{
    //cerr << "*** generateNormals\n";

    // Forget old normals
    if (_normals) {
        delete _normals;
        _normals = 0;
    }

    /*
     * Calculate per-face normals from face vertices.
     */
    vector<Vector> faceNormals;
    faceNormals.resize(_faces.size());

    unsigned int fi;
    for (fi = 0; fi < _faces.size(); fi++) {

        vector<Vector> poly;
        unsigned int n = _faces[fi].size();

        if (n < 3)
            continue;
        for (unsigned int i = 0; i < n; i++) {
            unsigned int idx = _faces[fi][i];
            poly.push_back(_vertices[idx]);
        }

        // Edge vectors
        Vector e0;
        e0.x = poly[1].x - poly[0].x;
        e0.y = poly[1].y - poly[0].y;
        e0.z = poly[1].z - poly[0].z;

        Vector e1;
        e1.x = poly[2].x - poly[0].x;
        e1.y = poly[2].y - poly[0].y;
        e1.z = poly[2].z - poly[0].z;

        // Cross-product of e0,e1
        Vector normal;
        normal.x = e0.y * e1.z - e0.z * e1.y;
        normal.y = e0.z * e1.x - e0.x * e1.z;
        normal.z = e0.x * e1.y - e0.y * e1.x;
        normal.normalize();

        // Add to per-face normals
        faceNormals[fi] = normal;
    }

    /*
     * Calculate per-vertex normals as average of all per-face normals that
     * share this vertex. The index of the vertex normal is identical to the
     * vertex index for now. This means each vertex only has a single normal...
     */
    _normals = new MeshNormals;
    _normals->normals.resize(_vertices.size());

    for (unsigned int vi = 0; vi < _vertices.size(); vi++) {

        Vector normal = { 0.0f, 0.0f, 0.0f };
        unsigned int polyCount = 0;

        // Collect normals of polygons that share this vertex
        for (unsigned int fi = 0; fi < _faces.size(); fi++)
            for (unsigned int i = 0; i < _faces[fi].size(); i++) {
                unsigned int idx = _faces[fi][i];
                if (idx == vi) {
                    normal.x += faceNormals[fi].x;
                    normal.y += faceNormals[fi].y;
                    normal.z += faceNormals[fi].z;
                    polyCount++;
                }
            }

        //OSG_INFO << "vertex " << vi << " used by " << polyCount << " faces\n";
        if (polyCount > 1) {
            float polyCountRecip = 1.0f / (float) polyCount;
            normal.x *= polyCountRecip;
            normal.y *= polyCountRecip;
            normal.z *= polyCountRecip;
            normal.normalize();
        }

        // Add vertex normal
        _normals->normals[vi] = normal;
    }

    // Copy face mesh to normals mesh
    _normals->faceNormals.resize(_faces.size());
    for (fi = 0; fi < _faces.size(); fi++)
        _normals->faceNormals[fi] = _faces[fi];

    return true;
}

// Parse 'Mesh'
void Mesh::parseMesh(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nVertices = 0, nFaces = 0;

    //cerr << "*** Mesh\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        //cerr << "*** Mesh token=" << token[0] << endl;
        if (strrchr(buf, '}') != 0) {
            break;
        }
        else if (strrchr(buf, '{') != 0) {
            if (token[0] == "MeshMaterialList")
                parseMeshMaterialList(fin);
            else if (token[0] == "MeshNormals")
                parseMeshNormals(fin);
            else if (token[0] == "MeshTextureCoords")
                readMeshTexCoords(fin);
            else {
                //cerr << "!!! Mesh: Begin section " << token[0] << endl;
                _obj->parseSection(fin);
            }
        }
        else if (nVertices == 0) {
            // Vertices
            nVertices = atoi(token[0].c_str());
            readVector(fin, _vertices, nVertices);

            if (nVertices != _vertices.size())
            {
                OSG_WARN << "DirectX loader: Error reading vertices; " << _vertices.size() << " instead of " << nVertices << endl;
            }
        }
        else if (nFaces == 0) {
            // Faces
            nFaces = atoi(token[0].c_str());
            readMeshFace(fin, _faces, nFaces);

            if (nFaces != _faces.size())
            {
                OSG_WARN << "DirectX loader: Error reading mesh; " << _faces.size() << " instead of " << nFaces << endl;
            }
        }
        else
            OSG_INFO << "!!! " << buf << endl;
    }
}

// Parse 'MeshMaterialList'
void Mesh::parseMeshMaterialList(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nMaterials = 0, nFaceIndices = 0;

    //cerr << "*** MeshMaterialList\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        // check for "{ <material name> }" for a
        // material which was declared globally
        Material * material = _obj->findMaterial(token[0]);
        if (material)
        {
            _materialList->material.push_back(*material);
            continue;
        }

        if (strrchr(buf, '}') != 0)
            break;
        else if (strrchr(buf, '{') != 0) {
            if (token[0] == "Material") {
                Material mm;
                parseMaterial(fin, mm);
                _materialList->material.push_back(mm);
                //cerr << "num mat=" << _materialList->material.size() << endl;
            }
            else {
                //cerr << "!!! MeshMaterialList: Begin section " << token[0] << endl;
                _obj->parseSection(fin);
            }
        }
        else if (nMaterials == 0) {
            // Create MeshMaterialList
            if (!_materialList)
                _materialList = new MeshMaterialList;

            // Materials
            nMaterials = atoi(token[0].c_str());
            //cerr << "expecting num Materials=" << nMaterials << endl;
        }
        else if (nFaceIndices == 0) {
            // Face indices
            nFaceIndices = atoi(token[0].c_str());
            readIndexList(fin, _materialList->faceIndices, nFaceIndices);

            if (nFaceIndices != _materialList->faceIndices.size())
            {
                OSG_WARN << "DirectX loader: Error reading face indices; " << nFaceIndices << " instead of " << _materialList->faceIndices.size() << endl;
            }
        }
    }

    if (nMaterials != _materialList->material.size())
    {
        OSG_WARN << "DirectX loader: Error reading material list; " << nMaterials << " instead of " << _materialList->material.size() << endl;
    }
}

// Parse 'MeshNormals'
void Mesh::parseMeshNormals(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nNormals = 0, nFaceNormals = 0;

    //cerr << "*** MeshNormals\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        if (strrchr(buf, '}') != 0)
            break;
        else if (nNormals == 0) {
            // Create MeshNormals
            if (!_normals)
                _normals = new MeshNormals;

            // Normals
            nNormals = atoi(token[0].c_str());
            readVector(fin, _normals->normals, nNormals);

            if (nNormals != _normals->normals.size())
            {
                OSG_WARN << "DirectX loader: Error reading normals; " << nNormals << " instead of " << _normals->normals.size() << endl;
            }

#define NORMALIZE_NORMALS
#ifdef NORMALIZE_NORMALS
            for (unsigned int i = 0; i < _normals->normals.size(); i++)
                _normals->normals[i].normalize();
#endif
        }
        else if (nFaceNormals == 0) {
            // Face normals
            nFaceNormals = atoi(token[0].c_str());
            readMeshFace(fin, _normals->faceNormals, nFaceNormals);

            if (nFaceNormals != _normals->faceNormals.size())
            {
                OSG_WARN << "DirectX loader: Error reading face normals; " << nFaceNormals << " instead of " << _normals->faceNormals.size() << endl;
            }
        }
    }
}

// Read 'MeshTextureCoords'
void Mesh::readMeshTexCoords(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nTextureCoords = 0;

    //cerr << "*** MeshTextureCoords\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        if (strrchr(buf, '}') != 0)
            break;

        // Create MeshTextureCoords
        if (!_textureCoords)
            _textureCoords = new MeshTextureCoords;

        // Texture coords
        nTextureCoords = atoi(token[0].c_str());
        readCoords2d(fin, *_textureCoords, nTextureCoords);

        if (nTextureCoords != _textureCoords->size())
        {
            OSG_INFO << "DirectX loader: Error reading texcoords; " << _textureCoords->size() << " instead of " << nTextureCoords << endl;
            delete _textureCoords;
            _textureCoords = 0;
        }
    }
}
<commit_msg>From Tassilo Glander, "I want to submit a fix for the plugin to load .x model files (Direct X).<commit_after>// -*-c++-*-

/*
 * $Id$
 *
 * Loader for DirectX .x files.
 * Copyright (c)2002-2006 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#if defined(_MSC_VER) && (_MSC_VER <= 1200)
#pragma warning (disable : 4786)
#endif

#include "mesh.h"
#include "directx.h"

#include <iostream>
#include <string.h>
#include <stdlib.h>

#include <osg/Notify>

using namespace DX;
using namespace std;

/**********************************************************************
 *
 * DirectX mesh.
 *
 **********************************************************************/

Mesh::Mesh(Object * obj)
{
    _obj = obj;
    _normals = 0;
    _textureCoords = 0;
    _materialList = 0;
}

void Mesh::clear()
{
    if (_normals) {
        delete _normals;
        _normals = 0;
    }

    if (_textureCoords) {
        delete _textureCoords;
        _textureCoords = 0;
    }

    if (_materialList) {
        delete _materialList;
        _materialList = 0;
    }
}

bool Mesh::generateNormals(float /*creaseAngle*/)
{
    //cerr << "*** generateNormals\n";

    // Forget old normals
    if (_normals) {
        delete _normals;
        _normals = 0;
    }

    /*
     * Calculate per-face normals from face vertices.
     */
    vector<Vector> faceNormals;
    faceNormals.resize(_faces.size());

    unsigned int fi;
    for (fi = 0; fi < _faces.size(); fi++) {

        vector<Vector> poly;
        unsigned int n = _faces[fi].size();

        if (n < 3)
            continue;
        for (unsigned int i = 0; i < n; i++) {
            unsigned int idx = _faces[fi][i];
            poly.push_back(_vertices[idx]);
        }

        // Edge vectors
        Vector e0;
        e0.x = poly[1].x - poly[0].x;
        e0.y = poly[1].y - poly[0].y;
        e0.z = poly[1].z - poly[0].z;

        Vector e1;
        e1.x = poly[2].x - poly[0].x;
        e1.y = poly[2].y - poly[0].y;
        e1.z = poly[2].z - poly[0].z;

        // Cross-product of e0,e1
        Vector normal;
        normal.x = e0.y * e1.z - e0.z * e1.y;
        normal.y = e0.z * e1.x - e0.x * e1.z;
        normal.z = e0.x * e1.y - e0.y * e1.x;
        normal.normalize();

        // Add to per-face normals
        faceNormals[fi] = normal;
    }

    /*
     * Calculate per-vertex normals as average of all per-face normals that
     * share this vertex. The index of the vertex normal is identical to the
     * vertex index for now. This means each vertex only has a single normal...
     */
    _normals = new MeshNormals;
    _normals->normals.resize(_vertices.size());

    for (unsigned int vi = 0; vi < _vertices.size(); vi++) {

        Vector normal = { 0.0f, 0.0f, 0.0f };
        unsigned int polyCount = 0;

        // Collect normals of polygons that share this vertex
        for (unsigned int fi = 0; fi < _faces.size(); fi++)
            for (unsigned int i = 0; i < _faces[fi].size(); i++) {
                unsigned int idx = _faces[fi][i];
                if (idx == vi) {
                    normal.x += faceNormals[fi].x;
                    normal.y += faceNormals[fi].y;
                    normal.z += faceNormals[fi].z;
                    polyCount++;
                }
            }

        //OSG_INFO << "vertex " << vi << " used by " << polyCount << " faces\n";
        if (polyCount > 1) {
            float polyCountRecip = 1.0f / (float) polyCount;
            normal.x *= polyCountRecip;
            normal.y *= polyCountRecip;
            normal.z *= polyCountRecip;
            normal.normalize();
        }

        // Add vertex normal
        _normals->normals[vi] = normal;
    }

    // Copy face mesh to normals mesh
    _normals->faceNormals.resize(_faces.size());
    for (fi = 0; fi < _faces.size(); fi++)
        _normals->faceNormals[fi] = _faces[fi];

    return true;
}

// Parse 'Mesh'
void Mesh::parseMesh(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nVertices = 0, nFaces = 0;

    //cerr << "*** Mesh\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        //cerr << "*** Mesh token=" << token[0] << endl;
        if (strrchr(buf, '}') != 0) {
            break;
        }
        else if (strrchr(buf, '{') != 0) {
            if (token[0] == "MeshMaterialList")
                parseMeshMaterialList(fin);
            else if (token[0] == "MeshNormals")
                parseMeshNormals(fin);
            else if (token[0] == "MeshTextureCoords")
                readMeshTexCoords(fin);
            else {
                //cerr << "!!! Mesh: Begin section " << token[0] << endl;
                _obj->parseSection(fin);
            }
        }
        else if (nVertices == 0) {
            // Vertices
            nVertices = atoi(token[0].c_str());
            readVector(fin, _vertices, nVertices);

            if (nVertices != _vertices.size())
            {
                OSG_WARN << "DirectX loader: Error reading vertices; " << _vertices.size() << " instead of " << nVertices << endl;
            }
        }
        else if (nFaces == 0) {
            // Faces
            nFaces = atoi(token[0].c_str());
            readMeshFace(fin, _faces, nFaces);

            if (nFaces != _faces.size())
            {
                OSG_WARN << "DirectX loader: Error reading mesh; " << _faces.size() << " instead of " << nFaces << endl;
            }
        }
        else
            OSG_INFO << "!!! " << buf << endl;
    }
}

// Parse 'MeshMaterialList'
void Mesh::parseMeshMaterialList(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nMaterials = 0, nFaceIndices = 0;

    //cerr << "*** MeshMaterialList\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        // check for "{ <material name> }" for a
        // material which was declared globally
        string materialName = token[0];
        // could be given as "{ someName }" which more than 1 tokens
        if (materialName == "{" && token.size()>1)
        {
            materialName = token[1];
        }
        // or could be given as "{someName}" which would be in token[0]
        else if (materialName.size() > 2 && materialName[0] == '{' && materialName[materialName.size()-1] == '}')
        {
            // remove curly brackets
            materialName = materialName.substr(1, materialName.size()-2);
        }
        Material * material = _obj->findMaterial(materialName);

        if (material)
        {
            _materialList->material.push_back(*material);
            continue;
        }

        if (strrchr(buf, '}') != 0)
            break;
        else if (strrchr(buf, '{') != 0) {
            if (token[0] == "Material") {
                Material mm;
                parseMaterial(fin, mm);
                _materialList->material.push_back(mm);
                //cerr << "num mat=" << _materialList->material.size() << endl;
            }
            else {
                //cerr << "!!! MeshMaterialList: Begin section " << token[0] << endl;
                _obj->parseSection(fin);
            }
        }
        else if (nMaterials == 0) {
            // Create MeshMaterialList
            if (!_materialList)
                _materialList = new MeshMaterialList;

            // Materials
            nMaterials = atoi(token[0].c_str());
            //cerr << "expecting num Materials=" << nMaterials << endl;
        }
        else if (nFaceIndices == 0) {
            // Face indices
            nFaceIndices = atoi(token[0].c_str());
            readIndexList(fin, _materialList->faceIndices, nFaceIndices);

            if (nFaceIndices != _materialList->faceIndices.size())
            {
                OSG_WARN << "DirectX loader: Error reading face indices; " << nFaceIndices << " instead of " << _materialList->faceIndices.size() << endl;
            }
        }
    }

    if (nMaterials != _materialList->material.size())
    {
        OSG_WARN << "DirectX loader: Error reading material list; " << nMaterials << " instead of " << _materialList->material.size() << endl;
    }
}

// Parse 'MeshNormals'
void Mesh::parseMeshNormals(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nNormals = 0, nFaceNormals = 0;

    //cerr << "*** MeshNormals\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        if (strrchr(buf, '}') != 0)
            break;
        else if (nNormals == 0) {
            // Create MeshNormals
            if (!_normals)
                _normals = new MeshNormals;

            // Normals
            nNormals = atoi(token[0].c_str());
            readVector(fin, _normals->normals, nNormals);

            if (nNormals != _normals->normals.size())
            {
                OSG_WARN << "DirectX loader: Error reading normals; " << nNormals << " instead of " << _normals->normals.size() << endl;
            }

#define NORMALIZE_NORMALS
#ifdef NORMALIZE_NORMALS
            for (unsigned int i = 0; i < _normals->normals.size(); i++)
                _normals->normals[i].normalize();
#endif
        }
        else if (nFaceNormals == 0) {
            // Face normals
            nFaceNormals = atoi(token[0].c_str());
            readMeshFace(fin, _normals->faceNormals, nFaceNormals);

            if (nFaceNormals != _normals->faceNormals.size())
            {
                OSG_WARN << "DirectX loader: Error reading face normals; " << nFaceNormals << " instead of " << _normals->faceNormals.size() << endl;
            }
        }
    }
}

// Read 'MeshTextureCoords'
void Mesh::readMeshTexCoords(std::istream& fin)
{
    char buf[256];
    vector<string> token;

    unsigned int nTextureCoords = 0;

    //cerr << "*** MeshTextureCoords\n";
    while (fin.getline(buf, sizeof(buf))) {

        // Tokenize
        token.clear();
        tokenize(buf, token);
        if (token.size() == 0)
            continue;

        if (strrchr(buf, '}') != 0)
            break;

        // Create MeshTextureCoords
        if (!_textureCoords)
            _textureCoords = new MeshTextureCoords;

        // Texture coords
        nTextureCoords = atoi(token[0].c_str());
        readCoords2d(fin, *_textureCoords, nTextureCoords);

        if (nTextureCoords != _textureCoords->size())
        {
            OSG_INFO << "DirectX loader: Error reading texcoords; " << _textureCoords->size() << " instead of " << nTextureCoords << endl;
            delete _textureCoords;
            _textureCoords = 0;
        }
    }
}
<|endoftext|>


<commit_before>#include "keygen.h"

#include <iostream>

namespace OpenPGP {
namespace KeyGen {

bool fill_key_sigs(SecretKey & private_key, const std::string & passphrase) {
    if (!private_key.meaningful()) {
        // "Error: Bad key.\n";
        return false;
    }

    const std::string keyid = private_key.keyid();
    const Packet::Tag5::Ptr primary = std::static_pointer_cast <Packet::Tag5> (private_key.get_packets()[0]);
    PGP::Packets packets = private_key.get_packets_clone();

    Packet::Key::Ptr key = nullptr;
    Packet::User::Ptr user = nullptr;

    for(Packet::Tag::Ptr & p : packets) {
        if (Packet::is_key_packet(p -> get_tag())) {
            key = std::static_pointer_cast <Packet::Key> (p);
            user = nullptr;
        }
        else if (Packet::is_user(p -> get_tag())) {
            user = std::static_pointer_cast <Packet::User> (p);
        }
        else if (p -> get_tag() == Packet::SIGNATURE) {
            Packet::Tag2::Ptr sig = std::static_pointer_cast <Packet::Tag2> (p);

            // only fill in keys that are supposed to be signed by the primary key
            // don't fill in empty key IDs
            if (sig -> get_keyid() == keyid) {
                if (Signature_Type::is_certification(sig -> get_type())) {
                    if (key -> get_tag() == Packet::SECRET_KEY) {
                        const Packet::Tag5::Ptr tag5 = std::static_pointer_cast <Packet::Tag5> (key);
                        sig = Sign::primary_key(primary, passphrase, tag5, user, sig);
                    }
                    else{
                        // "Error: Certification signature attempted to be made for a non-primary key.\n";
                        return false;
                    }
                }
                else if (sig -> get_type() == Signature_Type::SUBKEY_BINDING_SIGNATURE) {
                    if (key -> get_tag() == Packet::SECRET_SUBKEY) {
                        const Packet::Tag7::Ptr tag7 = std::static_pointer_cast <Packet::Tag7> (key);
                        sig = Sign::subkey_binding(primary, passphrase, tag7, sig);
                    }
                    else{
                        // "Error: Subkey Binding signature attempted to be made for a non-subkey.\n";
                        return false;
                    }
                }
                else if (sig -> get_type() == Signature_Type::KEY_REVOCATION_SIGNATURE) {
                    sig = Revoke::sig(primary, passphrase, primary, sig);
                }
                else if (sig -> get_type() == Signature_Type::SUBKEY_REVOCATION_SIGNATURE) {
                    sig = Revoke::sig(primary, passphrase, key, sig);
                }
                else if (sig -> get_type() == Signature_Type::CERTIFICATION_REVOCATION_SIGNATURE) {
                    sig = Revoke::uid_sig(primary, passphrase, user, sig);
                }
                else{
                    std::cerr << "Warning: Bad or unhandled signature type: 0x" << makehex(sig -> get_type(), 2) << std::endl;
                }
            }
        }
        else{
            // should never come here
            // "Error: Random packet found.\n";
            return false;
        }
    }

    private_key.set_packets(packets);

    return true;
}

SecretKey generate_key(Config & config) {
    if (!config.valid()) {
        // "Error: Bad key generation configuration.\n";
        return SecretKey();
    }

    // collection of packets to be put into final key
    PGP::Packets packets;

    // Key creation time
    const uint32_t time = now();

    // generate Primary Key, User ID, and Signature packets

    // generate public key values for primary key
    PKA::Values pub;
    PKA::Values pri;
    if (!PKA::generate_keypair(config.pka, PKA::generate_params(config.pka, config.bits >> 1), pri, pub)) {
        // "Error: Could not generate primary key pair.\n";
        return SecretKey();
    }

    // convert the secret values into a string
    std::string secret;
    for(MPI const & mpi : pri) {
        secret += write_MPI(mpi);
    }

    // Secret Key Packet
    Packet::Tag5::Ptr primary = std::make_shared <Packet::Tag5> ();
    primary -> set_version(4);
    primary -> set_time(time);
    primary -> set_pka(config.pka);
    primary -> set_mpi(pub);
    primary -> set_s2k_con(0); // no passphrase up to here

    // encrypt secret only if there is a passphrase
    if (config.passphrase.size()) {
        primary -> set_s2k_con(254);
        primary -> set_sym(config.sym);

        // Secret Key Packet S2K
        S2K::S2K3::Ptr s2k3 = std::make_shared <S2K::S2K3> ();
        s2k3 -> set_hash(config.hash);
        s2k3 -> set_salt(RNG::RNG().rand_bytes(8));
        s2k3 -> set_count(96);

        // calculate the key from the passphrase
        const std::string session_key = s2k3 -> run(config.passphrase, Sym::KEY_LENGTH.at(config.sym) >> 3);

        // add checksum to secret
        secret += Hash::use(Hash::ID::SHA1, secret);

        // encrypt private key value
        primary -> set_s2k(s2k3);
        primary -> set_IV(RNG::RNG().rand_bytes(Sym::BLOCK_LENGTH.at(config.sym >> 3)));
        secret = use_normal_CFB_encrypt(config.sym, secret, session_key, primary -> get_IV());
    }
    else{
        // add checksum to secret
        uint16_t checksum = 0;
        for(uint8_t const c : secret) {
            checksum += static_cast <uint16_t> (c);
        }

        secret += unhexlify(makehex(checksum, 4));
    }

    primary -> set_secret(secret);

    // first packet is primary key
    packets.push_back(primary);

    // get ID of primary key
    const std::string keyid = primary -> get_keyid();

    // generate User ID and Signature packets
    for(Config::UserID const & id : config.uids) {
        // User ID
        Packet::Tag13::Ptr uid = std::make_shared <Packet::Tag13> ();
        uid -> set_info(id.user, id.comment, id.email);

        packets.push_back(uid);

        Packet::Tag2::Ptr sig = std::make_shared <Packet::Tag2> ();
        sig -> set_version(4);
        sig -> set_type(Signature_Type::POSITIVE_CERTIFICATION_OF_A_USER_ID_AND_PUBLIC_KEY_PACKET);
        sig -> set_pka(config.pka);
        sig -> set_hash(id.sig);

        // set creation time
        Subpacket::Tag2::Sub2::Ptr tag2sub2 = std::make_shared <Subpacket::Tag2::Sub2> ();
        tag2sub2 -> set_time(time);
        sig -> set_hashed_subpackets({tag2sub2});

        // set issuer
        Subpacket::Tag2::Sub16::Ptr tag2sub16 = std::make_shared <Subpacket::Tag2::Sub16> ();
        tag2sub16 -> set_keyid(keyid);
        sig -> set_unhashed_subpackets({tag2sub16});

        // sign Primary Key and User ID
        sig = Sign::primary_key(primary, config.passphrase, primary, uid, sig);
        if (!sig) {
            // "Error: Failed to sign primary config.\n";
            return SecretKey();
        }

        packets.push_back(sig);
    }

    // generate 0 or more subkeys and associated signature packet
    for(Config::SubkeyGen const & skey : config.subkeys) {
        PKA::Values subkey_pub;
        PKA::Values subkey_pri;
        if (!PKA::generate_keypair(skey.pka, PKA::generate_params(skey.pka, skey.bits >> 1), subkey_pri, subkey_pub)) {
            // "Error: Could not generate subkey pair.\n";
            return SecretKey();
        }

        // convert the secret values into a string
        secret = "";
        for(MPI const & mpi : subkey_pri) {
            secret += write_MPI(mpi);
        }

        // Secret Subkey Packet
        Packet::Tag7::Ptr subkey = std::make_shared <Packet::Tag7> ();
        subkey -> set_version(4);
        subkey -> set_time(time);
        subkey -> set_pka(skey.pka);
        subkey -> set_mpi(subkey_pub);
        subkey -> set_s2k_con(0); // no passphrase up to here

        // encrypt secret only if there is a passphrase
        if (config.passphrase.size()) {
            subkey -> set_s2k_con(254);
            subkey -> set_sym(skey.sym);

            // Secret Subkey S2K
            S2K::S2K3::Ptr s2k3 = std::make_shared <S2K::S2K3> ();
            s2k3 -> set_hash(skey.hash);
            s2k3 -> set_salt(RNG::RNG().rand_bytes(8)); // new salt value
            s2k3 -> set_count(96);

            // calculate the key from the passphrase
            std::string session_key = s2k3 -> run(config.passphrase, Sym::KEY_LENGTH.at(skey.sym) >> 3);

            // add checksum to secret
            secret += Hash::use(Hash::ID::SHA1, secret);

            // encrypt private key value
            subkey -> set_s2k(s2k3);
            subkey -> set_IV(RNG::RNG().rand_bytes(Sym::BLOCK_LENGTH.at(skey.sym) >> 3));
            secret = use_normal_CFB_encrypt(skey.sym, secret + Hash::use(Hash::ID::SHA1, secret), session_key, subkey -> get_IV());
        }
        else{
            // add checksum to secret
            uint16_t checksum = 0;
            for(uint8_t const c : secret) {
                checksum += c;
            }

            secret += unhexlify(makehex(checksum, 4));
        }

        subkey -> set_secret(secret);

        packets.push_back(subkey);

        // Subkey Binding Signature
        Packet::Tag2::Ptr subsig = std::make_shared <Packet::Tag2> ();
        subsig -> set_version(4);
        subsig -> set_type(Signature_Type::SUBKEY_BINDING_SIGNATURE);
        subsig -> set_pka(config.pka);
        subsig -> set_hash(skey.sig);

        // set creation time
        Subpacket::Tag2::Sub2::Ptr tag2sub2 = std::make_shared <Subpacket::Tag2::Sub2> ();
        tag2sub2 -> set_time(time);
        subsig -> set_hashed_subpackets({tag2sub2});

        // set issuer
        Subpacket::Tag2::Sub16::Ptr tag2sub16 = std::make_shared <Subpacket::Tag2::Sub16> ();
        tag2sub16 -> set_keyid(keyid);
        subsig -> set_unhashed_subpackets({tag2sub16});

        // sign subkey
        subsig = Sign::subkey_binding(primary, config.passphrase, subkey, subsig);
        if (!subsig) {
            // "Error: Subkey signing failure.\n";
            return SecretKey();
        }

        packets.push_back(subsig);
    }

    // put everything into a private key
    SecretKey private_key;
    private_key.set_keys({std::make_pair("Version", "cc")});
    private_key.set_packets(packets);
    private_key.set_armored(true);

    // can call fill_key_sigs as well
    // return fill_key_sigs(private_key, config.passphrase);
    return private_key;
}

}
}
<commit_msg>Misplaced parenthesis (#45)<commit_after>#include "keygen.h"

#include <iostream>

namespace OpenPGP {
namespace KeyGen {

bool fill_key_sigs(SecretKey & private_key, const std::string & passphrase) {
    if (!private_key.meaningful()) {
        // "Error: Bad key.\n";
        return false;
    }

    const std::string keyid = private_key.keyid();
    const Packet::Tag5::Ptr primary = std::static_pointer_cast <Packet::Tag5> (private_key.get_packets()[0]);
    PGP::Packets packets = private_key.get_packets_clone();

    Packet::Key::Ptr key = nullptr;
    Packet::User::Ptr user = nullptr;

    for(Packet::Tag::Ptr & p : packets) {
        if (Packet::is_key_packet(p -> get_tag())) {
            key = std::static_pointer_cast <Packet::Key> (p);
            user = nullptr;
        }
        else if (Packet::is_user(p -> get_tag())) {
            user = std::static_pointer_cast <Packet::User> (p);
        }
        else if (p -> get_tag() == Packet::SIGNATURE) {
            Packet::Tag2::Ptr sig = std::static_pointer_cast <Packet::Tag2> (p);

            // only fill in keys that are supposed to be signed by the primary key
            // don't fill in empty key IDs
            if (sig -> get_keyid() == keyid) {
                if (Signature_Type::is_certification(sig -> get_type())) {
                    if (key -> get_tag() == Packet::SECRET_KEY) {
                        const Packet::Tag5::Ptr tag5 = std::static_pointer_cast <Packet::Tag5> (key);
                        sig = Sign::primary_key(primary, passphrase, tag5, user, sig);
                    }
                    else{
                        // "Error: Certification signature attempted to be made for a non-primary key.\n";
                        return false;
                    }
                }
                else if (sig -> get_type() == Signature_Type::SUBKEY_BINDING_SIGNATURE) {
                    if (key -> get_tag() == Packet::SECRET_SUBKEY) {
                        const Packet::Tag7::Ptr tag7 = std::static_pointer_cast <Packet::Tag7> (key);
                        sig = Sign::subkey_binding(primary, passphrase, tag7, sig);
                    }
                    else{
                        // "Error: Subkey Binding signature attempted to be made for a non-subkey.\n";
                        return false;
                    }
                }
                else if (sig -> get_type() == Signature_Type::KEY_REVOCATION_SIGNATURE) {
                    sig = Revoke::sig(primary, passphrase, primary, sig);
                }
                else if (sig -> get_type() == Signature_Type::SUBKEY_REVOCATION_SIGNATURE) {
                    sig = Revoke::sig(primary, passphrase, key, sig);
                }
                else if (sig -> get_type() == Signature_Type::CERTIFICATION_REVOCATION_SIGNATURE) {
                    sig = Revoke::uid_sig(primary, passphrase, user, sig);
                }
                else{
                    std::cerr << "Warning: Bad or unhandled signature type: 0x" << makehex(sig -> get_type(), 2) << std::endl;
                }
            }
        }
        else{
            // should never come here
            // "Error: Random packet found.\n";
            return false;
        }
    }

    private_key.set_packets(packets);

    return true;
}

SecretKey generate_key(Config & config) {
    if (!config.valid()) {
        // "Error: Bad key generation configuration.\n";
        return SecretKey();
    }

    // collection of packets to be put into final key
    PGP::Packets packets;

    // Key creation time
    const uint32_t time = now();

    // generate Primary Key, User ID, and Signature packets

    // generate public key values for primary key
    PKA::Values pub;
    PKA::Values pri;
    if (!PKA::generate_keypair(config.pka, PKA::generate_params(config.pka, config.bits >> 1), pri, pub)) {
        // "Error: Could not generate primary key pair.\n";
        return SecretKey();
    }

    // convert the secret values into a string
    std::string secret;
    for(MPI const & mpi : pri) {
        secret += write_MPI(mpi);
    }

    // Secret Key Packet
    Packet::Tag5::Ptr primary = std::make_shared <Packet::Tag5> ();
    primary -> set_version(4);
    primary -> set_time(time);
    primary -> set_pka(config.pka);
    primary -> set_mpi(pub);
    primary -> set_s2k_con(0); // no passphrase up to here

    // encrypt secret only if there is a passphrase
    if (config.passphrase.size()) {
        primary -> set_s2k_con(254);
        primary -> set_sym(config.sym);

        // Secret Key Packet S2K
        S2K::S2K3::Ptr s2k3 = std::make_shared <S2K::S2K3> ();
        s2k3 -> set_hash(config.hash);
        s2k3 -> set_salt(RNG::RNG().rand_bytes(8));
        s2k3 -> set_count(96);

        // calculate the key from the passphrase
        const std::string session_key = s2k3 -> run(config.passphrase, Sym::KEY_LENGTH.at(config.sym) >> 3);

        // add checksum to secret
        secret += Hash::use(Hash::ID::SHA1, secret);

        // encrypt private key value
        primary -> set_s2k(s2k3);
        primary -> set_IV(RNG::RNG().rand_bytes(Sym::BLOCK_LENGTH.at(config.sym) >> 3));
        secret = use_normal_CFB_encrypt(config.sym, secret, session_key, primary -> get_IV());
    }
    else{
        // add checksum to secret
        uint16_t checksum = 0;
        for(uint8_t const c : secret) {
            checksum += static_cast <uint16_t> (c);
        }

        secret += unhexlify(makehex(checksum, 4));
    }

    primary -> set_secret(secret);

    // first packet is primary key
    packets.push_back(primary);

    // get ID of primary key
    const std::string keyid = primary -> get_keyid();

    // generate User ID and Signature packets
    for(Config::UserID const & id : config.uids) {
        // User ID
        Packet::Tag13::Ptr uid = std::make_shared <Packet::Tag13> ();
        uid -> set_info(id.user, id.comment, id.email);

        packets.push_back(uid);

        Packet::Tag2::Ptr sig = std::make_shared <Packet::Tag2> ();
        sig -> set_version(4);
        sig -> set_type(Signature_Type::POSITIVE_CERTIFICATION_OF_A_USER_ID_AND_PUBLIC_KEY_PACKET);
        sig -> set_pka(config.pka);
        sig -> set_hash(id.sig);

        // set creation time
        Subpacket::Tag2::Sub2::Ptr tag2sub2 = std::make_shared <Subpacket::Tag2::Sub2> ();
        tag2sub2 -> set_time(time);
        sig -> set_hashed_subpackets({tag2sub2});

        // set issuer
        Subpacket::Tag2::Sub16::Ptr tag2sub16 = std::make_shared <Subpacket::Tag2::Sub16> ();
        tag2sub16 -> set_keyid(keyid);
        sig -> set_unhashed_subpackets({tag2sub16});

        // sign Primary Key and User ID
        sig = Sign::primary_key(primary, config.passphrase, primary, uid, sig);
        if (!sig) {
            // "Error: Failed to sign primary config.\n";
            return SecretKey();
        }

        packets.push_back(sig);
    }

    // generate 0 or more subkeys and associated signature packet
    for(Config::SubkeyGen const & skey : config.subkeys) {
        PKA::Values subkey_pub;
        PKA::Values subkey_pri;
        if (!PKA::generate_keypair(skey.pka, PKA::generate_params(skey.pka, skey.bits >> 1), subkey_pri, subkey_pub)) {
            // "Error: Could not generate subkey pair.\n";
            return SecretKey();
        }

        // convert the secret values into a string
        secret = "";
        for(MPI const & mpi : subkey_pri) {
            secret += write_MPI(mpi);
        }

        // Secret Subkey Packet
        Packet::Tag7::Ptr subkey = std::make_shared <Packet::Tag7> ();
        subkey -> set_version(4);
        subkey -> set_time(time);
        subkey -> set_pka(skey.pka);
        subkey -> set_mpi(subkey_pub);
        subkey -> set_s2k_con(0); // no passphrase up to here

        // encrypt secret only if there is a passphrase
        if (config.passphrase.size()) {
            subkey -> set_s2k_con(254);
            subkey -> set_sym(skey.sym);

            // Secret Subkey S2K
            S2K::S2K3::Ptr s2k3 = std::make_shared <S2K::S2K3> ();
            s2k3 -> set_hash(skey.hash);
            s2k3 -> set_salt(RNG::RNG().rand_bytes(8)); // new salt value
            s2k3 -> set_count(96);

            // calculate the key from the passphrase
            std::string session_key = s2k3 -> run(config.passphrase, Sym::KEY_LENGTH.at(skey.sym) >> 3);

            // add checksum to secret
            secret += Hash::use(Hash::ID::SHA1, secret);

            // encrypt private key value
            subkey -> set_s2k(s2k3);
            subkey -> set_IV(RNG::RNG().rand_bytes(Sym::BLOCK_LENGTH.at(skey.sym) >> 3));
            secret = use_normal_CFB_encrypt(skey.sym, secret + Hash::use(Hash::ID::SHA1, secret), session_key, subkey -> get_IV());
        }
        else{
            // add checksum to secret
            uint16_t checksum = 0;
            for(uint8_t const c : secret) {
                checksum += c;
            }

            secret += unhexlify(makehex(checksum, 4));
        }

        subkey -> set_secret(secret);

        packets.push_back(subkey);

        // Subkey Binding Signature
        Packet::Tag2::Ptr subsig = std::make_shared <Packet::Tag2> ();
        subsig -> set_version(4);
        subsig -> set_type(Signature_Type::SUBKEY_BINDING_SIGNATURE);
        subsig -> set_pka(config.pka);
        subsig -> set_hash(skey.sig);

        // set creation time
        Subpacket::Tag2::Sub2::Ptr tag2sub2 = std::make_shared <Subpacket::Tag2::Sub2> ();
        tag2sub2 -> set_time(time);
        subsig -> set_hashed_subpackets({tag2sub2});

        // set issuer
        Subpacket::Tag2::Sub16::Ptr tag2sub16 = std::make_shared <Subpacket::Tag2::Sub16> ();
        tag2sub16 -> set_keyid(keyid);
        subsig -> set_unhashed_subpackets({tag2sub16});

        // sign subkey
        subsig = Sign::subkey_binding(primary, config.passphrase, subkey, subsig);
        if (!subsig) {
            // "Error: Subkey signing failure.\n";
            return SecretKey();
        }

        packets.push_back(subsig);
    }

    // put everything into a private key
    SecretKey private_key;
    private_key.set_keys({std::make_pair("Version", "cc")});
    private_key.set_packets(packets);
    private_key.set_armored(true);

    // can call fill_key_sigs as well
    // return fill_key_sigs(private_key, config.passphrase);
    return private_key;
}

}
}
<|endoftext|>


<commit_before>#include <keymap.h>
#include <logger.h>
#include <vector>
#include <iostream>
#include <config.h>

namespace newsbeuter {

struct op_desc {
	operation op;
	const char * opstr;
	const char * default_key;
	const char * help_text;
	unsigned short flags;
};

/*
 * This is the list of operations, defining operation, operation name (for keybindings), default key, description, and where it's valid
 */
static op_desc opdescs[] = {
	{ OP_OPEN, "open", "ENTER", _("Open feed/article"), KM_NEWSBEUTER },
	{ OP_QUIT, "quit", "q", _("Return to previous dialog/Quit"), KM_BOTH },
	{ OP_RELOAD, "reload", "r", _("Reload currently selected feed"), KM_NEWSBEUTER },
	{ OP_RELOADALL, "reload-all", "R", _("Reload all feeds"), KM_NEWSBEUTER },
	{ OP_MARKFEEDREAD, "mark-feed-read", "A", _("Mark feed read"), KM_NEWSBEUTER },
	{ OP_MARKALLFEEDSREAD, "mark-all-feeds-read", "C", _("Mark all feeds read"), KM_NEWSBEUTER },
	{ OP_SAVE, "save", "s", _("Save article"), KM_NEWSBEUTER },
	{ OP_NEXTUNREAD, "next-unread", "n", _("Go to next unread article"), KM_NEWSBEUTER },
	{ OP_PREVUNREAD, "prev-unread", "p", _("Go to previous unread article"), KM_NEWSBEUTER },
	{ OP_OPENINBROWSER, "open-in-browser", "o", _("Open article in browser"), KM_NEWSBEUTER },
	{ OP_HELP, "help", "?", _("Open help dialog"), KM_BOTH },
	{ OP_TOGGLESOURCEVIEW, "toggle-source-view", "^U", _("Toggle source view"), KM_NEWSBEUTER },
	{ OP_TOGGLEITEMREAD, "toggle-article-read", "N", _("Toggle read status for article"), KM_NEWSBEUTER },
	{ OP_TOGGLESHOWREAD, "toggle-show-read-feeds", "l", _("Toggle show read feeds/articles"), KM_NEWSBEUTER },
	{ OP_SHOWURLS, "show-urls", "u", _("Show URLs in current article"), KM_NEWSBEUTER },
	{ OP_CLEARTAG, "clear-tag", "^T", _("Clear current tag"), KM_NEWSBEUTER },
	{ OP_SETTAG, "set-tag", "t", _("Select tag"), KM_NEWSBEUTER },
	{ OP_SEARCH, "open-search", "/", _("Open search dialog"), KM_NEWSBEUTER },
	{ OP_ENQUEUE, "enqueue", "e", _("Add download to queue"), KM_NEWSBEUTER },
	{ OP_RELOADURLS, "reload-urls", "^R", _("Reload the list of URLs from the configuration"), KM_NEWSBEUTER },
	{ OP_PB_DOWNLOAD, "pb-download", "d", _("Download file"), KM_PODBEUTER },
	{ OP_PB_CANCEL, "pb-cancel", "c", _("Cancel download"), KM_PODBEUTER },
	{ OP_PB_DELETE, "pb-delete", "D", _("Mark download as deleted"), KM_PODBEUTER },
	{ OP_PB_PURGE, "pb-purge", "P", _("Purge finished and deleted downloads from queue"), KM_PODBEUTER },
	{ OP_PB_TOGGLE_DLALL, "pb-toggle-download-all", "a", _("Toggle automatic download on/off"), KM_PODBEUTER },
	{ OP_PB_PLAY, "pb-play", "p", _("Start player with currently selected download"), KM_PODBEUTER },
	{ OP_PB_MOREDL, "pb-increase-max-dls", "+", _("Increase the number of concurrent downloads"), KM_PODBEUTER },
	{ OP_PB_LESSDL, "pb-decreate-max-dls", "-", _("Decrease the number of concurrent downloads"), KM_PODBEUTER },
	{ OP_REDRAW, "redraw", "^L", _("Redraw screen"), KM_BOTH },
	{ OP_CMDLINE, "cmdline", ":", _("Open the commandline"), KM_NEWSBEUTER },
	{ OP_SETFILTER, "set-filter", "F", _("Set a filter"), KM_NEWSBEUTER },
	{ OP_SELECTFILTER, "select-filter", "f", _("Select a predefined filter"), KM_NEWSBEUTER },
	{ OP_CLEARFILTER, "clear-filter", "^F", _("Clear currently set filter"), KM_NEWSBEUTER },
	{ OP_BOOKMARK, "bookmark", "^B", _("Bookmark current link/article"), KM_NEWSBEUTER },
	{ OP_EDITFLAGS, "edit-flags", "^E", _("Edit flags"), KM_NEWSBEUTER },
	{ OP_NEXTFEED, "next-unread-feed", "^N", _("Go to next unread feed"), KM_NEWSBEUTER },
	{ OP_PREVFEED, "prev-unread-feed", "^P", _("Go to previous unread feed"), KM_NEWSBEUTER },
	{ OP_MACROPREFIX, "macro-prefix", ",", _("Call a macro"), KM_NEWSBEUTER },
	{ OP_DELETE, "delete-article", "D", _("Delete article"), KM_NEWSBEUTER },
	{ OP_PURGE_DELETED, "purge-deleted", "$", _("Purge deleted articles"), KM_NEWSBEUTER },

	{ OP_SK_UP, "up", "UP", NULL, KM_SYSKEYS },
	{ OP_SK_DOWN, "down", "DOWN", NULL, KM_SYSKEYS },
	{ OP_SK_PGUP, "pageup", "PAGEUP", NULL, KM_SYSKEYS },
	{ OP_SK_PGDOWN, "pagedown", "PAGEDOWN", NULL, KM_SYSKEYS },

	{ OP_INT_END_QUESTION, "XXXNOKEY-end-question", "end-question", NULL, KM_INTERNAL },
	{ OP_INT_CANCEL_QNA, "XXXNOKEY-cancel-qna", "cancel-qna", NULL, KM_INTERNAL },
	{ OP_INT_QNA_NEXTHIST, "XXXNOKEY-qna-next-history", "qna-next-history", NULL, KM_INTERNAL },
	{ OP_INT_QNA_PREVHIST, "XXXNOKEY-qna-prev-history", "qna-prev-history", NULL, KM_INTERNAL },

	{ OP_INT_RESIZE, "RESIZE", "internal-resize", NULL, KM_INTERNAL },

	{ OP_NIL, NULL, NULL, NULL, 0 }
};

keymap::keymap(unsigned flags) {
	/*
	 * At startup, initialize the keymap with the default settings from the list above.
	 */
	for (int i=0;opdescs[i].op != OP_NIL;++i) {
		if (opdescs[i].flags & (flags | KM_INTERNAL | KM_SYSKEYS)) {
			keymap_[opdescs[i].default_key] = opdescs[i].op;
		}
	}
}

void keymap::get_keymap_descriptions(std::vector<keymap_desc>& descs, unsigned short flags) {
	/*
	 * Here we return the keymap descriptions for the specified application (handed to us via flags)
	 * This is used for the help screen.
	 */
	for (std::map<std::string,operation>::iterator it=keymap_.begin();it!=keymap_.end();++it) {
		operation op = it->second;
		if (op != OP_NIL) {
			std::string helptext;
			std::string opname;
			bool add = false;
			for (int i=0;opdescs[i].help_text;++i) {
				if (opdescs[i].op == op && opdescs[i].flags & flags) {
					helptext = gettext(opdescs[i].help_text);
					opname = opdescs[i].opstr;
					add = true;
				}
			}
			if (add) {
				keymap_desc desc;
				desc.key = it->first;
				desc.cmd = opname;
				desc.desc = helptext;
				descs.push_back(desc);
			}
		}
	}
}

keymap::~keymap() { }

void keymap::set_key(operation op, const std::string& key) {
	GetLogger().log(LOG_DEBUG,"keymap::set_key(%d,%s) called", op, key.c_str());
	keymap_[key] = op;
}

void keymap::unset_key(const std::string& key) {
	GetLogger().log(LOG_DEBUG,"keymap::unset_key(%s) called", key.c_str());
	keymap_[key] = OP_NIL;
}

operation keymap::get_opcode(const std::string& opstr) {
	for (int i=0;opdescs[i].opstr;++i) {
		if (opstr == opdescs[i].opstr) {
			return opdescs[i].op;
		}
	}
	return OP_NIL;
}

char keymap::get_key(const std::string& keycode) {
	if (keycode == "ENTER") {
		return '\n';
	} else if (keycode == "ESC") {
		return 27;
	} else if (keycode.length() == 2 && keycode[0] == '^') {
		char chr = keycode[1];
		return chr - '@';
	} else if (keycode.length() == 1) { // TODO: implement more keys
		return keycode[0];
	}
	return 0;
}

operation keymap::get_operation(const std::string& keycode) {
	std::string key;
	if (keycode.length() > 0) {
		key = keycode;
	} else {
		key = "NIL";
	}
	return keymap_[key];
}

action_handler_status keymap::handle_action(const std::string& action, const std::vector<std::string>& params) {
	/*
	 * The keymap acts as config_action_handler so that all the key-related configuration is immediately
	 * handed to it.
	 */
	GetLogger().log(LOG_DEBUG,"keymap::handle_action(%s, ...) called",action.c_str());
	if (action == "bind-key") {
		if (params.size() < 2) {
			return AHS_TOO_FEW_PARAMS;
		} else {
			operation op = get_opcode(params[1]);
			if (op > OP_SK_MIN && op < OP_SK_MAX)
				unset_key(getkey(get_opcode(params[1])));
			set_key(get_opcode(params[1]), params[0]);
			return AHS_OK;
		}
	} else if (action == "unbind-key") {
		if (params.size() < 1) {
			return AHS_TOO_FEW_PARAMS;
		} else {
			unset_key(params[0]);
			return AHS_OK;
		}
	} else if (action == "macro") {
		if (params.size() < 1) {
			return AHS_TOO_FEW_PARAMS;
		}
		std::vector<std::string>::const_iterator it = params.begin();
		std::string macrokey = *it;
		std::vector<macrocmd> cmds;
		macrocmd tmpcmd;
		tmpcmd.op = OP_NIL;
		bool first = true;
		it++;

		while (it != params.end()) {
			if (first && *it != ";") {
				tmpcmd.op = get_opcode(*it);
				GetLogger().log(LOG_DEBUG, "keymap::handle_action: new operation `%s' (op = %u)", it->c_str(), tmpcmd.op);
				if (tmpcmd.op == OP_NIL)
					return AHS_INVALID_PARAMS;
				first = false;
			} else {
				if (*it == ";") {
					if (tmpcmd.op != OP_NIL)
						cmds.push_back(tmpcmd);
					tmpcmd.op = OP_NIL;
					tmpcmd.args.clear();
					first = true;
				} else {
					GetLogger().log(LOG_DEBUG, "keymap::handle_action: new parameter `%s' (op = %u)", it->c_str());
					tmpcmd.args.push_back(*it);
				}
			}
			++it;
		}
		if (tmpcmd.op != OP_NIL)
			cmds.push_back(tmpcmd);

		macros_[macrokey] = cmds;
		return AHS_OK;
	} else
		return AHS_INVALID_PARAMS;
}

std::string keymap::getkey(operation op) {
	for (std::map<std::string,operation>::iterator it=keymap_.begin(); it!=keymap_.end(); ++it) {
		if (it->second == op)
			return it->first;
	}
	return "<none>";
}

std::vector<macrocmd> keymap::get_macro(const std::string& key) {
	for (std::map<std::string,std::vector<macrocmd> >::iterator it=macros_.begin(); it!=macros_.end(); ++it) {
		if (it->first == key) {
			return it->second;
		}
	}
	std::vector<macrocmd> dummyvector;
	return dummyvector;
}

}
<commit_msg>Andreas Krennmair: 	list all keys that are assigned to one function in help screen (fixes issue #82).<commit_after>#include <keymap.h>
#include <logger.h>
#include <vector>
#include <iostream>
#include <config.h>

namespace newsbeuter {

struct op_desc {
	operation op;
	const char * opstr;
	const char * default_key;
	const char * help_text;
	unsigned short flags;
};

/*
 * This is the list of operations, defining operation, operation name (for keybindings), default key, description, and where it's valid
 */
static op_desc opdescs[] = {
	{ OP_OPEN, "open", "ENTER", _("Open feed/article"), KM_NEWSBEUTER },
	{ OP_QUIT, "quit", "q", _("Return to previous dialog/Quit"), KM_BOTH },
	{ OP_RELOAD, "reload", "r", _("Reload currently selected feed"), KM_NEWSBEUTER },
	{ OP_RELOADALL, "reload-all", "R", _("Reload all feeds"), KM_NEWSBEUTER },
	{ OP_MARKFEEDREAD, "mark-feed-read", "A", _("Mark feed read"), KM_NEWSBEUTER },
	{ OP_MARKALLFEEDSREAD, "mark-all-feeds-read", "C", _("Mark all feeds read"), KM_NEWSBEUTER },
	{ OP_SAVE, "save", "s", _("Save article"), KM_NEWSBEUTER },
	{ OP_NEXTUNREAD, "next-unread", "n", _("Go to next unread article"), KM_NEWSBEUTER },
	{ OP_PREVUNREAD, "prev-unread", "p", _("Go to previous unread article"), KM_NEWSBEUTER },
	{ OP_OPENINBROWSER, "open-in-browser", "o", _("Open article in browser"), KM_NEWSBEUTER },
	{ OP_HELP, "help", "?", _("Open help dialog"), KM_BOTH },
	{ OP_TOGGLESOURCEVIEW, "toggle-source-view", "^U", _("Toggle source view"), KM_NEWSBEUTER },
	{ OP_TOGGLEITEMREAD, "toggle-article-read", "N", _("Toggle read status for article"), KM_NEWSBEUTER },
	{ OP_TOGGLESHOWREAD, "toggle-show-read-feeds", "l", _("Toggle show read feeds/articles"), KM_NEWSBEUTER },
	{ OP_SHOWURLS, "show-urls", "u", _("Show URLs in current article"), KM_NEWSBEUTER },
	{ OP_CLEARTAG, "clear-tag", "^T", _("Clear current tag"), KM_NEWSBEUTER },
	{ OP_SETTAG, "set-tag", "t", _("Select tag"), KM_NEWSBEUTER },
	{ OP_SEARCH, "open-search", "/", _("Open search dialog"), KM_NEWSBEUTER },
	{ OP_ENQUEUE, "enqueue", "e", _("Add download to queue"), KM_NEWSBEUTER },
	{ OP_RELOADURLS, "reload-urls", "^R", _("Reload the list of URLs from the configuration"), KM_NEWSBEUTER },
	{ OP_PB_DOWNLOAD, "pb-download", "d", _("Download file"), KM_PODBEUTER },
	{ OP_PB_CANCEL, "pb-cancel", "c", _("Cancel download"), KM_PODBEUTER },
	{ OP_PB_DELETE, "pb-delete", "D", _("Mark download as deleted"), KM_PODBEUTER },
	{ OP_PB_PURGE, "pb-purge", "P", _("Purge finished and deleted downloads from queue"), KM_PODBEUTER },
	{ OP_PB_TOGGLE_DLALL, "pb-toggle-download-all", "a", _("Toggle automatic download on/off"), KM_PODBEUTER },
	{ OP_PB_PLAY, "pb-play", "p", _("Start player with currently selected download"), KM_PODBEUTER },
	{ OP_PB_MOREDL, "pb-increase-max-dls", "+", _("Increase the number of concurrent downloads"), KM_PODBEUTER },
	{ OP_PB_LESSDL, "pb-decreate-max-dls", "-", _("Decrease the number of concurrent downloads"), KM_PODBEUTER },
	{ OP_REDRAW, "redraw", "^L", _("Redraw screen"), KM_BOTH },
	{ OP_CMDLINE, "cmdline", ":", _("Open the commandline"), KM_NEWSBEUTER },
	{ OP_SETFILTER, "set-filter", "F", _("Set a filter"), KM_NEWSBEUTER },
	{ OP_SELECTFILTER, "select-filter", "f", _("Select a predefined filter"), KM_NEWSBEUTER },
	{ OP_CLEARFILTER, "clear-filter", "^F", _("Clear currently set filter"), KM_NEWSBEUTER },
	{ OP_BOOKMARK, "bookmark", "^B", _("Bookmark current link/article"), KM_NEWSBEUTER },
	{ OP_EDITFLAGS, "edit-flags", "^E", _("Edit flags"), KM_NEWSBEUTER },
	{ OP_NEXTFEED, "next-unread-feed", "^N", _("Go to next unread feed"), KM_NEWSBEUTER },
	{ OP_PREVFEED, "prev-unread-feed", "^P", _("Go to previous unread feed"), KM_NEWSBEUTER },
	{ OP_MACROPREFIX, "macro-prefix", ",", _("Call a macro"), KM_NEWSBEUTER },
	{ OP_DELETE, "delete-article", "D", _("Delete article"), KM_NEWSBEUTER },
	{ OP_PURGE_DELETED, "purge-deleted", "$", _("Purge deleted articles"), KM_NEWSBEUTER },

	{ OP_SK_UP, "up", "UP", NULL, KM_SYSKEYS },
	{ OP_SK_DOWN, "down", "DOWN", NULL, KM_SYSKEYS },
	{ OP_SK_PGUP, "pageup", "PAGEUP", NULL, KM_SYSKEYS },
	{ OP_SK_PGDOWN, "pagedown", "PAGEDOWN", NULL, KM_SYSKEYS },

	{ OP_INT_END_QUESTION, "XXXNOKEY-end-question", "end-question", NULL, KM_INTERNAL },
	{ OP_INT_CANCEL_QNA, "XXXNOKEY-cancel-qna", "cancel-qna", NULL, KM_INTERNAL },
	{ OP_INT_QNA_NEXTHIST, "XXXNOKEY-qna-next-history", "qna-next-history", NULL, KM_INTERNAL },
	{ OP_INT_QNA_PREVHIST, "XXXNOKEY-qna-prev-history", "qna-prev-history", NULL, KM_INTERNAL },

	{ OP_INT_RESIZE, "RESIZE", "internal-resize", NULL, KM_INTERNAL },

	{ OP_NIL, NULL, NULL, NULL, 0 }
};

keymap::keymap(unsigned flags) {
	/*
	 * At startup, initialize the keymap with the default settings from the list above.
	 */
	for (int i=0;opdescs[i].op != OP_NIL;++i) {
		if (opdescs[i].flags & (flags | KM_INTERNAL | KM_SYSKEYS)) {
			keymap_[opdescs[i].default_key] = opdescs[i].op;
		}
	}
}

void keymap::get_keymap_descriptions(std::vector<keymap_desc>& descs, unsigned short flags) {
	/*
	 * Here we return the keymap descriptions for the specified application (handed to us via flags)
	 * This is used for the help screen.
	 */
	for (int i=0;opdescs[i].help_text;++i) {
		bool already_added = false;
		for (std::map<std::string,operation>::iterator it=keymap_.begin();it!=keymap_.end();++it) {
			operation op = it->second;
			if (op != OP_NIL) {
				if (opdescs[i].op == op && opdescs[i].flags & flags) {
					keymap_desc desc;
					desc.key = it->first;
					if (!already_added) {
						desc.cmd = opdescs[i].opstr;
						desc.desc = gettext(opdescs[i].help_text);
						already_added = true;
					}
					descs.push_back(desc);
				}
			}
		}
	}
}

keymap::~keymap() { }

void keymap::set_key(operation op, const std::string& key) {
	GetLogger().log(LOG_DEBUG,"keymap::set_key(%d,%s) called", op, key.c_str());
	keymap_[key] = op;
}

void keymap::unset_key(const std::string& key) {
	GetLogger().log(LOG_DEBUG,"keymap::unset_key(%s) called", key.c_str());
	keymap_[key] = OP_NIL;
}

operation keymap::get_opcode(const std::string& opstr) {
	for (int i=0;opdescs[i].opstr;++i) {
		if (opstr == opdescs[i].opstr) {
			return opdescs[i].op;
		}
	}
	return OP_NIL;
}

char keymap::get_key(const std::string& keycode) {
	if (keycode == "ENTER") {
		return '\n';
	} else if (keycode == "ESC") {
		return 27;
	} else if (keycode.length() == 2 && keycode[0] == '^') {
		char chr = keycode[1];
		return chr - '@';
	} else if (keycode.length() == 1) { // TODO: implement more keys
		return keycode[0];
	}
	return 0;
}

operation keymap::get_operation(const std::string& keycode) {
	std::string key;
	if (keycode.length() > 0) {
		key = keycode;
	} else {
		key = "NIL";
	}
	return keymap_[key];
}

action_handler_status keymap::handle_action(const std::string& action, const std::vector<std::string>& params) {
	/*
	 * The keymap acts as config_action_handler so that all the key-related configuration is immediately
	 * handed to it.
	 */
	GetLogger().log(LOG_DEBUG,"keymap::handle_action(%s, ...) called",action.c_str());
	if (action == "bind-key") {
		if (params.size() < 2) {
			return AHS_TOO_FEW_PARAMS;
		} else {
			operation op = get_opcode(params[1]);
			if (op > OP_SK_MIN && op < OP_SK_MAX)
				unset_key(getkey(get_opcode(params[1])));
			set_key(get_opcode(params[1]), params[0]);
			return AHS_OK;
		}
	} else if (action == "unbind-key") {
		if (params.size() < 1) {
			return AHS_TOO_FEW_PARAMS;
		} else {
			unset_key(params[0]);
			return AHS_OK;
		}
	} else if (action == "macro") {
		if (params.size() < 1) {
			return AHS_TOO_FEW_PARAMS;
		}
		std::vector<std::string>::const_iterator it = params.begin();
		std::string macrokey = *it;
		std::vector<macrocmd> cmds;
		macrocmd tmpcmd;
		tmpcmd.op = OP_NIL;
		bool first = true;
		it++;

		while (it != params.end()) {
			if (first && *it != ";") {
				tmpcmd.op = get_opcode(*it);
				GetLogger().log(LOG_DEBUG, "keymap::handle_action: new operation `%s' (op = %u)", it->c_str(), tmpcmd.op);
				if (tmpcmd.op == OP_NIL)
					return AHS_INVALID_PARAMS;
				first = false;
			} else {
				if (*it == ";") {
					if (tmpcmd.op != OP_NIL)
						cmds.push_back(tmpcmd);
					tmpcmd.op = OP_NIL;
					tmpcmd.args.clear();
					first = true;
				} else {
					GetLogger().log(LOG_DEBUG, "keymap::handle_action: new parameter `%s' (op = %u)", it->c_str());
					tmpcmd.args.push_back(*it);
				}
			}
			++it;
		}
		if (tmpcmd.op != OP_NIL)
			cmds.push_back(tmpcmd);

		macros_[macrokey] = cmds;
		return AHS_OK;
	} else
		return AHS_INVALID_PARAMS;
}

std::string keymap::getkey(operation op) {
	for (std::map<std::string,operation>::iterator it=keymap_.begin(); it!=keymap_.end(); ++it) {
		if (it->second == op)
			return it->first;
	}
	return "<none>";
}

std::vector<macrocmd> keymap::get_macro(const std::string& key) {
	for (std::map<std::string,std::vector<macrocmd> >::iterator it=macros_.begin(); it!=macros_.end(); ++it) {
		if (it->first == key) {
			return it->second;
		}
	}
	std::vector<macrocmd> dummyvector;
	return dummyvector;
}

}
<|endoftext|>


<commit_before>#include <fstream>
#include <iostream>
#include <string>
#include <stack>

#include "create_dot.h"
struct Node {
    uint32_t call_id = 0;

    //name of function, block ...
    std::string region;
    uint32_t invocations = 0;

    Node* parent = nullptr;

    uint32_t num_children = 0;
    std::vector<Node*> children;

    double min_incl_time = std::numeric_limits<uint64_t>::max();
    double max_incl_time = 0;
    double sum_incl_time = 0;
    double avg_incl_time = 0;

    double min_excl_time = std::numeric_limits<uint64_t>::max();
    double max_excl_time = 0;
    double sum_excl_time = 0;
    double avg_excl_time = 0;
};

typedef std::vector<Node*> Data;

Data* read_data( AllData& alldata) {

    Data* data = new Data;
    std::stack<Node*> parent_nodes;

    int call_id = 0;
    // uint64_t total_time = alldata[0].

    for ( const auto& region : alldata.call_path_tree ) {

        Node* node = new Node;

        //call_id
        node->call_id = call_id;
        ++call_id;

        //regionname
        std::string region_name = alldata.definitions.regions.get(region.function_id)->name;
        node->region = region_name;

        // number of children
        node->num_children = region.children.size();

        // mpi time resolution
        double timerResolution = (double)alldata.metaData.timerResolution;

        // acumulate data over all locations
        for (const auto& location : region.node_data) {
            // filter per rank
            if(alldata.params.rank == -1 || alldata.params.rank == location.first){

                node->invocations += location.second.f_data.count;

                double incl_time = location.second.f_data.incl_time / timerResolution;
                if (node->min_incl_time > incl_time)
                    node->min_incl_time = incl_time;
                if (node->max_incl_time < incl_time)
                    node->max_incl_time = incl_time;
                node->sum_incl_time += incl_time;

                double excl_time = location.second.f_data.excl_time / timerResolution;
                if (node->min_excl_time > excl_time)
                    node->min_excl_time = excl_time;
                if (node->max_excl_time < excl_time)
                    node->max_excl_time = excl_time;
                node->sum_excl_time += excl_time;
            }
        }

        // average time
        node->avg_incl_time = node->sum_incl_time / region.node_data.size();
        node->avg_excl_time = node->sum_excl_time / region.node_data.size();

        if(parent_nodes.size() != 0){

            // get parent of this node
            // add this node to their children
            parent_nodes.top()->children.push_back(node);

            // add parent to this node
            node->parent = parent_nodes.top();
            parent_nodes.pop();

        }

        // temporarily add this node to stack for child-parent relation see above
        for( int i = 0; i < node->num_children; ++i )
            parent_nodes.push(node);

        //finish
        data->push_back(node);
    }
    return data;
}

class Dot_writer{
public:
    Dot_writer(Data& data, Params& params): data(data), params(params)
    {}
private:
    std::ofstream result_file;
    Params params;
    Data data;

    //metaData
    double min_time = std::numeric_limits<uint64_t>::max();
    double max_time = 0;
    double timerange = 0;
    std::map<uint32_t, Node*> printed_nodes;

    // graph parameter
    std::string splines = "ortho";
    float ranksep = 1.5;
    std::string shape = "record";
    std::string colorscheme = "spectral9";
public:
    void print(){
        for( const auto& region : data ){
            if(params.node_min_ratio == 0 || params.node_min_ratio == 100){
                print_node(region);
            }
            else
            {
                if(region->sum_excl_time > params.node_min_ratio)
                    print_node(region);
                else if( filter_min_ratio(region) )
                    print_node_partial(region);
            }
        }
    }

    bool open(std::string filename = "result.dot"){
        result_file.open(filename);
        if(result_file.is_open()){
            // print header of graph file
            result_file
                << "digraph call_tree {\n"
                << "graph [splines=ortho, ranksep=1.5];\n"
                << "node [shape = record, colorscheme=spectral9];\n"
                << "edge [];\n"
            << std::endl;
            getMeta();
            return true;
        }
        else
        {
            std::cout << "Error opening file" << std::endl;
            return false;
        }
    }

    void close(){
        result_file << "}" << std::endl;
        result_file.close();
    }

    void getMeta(){

        for( const auto& region : data ){
            if( region->sum_excl_time < min_time )
                min_time = region->sum_excl_time;
            if( region->sum_excl_time > max_time )
                max_time = region->sum_excl_time;
        }
        timerange = max_time - min_time;
    }

    // go through all nodes, returns true when filter apply to any descendent
    bool filter_min_ratio(const Node* node){
        for(const auto& child : node->children){
            if(filter_min_ratio(child) == true)
                return true;
        }
        if(node->sum_excl_time > params.node_min_ratio)
            return true;

        return false;
    }

    void print_node_partial(Node* region){
        result_file
                << "\"" << region->call_id << "\" ["
                << "label = \""
                << region->region << "\"" << std::endl;
        // colorize node, 9 colors
        int num_colors = 9;
        int color_code = num_colors;
        for( int i = 0; i < num_colors; ++i ){
            if( region->sum_excl_time >= timerange/num_colors*i+min_time )
                color_code = num_colors-i;
        }
        result_file
            << "fillcolor=" << color_code << ",\n"
            << "style=filled\n";

        // closing tag
        result_file << "];\n" << std::endl;

        // set edge netween node and parent
        if( region->parent){
            result_file
                << region->parent->call_id
                << " -> "
                << region->call_id
                << ";"
            << std::endl;
        }
    }

    void print_node(Node* region){
        // filter nodes
        result_file
            << "\"" << region->call_id << "\" [\n"
            << " label = \""
            << region->region << "\\l\n"
            << " invocations: " << region->invocations << "\\l\n"
            << " include time:" << "\\l\n"
            << "  min: " << region->min_incl_time << "\\l\n"
            << "  max: " << region->max_incl_time << "\\l\n"
            << "  sum: " << region->sum_incl_time << "\\l\n"
            << "  avg: " << region->avg_incl_time << "\\l\n"
            << " exclude time:" << "\\l\n"
            << "  min: " << region->min_excl_time << "\\l\n"
            << "  max: " << region->max_excl_time << "\\l\n"
            << "  sum: " << region->sum_excl_time << "\\l\n"
            << "  avg: " << region->avg_excl_time << "\\l\n"
            << " \"\n";

        // colorize node, 9 colors
        int num_colors = 9;
        int color_code = num_colors;
        for( int i = 0; i < num_colors; ++i ){
            if( region->sum_excl_time >= timerange/num_colors*i+min_time )
                color_code = num_colors-i;
        }
        result_file
            << " fillcolor=" << color_code << ",\n"
            << " style=filled\n";

        // closing tag
        result_file << "];\n" << std::endl;

        // set edge netween node and parent
        if( region->parent){
            result_file
                << region->parent->call_id
                << " -> "
                << region->call_id
                << ";"
            << std::endl;
        }
    }
};

bool CreateDot(AllData& alldata) {
    alldata.verbosePrint(1, true, "producing dot output");
    Data* data = read_data(alldata);
    Dot_writer writer(*data, alldata.params);
    writer.open("res.dot");
    writer.print();
    writer.close();
    return true;
}<commit_msg>add function to draw all ancestor of one node<commit_after>#include <fstream>
#include <iostream>
#include <string>
#include <stack>

#include "create_dot.h"
struct Node {
    uint32_t call_id = 0;

    //name of function, block ...
    std::string region;
    uint32_t invocations = 0;

    Node* parent = nullptr;

    uint32_t num_children = 0;
    std::vector<Node*> children;

    double min_incl_time = std::numeric_limits<uint64_t>::max();
    double max_incl_time = 0;
    double sum_incl_time = 0;
    double avg_incl_time = 0;

    double min_excl_time = std::numeric_limits<uint64_t>::max();
    double max_excl_time = 0;
    double sum_excl_time = 0;
    double avg_excl_time = 0;
};

typedef std::vector<Node*> Data;

Data* read_data( AllData& alldata) {

    Data* data = new Data;
    std::stack<Node*> parent_nodes;

    int call_id = 0;
    // uint64_t total_time = alldata[0].

    for ( const auto& region : alldata.call_path_tree ) {

        Node* node = new Node;

        //call_id
        node->call_id = call_id;
        ++call_id;

        //regionname
        std::string region_name = alldata.definitions.regions.get(region.function_id)->name;
        node->region = region_name;

        // number of children
        node->num_children = region.children.size();

        // mpi time resolution
        double timerResolution = (double)alldata.metaData.timerResolution;

        // acumulate data over all locations
        for (const auto& location : region.node_data) {
            // filter per rank
            if(alldata.params.rank == -1 || alldata.params.rank == location.first){

                node->invocations += location.second.f_data.count;

                double incl_time = location.second.f_data.incl_time / timerResolution;
                if (node->min_incl_time > incl_time)
                    node->min_incl_time = incl_time;
                if (node->max_incl_time < incl_time)
                    node->max_incl_time = incl_time;
                node->sum_incl_time += incl_time;

                double excl_time = location.second.f_data.excl_time / timerResolution;
                if (node->min_excl_time > excl_time)
                    node->min_excl_time = excl_time;
                if (node->max_excl_time < excl_time)
                    node->max_excl_time = excl_time;
                node->sum_excl_time += excl_time;
            }
        }

        // average time
        node->avg_incl_time = node->sum_incl_time / region.node_data.size();
        node->avg_excl_time = node->sum_excl_time / region.node_data.size();

        if(parent_nodes.size() != 0){

            // get parent of this node
            // add this node to their children
            parent_nodes.top()->children.push_back(node);

            // add parent to this node
            node->parent = parent_nodes.top();
            parent_nodes.pop();

        }

        // temporarily add this node to stack for child-parent relation see above
        for( int i = 0; i < node->num_children; ++i )
            parent_nodes.push(node);

        //finish
        data->push_back(node);
    }
    return data;
}

class Dot_writer{
public:
    Dot_writer(Data& data, Params& params): data(data), params(params)
    {}
private:
    std::ofstream result_file;
    Params params;
    Data data;

    //metaData
    double min_time = std::numeric_limits<uint64_t>::max();
    double max_time = 0;
    double timerange = 0;
    std::map<uint32_t, Node*> printed_nodes;

    // graph parameter
    std::string splines = "ortho";
    float ranksep = 1.5;
    std::string shape = "record";
    std::string colorscheme = "spectral9";
public:

    bool open(std::string filename = "result.dot"){
        result_file.open(filename);
        if(result_file.is_open()){
            // print header of graph file
            result_file
                << "digraph call_tree {\n"
                << "graph [splines=ortho, ranksep=1.5];\n"
                << "node [shape = record, colorscheme=spectral9];\n"
                << "edge [];\n"
            << std::endl;
            getMeta();
            return true;
        }
        else
        {
            std::cout << "Error opening file" << std::endl;
            return false;
        }
    }

    void close(){
        result_file << "}" << std::endl;
        result_file.close();
    }

    void getMeta(){

        for( const auto& region : data ){
            if( region->sum_excl_time < min_time )
                min_time = region->sum_excl_time;
            if( region->sum_excl_time > max_time )
                max_time = region->sum_excl_time;
        }
        timerange = max_time - min_time;
    }

    void print(){

        for( const auto& region : data ){
            if(params.node_min_ratio == 0 || params.node_min_ratio == 100){
                print_node(*region);
            }
            else {
                if(region->sum_excl_time > params.node_min_ratio){
                    print_node(*region);
                    print_predecessor(*region);
                }
            }
        }
    }

    // draw all predessor
    void print_predecessor( Node& region){
        Node* curr = &region;
        while( curr->parent != nullptr){
            curr = region.parent;
            // draw if parent node hasn't been drawn yet else break
            if(printed_nodes.find(curr->call_id) == printed_nodes.end())
                print_node_partial(*curr);
            else
                break;
        }
    }

    void print_node_partial(Node* region){
        result_file
                << "\"" << region->call_id << "\" ["
                << "label = \""
                << region->region << "\"" << std::endl;
        // colorize node, 9 colors
        int num_colors = 9;
        int color_code = num_colors;
        for( int i = 0; i < num_colors; ++i ){
            if( region->sum_excl_time >= timerange/num_colors*i+min_time )
                color_code = num_colors-i;
        }
        result_file
            << "fillcolor=" << color_code << ",\n"
            << "style=filled\n";

        // closing tag
        result_file << "];\n" << std::endl;

        // set edge netween node and parent
        if( region->parent){
            result_file
                << region->parent->call_id
                << " -> "
                << region->call_id
                << ";"
            << std::endl;
        }

        printed_nodes[region.call_id] = &region;
    }

    void print_node(Node* region){
        // filter nodes
        result_file
            << "\"" << region->call_id << "\" [\n"
            << " label = \""
            << region->region << "\\l\n"
            << " invocations: " << region->invocations << "\\l\n"
            << " include time:" << "\\l\n"
            << "  min: " << region->min_incl_time << "\\l\n"
            << "  max: " << region->max_incl_time << "\\l\n"
            << "  sum: " << region->sum_incl_time << "\\l\n"
            << "  avg: " << region->avg_incl_time << "\\l\n"
            << " exclude time:" << "\\l\n"
            << "  min: " << region->min_excl_time << "\\l\n"
            << "  max: " << region->max_excl_time << "\\l\n"
            << "  sum: " << region->sum_excl_time << "\\l\n"
            << "  avg: " << region->avg_excl_time << "\\l\n"
            << " \"\n";

        // colorize node, 9 colors
        int num_colors = 9;
        int color_code = num_colors;
        for( int i = 0; i < num_colors; ++i ){
            if( region->sum_excl_time >= timerange/num_colors*i+min_time )
                color_code = num_colors-i;
        }
        result_file
            << " fillcolor=" << color_code << ",\n"
            << " style=filled\n";

        // closing tag
        result_file << "];\n" << std::endl;

        // set edge netween node and parent
        if( region->parent){
            result_file
                << region->parent->call_id
                << " -> "
                << region->call_id
                << ";"
            << std::endl;
        }
    }
};

bool CreateDot(AllData& alldata) {
    alldata.verbosePrint(1, true, "producing dot output");
    Data* data = read_data(alldata);
    Dot_writer writer(*data, alldata.params);
    writer.open("res.dot");
    writer.print();
    writer.close();
    return true;
}<|endoftext|>


<commit_before>// FRAGMENT(includes)
#include <iostream>
#include <seqan/store.h>
#include <seqan/misc/misc_svg.h>

using namespace seqan;

int main ()
{
    FragmentStore<> store;
    loadContigs(store, "ex1.fa");
    std::ifstream file("ex1.sam");
    read(file, store, Sam());

// FRAGMENT(ascii)
    AlignedReadLayout layout;
    layoutAlignment(layout, store);
    for (unsigned i = 0; i < length(store.contigStore); ++i)
        printAlignment(std::cout, Raw(), layout, store, i, 50, 150, 0, 30);

// FRAGMENT(svg)
    SVGFile svg("layout.svg");
    for (unsigned i = 0; i < length(store.contigStore); ++i)
        printAlignment(svg, Raw(), layout, store, i, 50, 150, 0, 30);

	return 0;
}
<commit_msg><commit_after>// FRAGMENT(includes)
#include <iostream>
#include <seqan/store.h>
#include <seqan/misc/misc_svg.h>

using namespace seqan;

int main ()
{
    FragmentStore<> store;
    loadContigs(store, "ex1.fa");
    std::ifstream file("ex1.sam");
    read(file, store, Sam());

// FRAGMENT(ascii)
    AlignedReadLayout layout;
    layoutAlignment(layout, store);
    printAlignment(std::cout, Raw(), layout, store, 1, 0, 150, 0, 36);

// FRAGMENT(svg)
    SVGFile svg("layout.svg");
    printAlignment(svg, Raw(), layout, store, 1, 0, 150, 0, 36);

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Consistently use Chromium style for identifiers.<commit_after><|endoftext|>