<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

#include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <LibreOfficeKit/LibreOfficeKitInit.h>
#include "../lokdocview_quad/lokdocview_quad.h"

#include <com/sun/star/awt/Key.hpp>

static int help()
{
    fprintf( stderr, "Usage: gtktiledviewer <absolute-path-to-libreoffice-install> <path-to-document>\n" );
    return 1;
}

static GtkWidget* pDocView;
static GtkWidget* pDocViewQuad;
static GtkWidget* pVBox;
// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
static GtkComboBoxText* pPartSelector;
#endif

static LibreOfficeKit* pOffice;
static char* pFileName;

const float fZooms[] = { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 5.0 };

void changeZoom( GtkWidget* pButton, gpointer /* pItem */ )
{
    const char *sName = gtk_tool_button_get_stock_id( GTK_TOOL_BUTTON(pButton) );

    float fZoom = 0;
    float fCurrentZoom = 0;

    if ( pDocView )
    {
        fCurrentZoom = lok_docview_get_zoom( LOK_DOCVIEW(pDocView) );
    }
    else if ( pDocViewQuad )
    {
        fCurrentZoom = lok_docview_quad_get_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad) );
    }

    if ( strcmp(sName, "gtk-zoom-in") == 0)
    {
        for ( unsigned int i = 0; i < sizeof( fZooms ) / sizeof( fZooms[0] ); i++ )
        {
            if ( fCurrentZoom < fZooms[i] )
            {
                fZoom = fZooms[i];
                break;
            }
        }
    }
    else if ( strcmp(sName, "gtk-zoom-100") == 0)
    {
        fZoom = 1;
    }
    else if ( strcmp(sName, "gtk-zoom-fit") == 0)
    {
        // TODO -- will need access to lokdocview internals?
    }
    else if ( strcmp(sName, "gtk-zoom-out") == 0)
    {
        for ( unsigned int i = 0; i < sizeof( fZooms ) / sizeof( fZooms[0] ); i++ )
        {
            if ( fCurrentZoom > fZooms[i] )
            {
                fZoom = fZooms[i];
            }
        }
    }

    if ( fZoom != 0 )
    {
        if ( pDocView )
        {
            lok_docview_set_zoom( LOK_DOCVIEW(pDocView), fZoom );
        }
        else if ( pDocViewQuad )
        {
            lok_docview_quad_set_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad), fZoom );
        }
    }
}

void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
{
    if ( pDocView )
    {
        const float fCurrentZoom = lok_docview_get_zoom( LOK_DOCVIEW(pDocView) );
        gtk_widget_destroy( pDocView );
        pDocView = 0;
        pDocViewQuad = lok_docview_quad_new( pOffice );
        gtk_container_add( GTK_CONTAINER(pVBox), pDocViewQuad );
        gtk_widget_show( pDocViewQuad );

        lok_docview_quad_set_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad), fCurrentZoom );
        lok_docview_quad_open_document( LOK_DOCVIEW_QUAD(pDocViewQuad), pFileName );
    }
    else if ( pDocViewQuad )
    {
        const float fCurrentZoom = lok_docview_quad_get_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad) );
        gtk_widget_destroy( pDocViewQuad );
        pDocViewQuad = 0;
        pDocView = lok_docview_new( pOffice );
        gtk_container_add( GTK_CONTAINER(pVBox), pDocView );
        gtk_widget_show( pDocView );

        lok_docview_set_zoom( LOK_DOCVIEW(pDocView), fCurrentZoom );
        lok_docview_open_document( LOK_DOCVIEW(pDocView), pFileName );
    }
}

/// Receives a key press or release event.
static void signalKey(GtkWidget* /*pWidget*/, GdkEventKey* pEvent, gpointer /*pData*/)
{
    LOKDocView* pLOKDocView = LOK_DOCVIEW(pDocView);
    int nCode = 0;

    if (!pLOKDocView->m_bEdit)
    {
        g_info("signalKey: not in edit mode, ignore");
        return;
    }

    switch (pEvent->keyval)
    {
    case GDK_BackSpace:
        nCode = com::sun::star::awt::Key::BACKSPACE;
        break;
    case GDK_Return:
        nCode = com::sun::star::awt::Key::RETURN;
        break;
    default:
        if (pEvent->keyval >= GDK_F1 && pEvent->keyval <= GDK_F26)
            nCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_F1);
        else
            nCode = gdk_keyval_to_unicode(pEvent->keyval);
    }

    if (pEvent->type == GDK_KEY_RELEASE)
        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, LOK_KEYEVENT_KEYUP, nCode);
    else
        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, LOK_KEYEVENT_KEYINPUT, nCode);
}

// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
void populatePartSelector()
{
    gtk_list_store_clear( GTK_LIST_STORE(
                              gtk_combo_box_get_model(
                                  GTK_COMBO_BOX(pPartSelector) )) );

    if ( !pDocView )
    {
        return;
    }

    const int nMaxLength = 50;
    char sText[nMaxLength];

    int nParts = lok_docview_get_parts( LOK_DOCVIEW(pDocView) );
    for ( int i = 0; i < nParts; i++ )
    {
        char* pName = lok_docview_get_part_name( LOK_DOCVIEW(pDocView), i );
        assert( pName );
        snprintf( sText, nMaxLength, "%i (%s)", i+1, pName );
        free( pName );

        gtk_combo_box_text_append_text( pPartSelector, sText );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX(pPartSelector),
                              lok_docview_get_part( LOK_DOCVIEW(pDocView) ) );
}

void changePart( GtkWidget* pSelector, gpointer /* pItem */ )
{
    int nPart = gtk_combo_box_get_active( GTK_COMBO_BOX(pSelector) );

    // We don't really care about the quad view for now -- it's only purpose
    // is to check that the edges of tiles aren't messed up, and no real
    // reason to maintain it to be able to show other document parts etc.
    if ( pDocView )
    {
        lok_docview_set_part( LOK_DOCVIEW(pDocView), nPart );
    }
}

void populatePartModeSelector( GtkComboBoxText* pSelector )
{
    gtk_combo_box_text_append_text( pSelector, "Default" );
    gtk_combo_box_text_append_text( pSelector, "Slide" );
    gtk_combo_box_text_append_text( pSelector, "Notes" );
    gtk_combo_box_text_append_text( pSelector, "Combined (SlideNotes)" );
    gtk_combo_box_text_append_text( pSelector, "Embedded Objects" );
    gtk_combo_box_set_active( GTK_COMBO_BOX(pSelector), 0 );
}

void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
{
    // Just convert directly back to the LibreOfficeKitPartMode enum.
    // I.e. the ordering above should match the enum member ordering.
    LibreOfficeKitPartMode ePartMode =
        LibreOfficeKitPartMode( gtk_combo_box_get_active( GTK_COMBO_BOX(pSelector) ) );

    if ( pDocView )
    {
        lok_docview_set_partmode( LOK_DOCVIEW(pDocView), ePartMode );
    }

    // The number of items could change e.g. if we change from slide
    // to embeddede obj mode -- hence we should update the part list.
    populatePartSelector();
}
#endif

int main( int argc, char* argv[] )
{
    if( argc < 3 ||
        ( argc > 1 && ( !strcmp( argv[1], "--help" ) || !strcmp( argv[1], "-h" ) ) ) )
        return help();

    if ( argv[1][0] != '/' )
    {
        fprintf(stderr, "Absolute path required to libreoffice install\n");
        return 1;
    }

    pOffice = lok_init( argv[1] );
    if ( pOffice == NULL )
        return 1;

    gtk_init( &argc, &argv );

    GtkWidget *pWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_title( GTK_WINDOW(pWindow), "LibreOffice GTK Tiled Viewer" );
    gtk_window_set_default_size(GTK_WINDOW(pWindow), 800, 600);
    g_signal_connect( pWindow, "destroy", G_CALLBACK(gtk_main_quit), NULL );

    pVBox = gtk_vbox_new( FALSE, 0 );
    gtk_container_add( GTK_CONTAINER(pWindow), pVBox );

    // Toolbar
    GtkWidget* pToolbar = gtk_toolbar_new();
    gtk_toolbar_set_style( GTK_TOOLBAR(pToolbar), GTK_TOOLBAR_ICONS );

    GtkToolItem* pZoomIn = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_IN );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomIn, 0);
    g_signal_connect( G_OBJECT(pZoomIn), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoom1 = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_100 );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoom1, -1);
    g_signal_connect( G_OBJECT(pZoom1), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoomFit = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_FIT );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomFit, -1);
    g_signal_connect( G_OBJECT(pZoomFit), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoomOut = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_OUT );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomOut, -1);
    g_signal_connect( G_OBJECT(pZoomOut), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pSeparator1 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator1, -1);

// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
    GtkToolItem* pPartSelectorToolItem = gtk_tool_item_new();
    GtkWidget* pComboBox = gtk_combo_box_text_new();
    gtk_container_add( GTK_CONTAINER(pPartSelectorToolItem), pComboBox );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pPartSelectorToolItem, -1 );
    g_signal_connect( G_OBJECT(pComboBox), "changed", G_CALLBACK(changePart), NULL );

    pPartSelector = GTK_COMBO_BOX_TEXT(pComboBox);

    GtkToolItem* pSeparator2 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator2, -1);

    GtkToolItem* pPartModeSelectorToolItem = gtk_tool_item_new();
    GtkWidget* pPartModeComboBox = gtk_combo_box_text_new();
    gtk_container_add( GTK_CONTAINER(pPartModeSelectorToolItem), pPartModeComboBox );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pPartModeSelectorToolItem, -1 );
    g_signal_connect( G_OBJECT(pPartModeComboBox), "changed", G_CALLBACK(changePartMode), NULL );
#endif

    GtkToolItem* pSeparator3 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator3, -1);

    GtkToolItem* pEnableQuadView = gtk_toggle_tool_button_new();
    gtk_tool_button_set_label( GTK_TOOL_BUTTON(pEnableQuadView), "Use Quad View" );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pEnableQuadView, -1 );
    g_signal_connect( G_OBJECT(pEnableQuadView), "toggled", G_CALLBACK(changeQuadView), NULL );

    gtk_box_pack_start( GTK_BOX(pVBox), pToolbar, FALSE, FALSE, 0 ); // Adds to top.

    // Docview
    pDocView = lok_docview_new( pOffice );
    pDocViewQuad = 0;

    // Input handling.
    g_signal_connect(pWindow, "key-press-event", G_CALLBACK(signalKey), NULL);
    g_signal_connect(pWindow, "key-release-event", G_CALLBACK(signalKey), NULL);

    gtk_container_add( GTK_CONTAINER(pVBox), pDocView );

    gtk_widget_show_all( pWindow );

    pFileName = argv[2];
    int bOpened = lok_docview_open_document( LOK_DOCVIEW(pDocView), argv[2] );
    if (!bOpened)
        g_error("main: lok_docview_open_document() failed with '%s'", pOffice->pClass->getError(pOffice));
    assert( LOK_DOCVIEW(pDocView)->pDocument );

    // GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
    populatePartSelector();
    populatePartModeSelector( GTK_COMBO_BOX_TEXT(pPartModeComboBox) );
#endif

    gtk_main();

    pOffice->pClass->destroy( pOffice );

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>libreofficekit: cosmetics<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>

#include <gdk/gdk.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

#include <LibreOfficeKit/LibreOfficeKitGtk.h>
#include <LibreOfficeKit/LibreOfficeKitInit.h>
#include "../lokdocview_quad/lokdocview_quad.h"

#include <com/sun/star/awt/Key.hpp>

static int help()
{
    fprintf( stderr, "Usage: gtktiledviewer <absolute-path-to-libreoffice-install> <path-to-document>\n" );
    return 1;
}

static GtkWidget* pDocView;
static GtkWidget* pDocViewQuad;
static GtkWidget* pVBox;
// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
static GtkComboBoxText* pPartSelector;
#endif

static LibreOfficeKit* pOffice;
static char* pFileName;

const float fZooms[] = { 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 5.0 };

void changeZoom( GtkWidget* pButton, gpointer /* pItem */ )
{
    const char *sName = gtk_tool_button_get_stock_id( GTK_TOOL_BUTTON(pButton) );

    float fZoom = 0;
    float fCurrentZoom = 0;

    if ( pDocView )
    {
        fCurrentZoom = lok_docview_get_zoom( LOK_DOCVIEW(pDocView) );
    }
    else if ( pDocViewQuad )
    {
        fCurrentZoom = lok_docview_quad_get_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad) );
    }

    if ( strcmp(sName, "gtk-zoom-in") == 0)
    {
        for ( unsigned int i = 0; i < sizeof( fZooms ) / sizeof( fZooms[0] ); i++ )
        {
            if ( fCurrentZoom < fZooms[i] )
            {
                fZoom = fZooms[i];
                break;
            }
        }
    }
    else if ( strcmp(sName, "gtk-zoom-100") == 0)
    {
        fZoom = 1;
    }
    else if ( strcmp(sName, "gtk-zoom-fit") == 0)
    {
        // TODO -- will need access to lokdocview internals?
    }
    else if ( strcmp(sName, "gtk-zoom-out") == 0)
    {
        for ( unsigned int i = 0; i < sizeof( fZooms ) / sizeof( fZooms[0] ); i++ )
        {
            if ( fCurrentZoom > fZooms[i] )
            {
                fZoom = fZooms[i];
            }
        }
    }

    if ( fZoom != 0 )
    {
        if ( pDocView )
        {
            lok_docview_set_zoom( LOK_DOCVIEW(pDocView), fZoom );
        }
        else if ( pDocViewQuad )
        {
            lok_docview_quad_set_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad), fZoom );
        }
    }
}

void changeQuadView( GtkWidget* /*pButton*/, gpointer /* pItem */ )
{
    if ( pDocView )
    {
        const float fCurrentZoom = lok_docview_get_zoom( LOK_DOCVIEW(pDocView) );
        gtk_widget_destroy( pDocView );
        pDocView = 0;
        pDocViewQuad = lok_docview_quad_new( pOffice );
        gtk_container_add( GTK_CONTAINER(pVBox), pDocViewQuad );
        gtk_widget_show( pDocViewQuad );

        lok_docview_quad_set_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad), fCurrentZoom );
        lok_docview_quad_open_document( LOK_DOCVIEW_QUAD(pDocViewQuad), pFileName );
    }
    else if ( pDocViewQuad )
    {
        const float fCurrentZoom = lok_docview_quad_get_zoom( LOK_DOCVIEW_QUAD(pDocViewQuad) );
        gtk_widget_destroy( pDocViewQuad );
        pDocViewQuad = 0;
        pDocView = lok_docview_new( pOffice );
        gtk_container_add( GTK_CONTAINER(pVBox), pDocView );
        gtk_widget_show( pDocView );

        lok_docview_set_zoom( LOK_DOCVIEW(pDocView), fCurrentZoom );
        lok_docview_open_document( LOK_DOCVIEW(pDocView), pFileName );
    }
}

/// Receives a key press or release event.
static void signalKey(GtkWidget* /*pWidget*/, GdkEventKey* pEvent, gpointer /*pData*/)
{
    LOKDocView* pLOKDocView = LOK_DOCVIEW(pDocView);
    int nCode = 0;

    if (!pLOKDocView->m_bEdit)
    {
        g_info("signalKey: not in edit mode, ignore");
        return;
    }

    switch (pEvent->keyval)
    {
    case GDK_BackSpace:
        nCode = com::sun::star::awt::Key::BACKSPACE;
        break;
    case GDK_Return:
        nCode = com::sun::star::awt::Key::RETURN;
        break;
    default:
        if (pEvent->keyval >= GDK_F1 && pEvent->keyval <= GDK_F26)
            nCode = com::sun::star::awt::Key::F1 + (pEvent->keyval - GDK_F1);
        else
            nCode = gdk_keyval_to_unicode(pEvent->keyval);
    }

    if (pEvent->type == GDK_KEY_RELEASE)
        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, LOK_KEYEVENT_KEYUP, nCode);
    else
        pLOKDocView->pOffice->pClass->postKeyEvent(pLOKDocView->pOffice, LOK_KEYEVENT_KEYINPUT, nCode);
}

// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
void populatePartSelector()
{
    gtk_list_store_clear( GTK_LIST_STORE(
                              gtk_combo_box_get_model(
                                  GTK_COMBO_BOX(pPartSelector) )) );

    if ( !pDocView )
    {
        return;
    }

    const int nMaxLength = 50;
    char sText[nMaxLength];

    int nParts = lok_docview_get_parts( LOK_DOCVIEW(pDocView) );
    for ( int i = 0; i < nParts; i++ )
    {
        char* pName = lok_docview_get_part_name( LOK_DOCVIEW(pDocView), i );
        assert( pName );
        snprintf( sText, nMaxLength, "%i (%s)", i+1, pName );
        free( pName );

        gtk_combo_box_text_append_text( pPartSelector, sText );
    }
    gtk_combo_box_set_active( GTK_COMBO_BOX(pPartSelector),
                              lok_docview_get_part( LOK_DOCVIEW(pDocView) ) );
}

void changePart( GtkWidget* pSelector, gpointer /* pItem */ )
{
    int nPart = gtk_combo_box_get_active( GTK_COMBO_BOX(pSelector) );

    // We don't really care about the quad view for now -- it's only purpose
    // is to check that the edges of tiles aren't messed up, and no real
    // reason to maintain it to be able to show other document parts etc.
    if ( pDocView )
    {
        lok_docview_set_part( LOK_DOCVIEW(pDocView), nPart );
    }
}

void populatePartModeSelector( GtkComboBoxText* pSelector )
{
    gtk_combo_box_text_append_text( pSelector, "Default" );
    gtk_combo_box_text_append_text( pSelector, "Slide" );
    gtk_combo_box_text_append_text( pSelector, "Notes" );
    gtk_combo_box_text_append_text( pSelector, "Combined (SlideNotes)" );
    gtk_combo_box_text_append_text( pSelector, "Embedded Objects" );
    gtk_combo_box_set_active( GTK_COMBO_BOX(pSelector), 0 );
}

void changePartMode( GtkWidget* pSelector, gpointer /* pItem */ )
{
    // Just convert directly back to the LibreOfficeKitPartMode enum.
    // I.e. the ordering above should match the enum member ordering.
    LibreOfficeKitPartMode ePartMode =
        LibreOfficeKitPartMode( gtk_combo_box_get_active( GTK_COMBO_BOX(pSelector) ) );

    if ( pDocView )
    {
        lok_docview_set_partmode( LOK_DOCVIEW(pDocView), ePartMode );
    }

    // The number of items could change e.g. if we change from slide
    // to embeddede obj mode -- hence we should update the part list.
    populatePartSelector();
}
#endif

int main( int argc, char* argv[] )
{
    if( argc < 3 ||
        ( argc > 1 && ( !strcmp( argv[1], "--help" ) || !strcmp( argv[1], "-h" ) ) ) )
        return help();

    if ( argv[1][0] != '/' )
    {
        fprintf(stderr, "Absolute path required to libreoffice install\n");
        return 1;
    }

    pOffice = lok_init( argv[1] );
    if ( pOffice == NULL )
        return 1;

    gtk_init( &argc, &argv );

    GtkWidget *pWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_title( GTK_WINDOW(pWindow), "LibreOfficeKit GTK Tiled Viewer" );
    gtk_window_set_default_size(GTK_WINDOW(pWindow), 800, 600);
    g_signal_connect( pWindow, "destroy", G_CALLBACK(gtk_main_quit), NULL );

    pVBox = gtk_vbox_new( FALSE, 0 );
    gtk_container_add( GTK_CONTAINER(pWindow), pVBox );

    // Toolbar
    GtkWidget* pToolbar = gtk_toolbar_new();
    gtk_toolbar_set_style( GTK_TOOLBAR(pToolbar), GTK_TOOLBAR_ICONS );

    GtkToolItem* pZoomIn = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_IN );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomIn, 0);
    g_signal_connect( G_OBJECT(pZoomIn), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoom1 = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_100 );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoom1, -1);
    g_signal_connect( G_OBJECT(pZoom1), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoomFit = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_FIT );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomFit, -1);
    g_signal_connect( G_OBJECT(pZoomFit), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pZoomOut = gtk_tool_button_new_from_stock( GTK_STOCK_ZOOM_OUT );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pZoomOut, -1);
    g_signal_connect( G_OBJECT(pZoomOut), "clicked", G_CALLBACK(changeZoom), NULL );

    GtkToolItem* pSeparator1 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator1, -1);

// GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
    GtkToolItem* pPartSelectorToolItem = gtk_tool_item_new();
    GtkWidget* pComboBox = gtk_combo_box_text_new();
    gtk_container_add( GTK_CONTAINER(pPartSelectorToolItem), pComboBox );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pPartSelectorToolItem, -1 );
    g_signal_connect( G_OBJECT(pComboBox), "changed", G_CALLBACK(changePart), NULL );

    pPartSelector = GTK_COMBO_BOX_TEXT(pComboBox);

    GtkToolItem* pSeparator2 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator2, -1);

    GtkToolItem* pPartModeSelectorToolItem = gtk_tool_item_new();
    GtkWidget* pPartModeComboBox = gtk_combo_box_text_new();
    gtk_container_add( GTK_CONTAINER(pPartModeSelectorToolItem), pPartModeComboBox );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pPartModeSelectorToolItem, -1 );
    g_signal_connect( G_OBJECT(pPartModeComboBox), "changed", G_CALLBACK(changePartMode), NULL );
#endif

    GtkToolItem* pSeparator3 = gtk_separator_tool_item_new();
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pSeparator3, -1);

    GtkToolItem* pEnableQuadView = gtk_toggle_tool_button_new();
    gtk_tool_button_set_label( GTK_TOOL_BUTTON(pEnableQuadView), "Use Quad View" );
    gtk_toolbar_insert( GTK_TOOLBAR(pToolbar), pEnableQuadView, -1 );
    g_signal_connect( G_OBJECT(pEnableQuadView), "toggled", G_CALLBACK(changeQuadView), NULL );

    gtk_box_pack_start( GTK_BOX(pVBox), pToolbar, FALSE, FALSE, 0 ); // Adds to top.

    // Docview
    pDocView = lok_docview_new( pOffice );
    pDocViewQuad = 0;

    // Input handling.
    g_signal_connect(pWindow, "key-press-event", G_CALLBACK(signalKey), NULL);
    g_signal_connect(pWindow, "key-release-event", G_CALLBACK(signalKey), NULL);

    gtk_container_add( GTK_CONTAINER(pVBox), pDocView );

    gtk_widget_show_all( pWindow );

    pFileName = argv[2];
    int bOpened = lok_docview_open_document( LOK_DOCVIEW(pDocView), argv[2] );
    if (!bOpened)
        g_error("main: lok_docview_open_document() failed with '%s'", pOffice->pClass->getError(pOffice));
    assert( LOK_DOCVIEW(pDocView)->pDocument );

    // GtkComboBox requires gtk 2.24 or later
#if ( GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 24 ) || GTK_MAJOR_VERSION > 2
    populatePartSelector();
    populatePartModeSelector( GTK_COMBO_BOX_TEXT(pPartModeComboBox) );
#endif

    gtk_main();

    pOffice->pClass->destroy( pOffice );

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Open Chinese Convert
 *
 * Copyright 2010-2014 BYVoid <byvoid@byvoid.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "Common.hpp"
#include "DictEntry.hpp"

namespace opencc {
/**
 * Storage of all entries
 * @ingroup opencc_cpp_api
 */
class OPENCC_EXPORT Lexicon {
public:
  Lexicon() {}
  Lexicon(vector<std::unique_ptr<DictEntry>> entries_)
      : entries(std::move(entries_)) {}

  // Lexicon will take the ownership of the entry.
  void Add(DictEntry* entry) { entries.emplace_back(entry); }

  void Add(std::unique_ptr<DictEntry> entry) {
    entries.push_back(std::move(entry));
  }

  void Sort() {
    std::sort(entries.begin(), entries.end(), DictEntry::UPtrLessThan);
  }

  bool IsSorted() {
    return std::is_sorted(entries.begin(), entries.end(),
                          DictEntry::UPtrLessThan);
  }

  const DictEntry* At(size_t index) const { return entries.at(index).get(); }

  size_t Length() const { return entries.size(); }

  vector<std::unique_ptr<DictEntry>>::const_iterator begin() const {
    return entries.begin();
  }

  vector<std::unique_ptr<DictEntry>>::const_iterator end() const {
    return entries.end();
  }

private:
  vector<std::unique_ptr<DictEntry>> entries;
};
} // namespace opencc
<commit_msg>Disable copy constructor for Lexicon.<commit_after>/*
 * Open Chinese Convert
 *
 * Copyright 2010-2014 BYVoid <byvoid@byvoid.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "Common.hpp"
#include "DictEntry.hpp"

namespace opencc {
/**
 * Storage of all entries
 * @ingroup opencc_cpp_api
 */
class OPENCC_EXPORT Lexicon {
public:
  Lexicon() {}
  Lexicon(vector<std::unique_ptr<DictEntry>> entries_)
      : entries(std::move(entries_)) {}
  Lexicon(const Lexicon&) = delete;
  Lexicon& operator=(const Lexicon&) = delete;

  // Lexicon will take the ownership of the entry.
  void Add(DictEntry* entry) { entries.emplace_back(entry); }

  void Add(std::unique_ptr<DictEntry> entry) {
    entries.push_back(std::move(entry));
  }

  void Sort() {
    std::sort(entries.begin(), entries.end(), DictEntry::UPtrLessThan);
  }

  bool IsSorted() {
    return std::is_sorted(entries.begin(), entries.end(),
                          DictEntry::UPtrLessThan);
  }

  const DictEntry* At(size_t index) const { return entries.at(index).get(); }

  size_t Length() const { return entries.size(); }

  vector<std::unique_ptr<DictEntry>>::const_iterator begin() const {
    return entries.begin();
  }

  vector<std::unique_ptr<DictEntry>>::const_iterator end() const {
    return entries.end();
  }

private:
  vector<std::unique_ptr<DictEntry>> entries;
};
} // namespace opencc
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
Copyright (c) 2016 Scheer E2E AG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "Loggable.h"
#include <algorithm>

const std::string Loggable::Levels::SILLY	= "silly";
const std::string Loggable::Levels::DBG		= "debug";
const std::string Loggable::Levels::VERBOSE	= "verbose";
const std::string Loggable::Levels::INFO	= "info";
const std::string Loggable::Levels::WARN	= "warn";
const std::string Loggable::Levels::ERR	= "error";

const std::string Loggable::API_CALL_MESSAGE	= "SAPNWRFC API Call";

v8::Local<v8::Value> metaToJS( const Loggable::LogEntry::Meta& meta)
{
  Nan::EscapableHandleScope scope;

  v8::Local<v8::Object> result = Nan::New<v8::Object>();

  for( Loggable::LogEntry::Meta::const_iterator it = meta.begin(), eit = meta.end(); it != eit; ++it)
  {
    result->Set(
		Nan::New<v8::String>(it->first).ToLocalChecked(),
		Nan::New<v8::String>(it->second).ToLocalChecked()
    );
  }

  return scope.Escape(result);
}

static v8::Local<v8::Value> errorInfoToJS(const RFC_ERROR_INFO &info)
{
  Nan::EscapableHandleScope scope;

  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
  obj->Set(
      Nan::New<v8::String>("code").ToLocalChecked(),
      Nan::New<v8::Integer>(info.code)
  );
  obj->Set(
      Nan::New<v8::String>("group").ToLocalChecked(),
      Nan::New<v8::Integer>(info.group)
  );
  obj->Set(
      Nan::New<v8::String>("key").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.key)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("class").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgClass)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("type").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgType)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("number").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgNumber)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv1").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV1)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv2").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV2)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv3").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV3)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv4").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV4)).ToLocalChecked()
  );

  return scope.Escape(obj);
}

Loggable::~Loggable()
{
}

void Loggable::init(v8::Handle<v8::Object> thisHandle)
{
    Wrap( thisHandle);

    logFunction =
        Nan::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>(
          v8::Local<v8::Function>::Cast(
                    Nan::Get(handle(),
                             Nan::New<v8::String>("_log").ToLocalChecked()).ToLocalChecked()));
}

void Loggable::log(const std::string& level, const std::string& message)
{
  log(level, Nan::New<v8::String>(message).ToLocalChecked());
}

void Loggable::log(const std::string& level, v8::Local<v8::Value> message)
{
  log(level, message, Nan::Undefined());
}

void Loggable::log(const std::string& level, const std::string& message, v8::Local<v8::Value> meta)
{
  log(level, Nan::New<v8::String>(message).ToLocalChecked(), meta);
}

void Loggable::log(const std::string& level, v8::Local<v8::Value> message, v8::Local<v8::Value> meta)
{
  logDeferred();
  log_(level, message, meta);
}

void Loggable::log_(const std::string& level, v8::Local<v8::Value> message, v8::Local<v8::Value> meta)
{
  v8::Local<v8::Value> argv[3];
  argv[0] = Nan::New<v8::String>(level).ToLocalChecked();
  argv[1] = message->ToString();

  if(meta.IsEmpty() || meta->IsUndefined()) {
      meta = Nan::New<v8::Object>();
  }

  addObjectInfoToLogMeta(meta->ToObject());
  argv[2] = meta;

  assert(!logFunction.IsEmpty());
  auto functionHandle = Nan::New(logFunction);
  Nan::Call(functionHandle, functionHandle, 3, argv);
}

void Loggable::log(const LogEntry& logEntry)
{
  Nan::HandleScope scope;

  v8::Handle<v8::Object> meta;
  if(!logEntry.call.empty()) {
    meta = v8::Handle<v8::Object>::Cast( metaToJS( logEntry.meta));
    meta->Set(Nan::New<v8::String>("call").ToLocalChecked(), Nan::New<v8::String>(logEntry.call).ToLocalChecked());
    meta->Set(Nan::New<v8::String>("errorInfo").ToLocalChecked(), errorInfoToJS(logEntry.errorInfo));
  } else {
    meta = Nan::New<v8::Object>();
  }

  if(!logEntry.file.empty()) {
    meta->Set(Nan::New<v8::String>("file").ToLocalChecked(), Nan::New<v8::String>(logEntry.file).ToLocalChecked());
  }

  if(!logEntry.function.empty()) {
    meta->Set(Nan::New<v8::String>("function").ToLocalChecked(), Nan::New<v8::String>(logEntry.function).ToLocalChecked());
  }

  if(logEntry.line) {
    meta->Set(Nan::New<v8::String>("line").ToLocalChecked(), Nan::New<v8::Integer>(logEntry.line));
  }

  log_(logEntry.level, Nan::New<v8::String>(logEntry.message).ToLocalChecked(), meta);
}

void Loggable::deferLog(const std::string& level, const std::string& message, const Loggable::LogEntry::Meta& meta)
{
  LogEntry entry;
  entry.level = level;
  entry.message = message;
  entry.meta = meta;
  deferredLogs.push_back( entry);
}

void Loggable::createAPILogEntry_(Loggable::LogEntry& logEntry, const std::string& call,
                                  const std::string& file, const std::string& function,
                                  unsigned long line, RFC_ERROR_INFO& errorInfo,
                                  const Loggable::LogEntry::Meta& meta)
{
  logEntry.level = Levels::DBG;
  logEntry.message = API_CALL_MESSAGE;
  logEntry.call = call;
  logEntry.file = file;
  logEntry.function = function;
  logEntry.line = line;
  logEntry.errorInfo = errorInfo;
  logEntry.meta = meta;
}

void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function,
                          unsigned long line, RFC_ERROR_INFO& errorInfo)
{
  logAPICall(call, file, function, line, errorInfo, LogEntry::Meta());
}

void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function,
                          unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta)
{
  logDeferred();
  LogEntry logEntry;
  createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta);
  log(logEntry);
}

void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function,
                               unsigned long line, RFC_ERROR_INFO& errorInfo)
{
  deferLogAPICall(call, file, function, line, errorInfo, LogEntry::Meta());
}

void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function,
                               unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta)
{
  LogEntry logEntry;
  createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta);
  deferredLogs.push_back( logEntry);
}

void Loggable::logDeferred()
{
  for(LogEntries::iterator it = deferredLogs.begin(), eit = deferredLogs.end(); it != eit; ++it)
  {
    log(*it);
  }
  deferredLogs.clear();
}

void Loggable::resetLogFunction()
{
  logFunction.Reset();
}
<commit_msg>Use HandleScope in the logging helpers to ensure we have one<commit_after>/*
-----------------------------------------------------------------------------
Copyright (c) 2016 Scheer E2E AG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "Loggable.h"
#include <algorithm>

const std::string Loggable::Levels::SILLY	= "silly";
const std::string Loggable::Levels::DBG		= "debug";
const std::string Loggable::Levels::VERBOSE	= "verbose";
const std::string Loggable::Levels::INFO	= "info";
const std::string Loggable::Levels::WARN	= "warn";
const std::string Loggable::Levels::ERR	= "error";

const std::string Loggable::API_CALL_MESSAGE	= "SAPNWRFC API Call";

v8::Local<v8::Value> metaToJS( const Loggable::LogEntry::Meta& meta)
{
  Nan::EscapableHandleScope scope;

  v8::Local<v8::Object> result = Nan::New<v8::Object>();

  for( Loggable::LogEntry::Meta::const_iterator it = meta.begin(), eit = meta.end(); it != eit; ++it)
  {
    result->Set(
		Nan::New<v8::String>(it->first).ToLocalChecked(),
		Nan::New<v8::String>(it->second).ToLocalChecked()
    );
  }

  return scope.Escape(result);
}

static v8::Local<v8::Value> errorInfoToJS(const RFC_ERROR_INFO &info)
{
  Nan::EscapableHandleScope scope;

  v8::Local<v8::Object> obj = Nan::New<v8::Object>();
  obj->Set(
      Nan::New<v8::String>("code").ToLocalChecked(),
      Nan::New<v8::Integer>(info.code)
  );
  obj->Set(
      Nan::New<v8::String>("group").ToLocalChecked(),
      Nan::New<v8::Integer>(info.group)
  );
  obj->Set(
      Nan::New<v8::String>("key").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.key)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("class").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgClass)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("type").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgType)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("number").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgNumber)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv1").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV1)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv2").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV2)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv3").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV3)).ToLocalChecked()
  );
  obj->Set(
      Nan::New<v8::String>("msgv4").ToLocalChecked(),
      Nan::New<v8::String>((const uint16_t*)(info.abapMsgV4)).ToLocalChecked()
  );

  return scope.Escape(obj);
}

Loggable::~Loggable()
{
}

void Loggable::init(v8::Handle<v8::Object> thisHandle)
{
    Wrap( thisHandle);

    logFunction =
        Nan::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>(
          v8::Local<v8::Function>::Cast(
                    Nan::Get(handle(),
                             Nan::New<v8::String>("_log").ToLocalChecked()).ToLocalChecked()));
}

void Loggable::log(const std::string& level, const std::string& message)
{
  Nan::HandleScope scope;
  log(level, Nan::New<v8::String>(message).ToLocalChecked());
}

void Loggable::log(const std::string& level, v8::Local<v8::Value> message)
{
  Nan::HandleScope scope;
  log(level, message, Nan::Undefined());
}

void Loggable::log(const std::string& level, const std::string& message, v8::Local<v8::Value> meta)
{
  Nan::HandleScope scope;
  log(level, Nan::New<v8::String>(message).ToLocalChecked(), meta);
}

void Loggable::log(const std::string& level, v8::Local<v8::Value> message, v8::Local<v8::Value> meta)
{
  logDeferred();
  log_(level, message, meta);
}

void Loggable::log_(const std::string& level, v8::Local<v8::Value> message, v8::Local<v8::Value> meta)
{
  Nan::HandleScope scope;
  v8::Local<v8::Value> argv[3];
  argv[0] = Nan::New<v8::String>(level).ToLocalChecked();
  argv[1] = message->ToString();

  if(meta.IsEmpty() || meta->IsUndefined()) {
      meta = Nan::New<v8::Object>();
  }

  addObjectInfoToLogMeta(meta->ToObject());
  argv[2] = meta;

  assert(!logFunction.IsEmpty());
  auto functionHandle = Nan::New(logFunction);
  Nan::Call(functionHandle, functionHandle, 3, argv);
}

void Loggable::log(const LogEntry& logEntry)
{
  Nan::HandleScope scope;

  v8::Handle<v8::Object> meta;
  if(!logEntry.call.empty()) {
    meta = v8::Handle<v8::Object>::Cast( metaToJS( logEntry.meta));
    meta->Set(Nan::New<v8::String>("call").ToLocalChecked(), Nan::New<v8::String>(logEntry.call).ToLocalChecked());
    meta->Set(Nan::New<v8::String>("errorInfo").ToLocalChecked(), errorInfoToJS(logEntry.errorInfo));
  } else {
    meta = Nan::New<v8::Object>();
  }

  if(!logEntry.file.empty()) {
    meta->Set(Nan::New<v8::String>("file").ToLocalChecked(), Nan::New<v8::String>(logEntry.file).ToLocalChecked());
  }

  if(!logEntry.function.empty()) {
    meta->Set(Nan::New<v8::String>("function").ToLocalChecked(), Nan::New<v8::String>(logEntry.function).ToLocalChecked());
  }

  if(logEntry.line) {
    meta->Set(Nan::New<v8::String>("line").ToLocalChecked(), Nan::New<v8::Integer>(logEntry.line));
  }

  log_(logEntry.level, Nan::New<v8::String>(logEntry.message).ToLocalChecked(), meta);
}

void Loggable::deferLog(const std::string& level, const std::string& message, const Loggable::LogEntry::Meta& meta)
{
  LogEntry entry;
  entry.level = level;
  entry.message = message;
  entry.meta = meta;
  deferredLogs.push_back( entry);
}

void Loggable::createAPILogEntry_(Loggable::LogEntry& logEntry, const std::string& call,
                                  const std::string& file, const std::string& function,
                                  unsigned long line, RFC_ERROR_INFO& errorInfo,
                                  const Loggable::LogEntry::Meta& meta)
{
  logEntry.level = Levels::DBG;
  logEntry.message = API_CALL_MESSAGE;
  logEntry.call = call;
  logEntry.file = file;
  logEntry.function = function;
  logEntry.line = line;
  logEntry.errorInfo = errorInfo;
  logEntry.meta = meta;
}

void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function,
                          unsigned long line, RFC_ERROR_INFO& errorInfo)
{
  logAPICall(call, file, function, line, errorInfo, LogEntry::Meta());
}

void Loggable::logAPICall(const std::string& call, const std::string& file, const std::string& function,
                          unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta)
{
  logDeferred();
  LogEntry logEntry;
  createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta);
  log(logEntry);
}

void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function,
                               unsigned long line, RFC_ERROR_INFO& errorInfo)
{
  deferLogAPICall(call, file, function, line, errorInfo, LogEntry::Meta());
}

void Loggable::deferLogAPICall(const std::string& call, const std::string& file, const std::string& function,
                               unsigned long line, RFC_ERROR_INFO& errorInfo, const Loggable::LogEntry::Meta& meta)
{
  LogEntry logEntry;
  createAPILogEntry_(logEntry, call, file, function, line, errorInfo, meta);
  deferredLogs.push_back( logEntry);
}

void Loggable::logDeferred()
{
  for(LogEntries::iterator it = deferredLogs.begin(), eit = deferredLogs.end(); it != eit; ++it)
  {
    log(*it);
  }
  deferredLogs.clear();
}

void Loggable::resetLogFunction()
{
  logFunction.Reset();
}
<|endoftext|>


<commit_before>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk 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
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file MSCData.hpp
 * Monitor station coordinate file data
 */

#ifndef MSCDATA_HPP
#define MSCDATA_HPP

#include <string>
#include "StringUtils.hpp"
#include "Triple.hpp"
#include "ECEF.hpp"
#include "DayTime.hpp"
#include "FFData.hpp"
#include "Xvt.hpp"

namespace gpstk
{
      /** @addtogroup icd211group ICD-GPS-211 Classes */
      //@{

      /**
       * Model for a Monitor Station Coordinates File Data Record
       */
   class MSCData : public gpstk::FFData
   {
   public:
         /// constructor
      MSCData() throw() : time(gpstk::DayTime(0.L)) {}

         /// destructor
      virtual ~MSCData() throw() {}

         /// Returns position, velocity, time in ECEF coords, units meters, for the indicated time.
         /// @param t time for which to calcuate the position
         /// @throw InvalidRequest If the request can not be completed for any
         ///    reason, this is thrown. The text may have additional
         ///    information as to why the request failed.
      Xvt getXvt(const DayTime& t)
         const throw(InvalidRequest);

      gpstk::DayTime time;  ///< date of coordinates release from NIMA
      unsigned long station; ///< NIMA Monitor Station number (e.g. 85408)
      std::string mnemonic;  ///< NIMA Monitor Station identifier (e.g. ARLM)
      gpstk::DayTime refepoch;  ///< epoch of coordinates and velocities
      gpstk::DayTime effepoch;  ///< earliest epoch data is valid
      gpstk::ECEF coordinates;  ///< ECEF XYZ coordinates
      gpstk::Triple velocities; ///< XYZ velocities

         /// MSCData \b is data, so this always return \c true
      virtual bool isData() const { return true; }

   protected:
         /// Write an MSCData object in the format specified by the stream
      virtual void reallyPutRecord(gpstk::FFStream& ffs) const
         throw(std::exception, gpstk::FFStreamError,
               gpstk::StringUtils::StringException);

         /**
          * Retrieve an MSCData record from the given gpstk::FFStream.
          * If there is a problem reading from the stream, it
          * is reset to its original position and it's failbit is set.
          * @throws StringException when a gpstk::StringUtils functions fails
          * @throws gpstk::FFStreamError when exceptions(failbit) is set and
          *  a read or formatting error occurs. This also resets the
          *  stream to it pre-read position.
          */
      virtual void reallyGetRecord(gpstk::FFStream& ffs)
         throw(std::exception, gpstk::FFStreamError,
               gpstk::StringUtils::StringException);
   }; // class MSCData

      //@}

} // namespace gpstk

#endif

<commit_msg>Removed NIMA-specific comments.<commit_after>#pragma ident "$Id$"

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk 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
//  any later version.
//
//  The GPSTk 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 GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Copyright 2004, The University of Texas at Austin
//
//============================================================================

//============================================================================
//
//This software developed by Applied Research Laboratories at the University of
//Texas at Austin, under contract to an agency or agencies within the U.S.
//Department of Defense. The U.S. Government retains all rights to use,
//duplicate, distribute, disclose, or release this software.
//
//Pursuant to DoD Directive 523024
//
// DISTRIBUTION STATEMENT A: This software has been approved for public
//                           release, distribution is unlimited.
//
//=============================================================================

/**
 * @file MSCData.hpp
 * Monitor station coordinate file data
 */

#ifndef MSCDATA_HPP
#define MSCDATA_HPP

#include <string>
#include "StringUtils.hpp"
#include "Triple.hpp"
#include "ECEF.hpp"
#include "DayTime.hpp"
#include "FFData.hpp"
#include "Xvt.hpp"

namespace gpstk
{
      /** @addtogroup icd211group ICD-GPS-211 Classes */
      //@{

      /**
       * Model for a Monitor Station Coordinates File Data Record
       */
   class MSCData : public gpstk::FFData
   {
   public:
         /// constructor
      MSCData() throw() : time(gpstk::DayTime(0.L)) {}

         /// destructor
      virtual ~MSCData() throw() {}

         /// Returns position, velocity, time in ECEF coords, units meters, for the indicated time.
         /// @param t time for which to calcuate the position
         /// @throw InvalidRequest If the request can not be completed for any
         ///    reason, this is thrown. The text may have additional
         ///    information as to why the request failed.
      Xvt getXvt(const DayTime& t)
         const throw(InvalidRequest);

      gpstk::DayTime time;  ///< date coordinates released
                            ///<   (Bookkeeping convenience not used)
      unsigned long station; ///< Monitor Station number (e.g. 10234)
      std::string mnemonic;  ///< Monitor Station identifier (e.g. ARLM)
      gpstk::DayTime refepoch;  ///< epoch of coordinates and velocities
      gpstk::DayTime effepoch;  ///< earliest epoch data is valid
      gpstk::ECEF coordinates;  ///< ECEF XYZ coordinates
      gpstk::Triple velocities; ///< XYZ velocities

         /// MSCData \b is data, so this always return \c true
      virtual bool isData() const { return true; }

   protected:
         /// Write an MSCData object in the format specified by the stream
      virtual void reallyPutRecord(gpstk::FFStream& ffs) const
         throw(std::exception, gpstk::FFStreamError,
               gpstk::StringUtils::StringException);

         /**
          * Retrieve an MSCData record from the given gpstk::FFStream.
          * If there is a problem reading from the stream, it
          * is reset to its original position and it's failbit is set.
          * @throws StringException when a gpstk::StringUtils functions fails
          * @throws gpstk::FFStreamError when exceptions(failbit) is set and
          *  a read or formatting error occurs. This also resets the
          *  stream to it pre-read position.
          */
      virtual void reallyGetRecord(gpstk::FFStream& ffs)
         throw(std::exception, gpstk::FFStreamError,
               gpstk::StringUtils::StringException);
   }; // class MSCData

      //@}

} // namespace gpstk

#endif

<|endoftext|>


<commit_before>/* cclive
 * Copyright (C) 2010-2011  Toni Gundogdu <legatvs@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdexcept>
#include <sstream>
#include <cstdio>
#include <cerrno>

#include <sys/wait.h>

#include <boost/program_options/variables_map.hpp>
#include <boost/foreach.hpp>
#include <pcrecpp.h>

#ifndef foreach
#define foreach BOOST_FOREACH
#endif

#include <ccquvi>
#include <ccfile>
#include <ccre>
#include <ccutil>
#include <cclog>

namespace cc
{

typedef std::vector<std::string> vst;

static void tokenize(const std::string& r,
                     const std::string& s,
                     vst& dst)
{
  pcrecpp::StringPiece sp(s);
  pcrecpp::RE rx(r);

  std::string t;
  while (rx.FindAndConsume(&sp, &t))
    dst.push_back(t);
}

namespace po = boost::program_options;

int exec(const file& file,
         const quvi::url& url,
         const po::variables_map& map)
{
  std::stringstream b;
  b << "\"" << file.path() << "\"";

  std::string e = map["exec"].as<std::string>();
  pcrecpp::RE("%f").GlobalReplace(b.str(), &e);

  vst tokens;
  tokenize("(\"(.*?)\"|\\S+)", e, tokens);

  std::string t;
  vst args;

  foreach (const std::string s, tokens)
  {
    t = s;
    pcrecpp::RE("\"").GlobalReplace("", &t);
    args.push_back(t);
  }

  const size_t sz = args.size();
  const char **argv = new const char* [sz+2];
  if (!argv)
    throw std::runtime_error("memory allocation error");

  argv[0] = args[0].c_str();

  for (size_t i=1; i<sz; ++i)
    argv[i] = args[i].c_str();

  argv[sz] = NULL;

  fflush(stdout);
  fflush(stderr);

  pid_t child_pid = fork();
  if (child_pid == -1)
    {
      delete [] argv;
      throw std::runtime_error(cc::perror("fork"));
    }

  if (child_pid == 0)
    {
      execvp(argv[0], (char **)argv);
      exit(1);
    }

  delete [] argv;

  int wait_status = 0;
  while (waitpid(child_pid, &wait_status, 0) == (pid_t)-1)
    {
      if (errno != EINTR)
        {
          cc::log << "error waiting for " << args[0] << std::endl;
          break;
        }
    }

  if (WIFSIGNALED(wait_status))
    {
      cc::log << args[0]
              << " terminated by signal "
              << WTERMSIG(wait_status)
              << std::endl;
    }

  if (WEXITSTATUS(wait_status) == 0)
    return 0; // OK.

  return 1;
}

} // namespace cc

// vim: set ts=2 sw=2 tw=72 expandtab:
<commit_msg>Eliminate extra std::string<commit_after>/* cclive
 * Copyright (C) 2010-2011  Toni Gundogdu <legatvs@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdexcept>
#include <sstream>
#include <cstdio>
#include <cerrno>

#include <sys/wait.h>

#include <boost/program_options/variables_map.hpp>
#include <boost/foreach.hpp>
#include <pcrecpp.h>

#ifndef foreach
#define foreach BOOST_FOREACH
#endif

#include <ccquvi>
#include <ccfile>
#include <ccre>
#include <ccutil>
#include <cclog>

namespace cc
{

typedef std::vector<std::string> vst;

static void tokenize(const std::string& r,
                     const std::string& s,
                     vst& dst)
{
  pcrecpp::StringPiece sp(s);
  pcrecpp::RE rx(r);

  std::string t;
  while (rx.FindAndConsume(&sp, &t))
    dst.push_back(t);
}

namespace po = boost::program_options;

int exec(const file& file,
         const quvi::url& url,
         const po::variables_map& map)
{
  std::stringstream b;
  b << "\"" << file.path() << "\"";

  std::string e = map["exec"].as<std::string>();
  pcrecpp::RE("%f").GlobalReplace(b.str(), &e);

  vst tokens;
  tokenize("(\"(.*?)\"|\\S+)", e, tokens);

  vst args;
  foreach (std::string s, tokens)
  {
    pcrecpp::RE("\"").GlobalReplace("", &s);
    args.push_back(s);
  }

  const size_t sz = args.size();
  const char **argv = new const char* [sz+2];
  if (!argv)
    throw std::runtime_error("memory allocation error");

  argv[0] = args[0].c_str();

  for (size_t i=1; i<sz; ++i)
    argv[i] = args[i].c_str();

  argv[sz] = NULL;

  fflush(stdout);
  fflush(stderr);

  pid_t child_pid = fork();
  if (child_pid == -1)
    {
      delete [] argv;
      throw std::runtime_error(cc::perror("fork"));
    }

  if (child_pid == 0)
    {
      execvp(argv[0], (char **)argv);
      exit(1);
    }

  delete [] argv;

  int wait_status = 0;
  while (waitpid(child_pid, &wait_status, 0) == (pid_t)-1)
    {
      if (errno != EINTR)
        {
          cc::log << "error waiting for " << args[0] << std::endl;
          break;
        }
    }

  if (WIFSIGNALED(wait_status))
    {
      cc::log << args[0]
              << " terminated by signal "
              << WTERMSIG(wait_status)
              << std::endl;
    }

  if (WEXITSTATUS(wait_status) == 0)
    return 0; // OK.

  return 1;
}

} // namespace cc

// vim: set ts=2 sw=2 tw=72 expandtab:
<|endoftext|>


<commit_before>/* cclive
 * Copyright (C) 2010-2013  Toni Gundogdu <legatvs@gmail.com>
 *
 * This file is part of cclive <http://cclive.sourceforge.net/>.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <ccinternal>

#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/errinfo_file_name.hpp>
#include <boost/exception/get_error_info.hpp>
#include <boost/exception/errinfo_errno.hpp>

#include <stdexcept>
#include <iostream>
#include <clocale>

#include <ccapplication>
#include <ccquvi>
#include <ccoptions>
#include <ccutil>

using namespace cc;

int main(int const argc, char const **argv)
{
  setlocale(LC_ALL, "");
  application::exit_status es = application::ok;
  application app;
  try
    {
      es = app.exec(argc, argv);
    }
  // --version, --help, etc.
  catch (const cc::options::exit_program&)
    {
      // Fall through.
    }
  // Thrown by quvi::query constructor (e.g. quvi_init, quvi_new).
  catch (const quvi::error& e)
    {
      std::clog << "libquvi: error: " << e.what() << std::endl;
      es = application::error;
    }
  // Thrown by boost (e.g. cc::go_background failure).
  catch (const std::runtime_error& e)
    {
      std::clog << "error: " << e.what() << std::endl;
      es = application::error;
    }
  // Thrown by boost::program_options (cc::options).
  catch (const boost::exception& x)
    {
      es = static_cast<application::exit_status>(cc::error::print(x));
    }
  return es;
}

// vim: set ts=2 sw=2 tw=72 expandtab:
<commit_msg>Update main for rewritten cc::input<commit_after>/* cclive
 * Copyright (C) 2010-2013  Toni Gundogdu <legatvs@gmail.com>
 *
 * This file is part of cclive <http://cclive.sourceforge.net/>.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include <ccinternal>

#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception/errinfo_file_name.hpp>
#include <boost/exception/get_error_info.hpp>
#include <boost/exception/errinfo_errno.hpp>

#include <stdexcept>
#include <iostream>
#include <clocale>

#include <ccapplication>
#include <ccquvi>
#include <ccoptions>
#include <ccutil>

using namespace cc;

int main(int const argc, char const **argv)
{
  setlocale(LC_ALL, "");
  application::exit_status es = application::ok;
  application app;
  try
    {
      es = app.exec(argc, argv);
    }
  // --version, --help, etc.
  catch (const cc::options::exit_program&)
    {
      // Fall through.
    }
  catch (const cc::error::no_input&)
    {
      std::clog << "error: no input URL" << std::endl;
      es = application::error;
    }
  // Thrown by quvi::query constructor (e.g. quvi_init, quvi_new).
  catch (const quvi::error& e)
    {
      std::clog << "libquvi: error: " << e.what() << std::endl;
      es = application::error;
    }
  // Thrown by boost (e.g. cc::go_background failure).
  catch (const std::runtime_error& e)
    {
      std::clog << "error: " << e.what() << std::endl;
      es = application::error;
    }
  // Thrown by boost::program_options (cc::options).
  catch (const boost::exception& x)
    {
      es = static_cast<application::exit_status>(cc::error::print(x));
    }
  return es;
}

// vim: set ts=2 sw=2 tw=72 expandtab:
<|endoftext|>


<commit_before>//
//  ObjLoader.cpp
//  KickObjLoader
//
//  Created by morten on 8/31/13.
//  Copyright (c) 2013 morten. All rights reserved.
//

#include "ObjLoad.h"
#include <fstream>
#include <string>
#include <cstring>
#include <sstream>
#include <cerrno>
#include "glm/ext.hpp"

using namespace std;
using namespace glm;

namespace kick {
    // from http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
    string getFileContents(string filename)
    {
        ifstream in{filename, ios::in | ios::binary};
        if (in)
        {
            std::string contents;
            in.seekg(0, std::ios::end);
            contents.resize(in.tellg());
            in.seekg(0, std::ios::beg);
            in.read(&contents[0], contents.size());
            in.close();
            return contents;
        }
        throw(errno);
    }

    vec4 toVec4(vector<string> &tokens){
        vec4 res{0,0,0,1};
        for (int i=0;i<4;i++){
            if (i+1 < tokens.size()){
                res[i] = atof(tokens[i+1].c_str());
            }
        }
        return res;
    }

    vec3 toVec3(vector<string> &tokens){
        vec3 res{0,0,0};
        for (int i=0;i<3;i++){
            if (i+1 < tokens.size()){
                res[i] = atof(tokens[i+1].c_str());
            }
        }
        return res;
    }

    // replace first occurrence of from in str with to
    bool replace(std::string& str, const std::string& from, const std::string& to) {
        size_t start_pos = str.find(from);
        if(start_pos == std::string::npos)
            return false;
        str.replace(start_pos, from.length(), to);
        return true;
    }

    ObjFace toObjFace(vector<string> &tokens){
        ObjFace res;
        for (int i=1; i<tokens.size(); i++) {
            string & p = tokens[i];
            replace(p, "//","/0/");

            ObjVertex o{0,0,0};

            stringstream ss{p};
            char buffer[50];

            ss.getline(buffer,50, '/');
            o.vertexPositionIdx = atoi(buffer);
            if (ss.good()){
                ss.getline(buffer,50, '/');
                o.textureIdx = atoi(buffer);
            }
            if (ss.good()){
                ss.getline(buffer,50, '/');
                o.normalIdx = atoi(buffer);
            }
            res.push_back(o);
        }
        return move(res);
    }

    void parseMaterialLib(std::string & materialLib, ObjData & dest){
        const int bufferSize = 256;
        char buffer[bufferSize];
        char buffer2[bufferSize];
        stringstream ss{materialLib};

        while (ss.good()){
            ss.getline(buffer, bufferSize);
            stringstream likeTokensizer{buffer};
            vector<string> tokens;
            while (likeTokensizer.good()) {
                likeTokensizer.getline(buffer2, bufferSize, ' ');
                tokens.push_back(buffer2);
            }
            if (tokens.size()==0){
                continue;
            }
            if (tokens[0] == "newmtl"){
                vec3 zero{0,0,0};
                ObjMaterial material{tokens[1],zero,zero,zero,50,1};
                dest.materials.push_back(material);
            } else {
                if (dest.materials.size()==0){
                    continue;
                }
                ObjMaterial & currentMat = dest.materials.back();
                if (tokens[0] == "Ka"){
                    currentMat.ambientColor = toVec3(tokens);
                } else if (tokens[0] == "Kd"){
                    currentMat.diffuseColor = toVec3(tokens);
                } else if (tokens[0] == "Ks"){
                    currentMat.specularColor = toVec3(tokens);
                } else if (tokens[0] == "d"){
                    currentMat.transparent = atoi(tokens[1].c_str());
                } else if (tokens[0] == "illum"){
                    int illumMode = atoi(tokens[1].c_str());
                    currentMat.illuminationModes.push_back(static_cast<ObjIlluminationMode>(illumMode));
                } else if (tokens[0] == "map_Ka"){

                } else if (tokens[0] == "map_Kd"){
                } else if (tokens[0] == "map_Ks"){
                } else if (tokens[0] == "map_Ns"){
                } else if (tokens[0] == "map_d"){
                } else if (tokens[0] == "map_bump" || tokens[0] == "bump" ){
                } else if (tokens[0] == "map_disp" || tokens[0] == "disp" ){
                } else if (tokens[0] == "map_decal" || tokens[0] == "decal" ){
                }
            }
        }
    }

    ObjData loadObjData(std::string objSource, std::function<std::string (std::string)> materialMap){
        ObjData res;
        stringstream ss{objSource};
        const int bufferSize = 256;
        char buffer[bufferSize];
        char buffer2[bufferSize];
        bool initialComment = true;
        while (ss.good()){
            ss.getline(buffer, bufferSize);
            cout << buffer << endl;
            stringstream likeTokensizer{buffer};
            vector<string> tokens;
            while (likeTokensizer.good()) {
                likeTokensizer.getline(buffer2, bufferSize, ' ');
                tokens.push_back(buffer2);
            }
            if (tokens.size()==0){
                continue;
            }
            initialComment = initialComment && (tokens[0] == "#");
            int currentIndex = static_cast<int>(res.faces.size()) + 1;
            if (tokens[0] == "#"){ // comment
                if (initialComment){
                    res.initialComment += string(buffer + 2) + "\n";
                }
            } else if (tokens[0] == "v"){ // vertex position
                vec4 vertexPosition = toVec4(tokens);
                res.vertexPositions.push_back(vertexPosition);
            } else if (tokens[0] == "vt"){ // vertex texture coordinates
                vec3 textureCoord = toVec3(tokens);
                res.textureCoords.push_back(textureCoord);
            } else if (tokens[0] == "vn"){ // vertex normal
                vec3 normal = toVec3(tokens);
                res.normals.push_back(normal);
            } else if (tokens[0] == "f"){ // face
                res.faces.push_back(toObjFace(tokens));
            } else if (tokens[0] == "mtllib"){ // material library
                string materialLib = materialMap(tokens[1]);
                parseMaterialLib(materialLib, res);
            } else if (tokens[0] == "usemtl"){ // use material
                res.materialChanges.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "o"){ // named object
                res.namedObjects.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "g"){ // polygon group
                res.polygonGroups.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "s"){ // smoothing groups
                int smoothingGroup = 0; // 0 = no smoothing
                if (tokens[1] != "off"){
                    smoothingGroup = atoi(tokens[1].c_str());
                }
                res.smoothGroups.push_back({currentIndex, smoothingGroup});
            }
        }

        return res;
    }

    std::string fixPathEnd(std::string &path){
        char lastChar = path[path.length()-1];
        if (lastChar != '/'){
            return path + "/";
        }
        return path;
    }

    ObjData loadObjData(std::string path, std::string filename){
        path = fixPathEnd(path);
        string file = getFileContents(path+filename);
        std::function<std::string (std::string)>  materialLoader = [&](string filename){
            return getFileContents(path+filename);
        };
        return loadObjData(file, materialLoader);
    }
}
<commit_msg>Fix wrong transparent parsing in material<commit_after>//
//  ObjLoader.cpp
//  KickObjLoader
//
//  Created by morten on 8/31/13.
//  Copyright (c) 2013 morten. All rights reserved.
//

#include "ObjLoad.h"
#include <fstream>
#include <string>
#include <cstring>
#include <sstream>
#include <cerrno>
#include "glm/ext.hpp"

using namespace std;
using namespace glm;

namespace kick {
    // from http://stackoverflow.com/questions/2602013/read-whole-ascii-file-into-c-stdstring
    string getFileContents(string filename)
    {
        ifstream in{filename, ios::in | ios::binary};
        if (in)
        {
            std::string contents;
            in.seekg(0, std::ios::end);
            contents.resize(in.tellg());
            in.seekg(0, std::ios::beg);
            in.read(&contents[0], contents.size());
            in.close();
            return contents;
        }
        throw(errno);
    }

    vec4 toVec4(vector<string> &tokens){
        vec4 res{0,0,0,1};
        for (int i=0;i<4;i++){
            if (i+1 < tokens.size()){
                res[i] = atof(tokens[i+1].c_str());
            }
        }
        return res;
    }

    vec3 toVec3(vector<string> &tokens){
        vec3 res{0,0,0};
        for (int i=0;i<3;i++){
            if (i+1 < tokens.size()){
                res[i] = atof(tokens[i+1].c_str());
            }
        }
        return res;
    }

    // replace first occurrence of from in str with to
    bool replace(std::string& str, const std::string& from, const std::string& to) {
        size_t start_pos = str.find(from);
        if(start_pos == std::string::npos)
            return false;
        str.replace(start_pos, from.length(), to);
        return true;
    }

    ObjFace toObjFace(vector<string> &tokens){
        ObjFace res;
        for (int i=1; i<tokens.size(); i++) {
            string & p = tokens[i];
            replace(p, "//","/0/");

            ObjVertex o{0,0,0};

            stringstream ss{p};
            char buffer[50];

            ss.getline(buffer,50, '/');
            o.vertexPositionIdx = atoi(buffer);
            if (ss.good()){
                ss.getline(buffer,50, '/');
                o.textureIdx = atoi(buffer);
            }
            if (ss.good()){
                ss.getline(buffer,50, '/');
                o.normalIdx = atoi(buffer);
            }
            res.push_back(o);
        }
        return move(res);
    }

    void parseMaterialLib(std::string & materialLib, ObjData & dest){
        const int bufferSize = 256;
        char buffer[bufferSize];
        char buffer2[bufferSize];
        stringstream ss{materialLib};

        while (ss.good()){
            ss.getline(buffer, bufferSize);
            stringstream likeTokensizer{buffer};
            vector<string> tokens;
            while (likeTokensizer.good()) {
                likeTokensizer.getline(buffer2, bufferSize, ' ');
                tokens.push_back(buffer2);
            }
            if (tokens.size()==0){
                continue;
            }
            if (tokens[0] == "newmtl"){
                vec3 zero{0,0,0};
                ObjMaterial material{tokens[1],zero,zero,zero,50,1};
                dest.materials.push_back(material);
            } else {
                if (dest.materials.size()==0){
                    continue;
                }
                ObjMaterial & currentMat = dest.materials.back();
                if (tokens[0] == "Ka"){
                    currentMat.ambientColor = toVec3(tokens);
                } else if (tokens[0] == "Kd"){
                    currentMat.diffuseColor = toVec3(tokens);
                } else if (tokens[0] == "Ks"){
                    currentMat.specularColor = toVec3(tokens);
                } else if (tokens[0] == "d"){
                    currentMat.transparent = atof(tokens[1].c_str());
                } else if (tokens[0] == "illum"){
                    int illumMode = atoi(tokens[1].c_str());
                    currentMat.illuminationModes.push_back(static_cast<ObjIlluminationMode>(illumMode));
                } else if (tokens[0] == "map_Ka"){

                } else if (tokens[0] == "map_Kd"){
                } else if (tokens[0] == "map_Ks"){
                } else if (tokens[0] == "map_Ns"){
                } else if (tokens[0] == "map_d"){
                } else if (tokens[0] == "map_bump" || tokens[0] == "bump" ){
                } else if (tokens[0] == "map_disp" || tokens[0] == "disp" ){
                } else if (tokens[0] == "map_decal" || tokens[0] == "decal" ){
                }
            }
        }
    }

    ObjData loadObjData(std::string objSource, std::function<std::string (std::string)> materialMap){
        ObjData res;
        stringstream ss{objSource};
        const int bufferSize = 256;
        char buffer[bufferSize];
        char buffer2[bufferSize];
        bool initialComment = true;
        while (ss.good()){
            ss.getline(buffer, bufferSize);
            cout << buffer << endl;
            stringstream likeTokensizer{buffer};
            vector<string> tokens;
            while (likeTokensizer.good()) {
                likeTokensizer.getline(buffer2, bufferSize, ' ');
                tokens.push_back(buffer2);
            }
            if (tokens.size()==0){
                continue;
            }
            initialComment = initialComment && (tokens[0] == "#");
            int currentIndex = static_cast<int>(res.faces.size()) + 1;
            if (tokens[0] == "#"){ // comment
                if (initialComment){
                    res.initialComment += string(buffer + 2) + "\n";
                }
            } else if (tokens[0] == "v"){ // vertex position
                vec4 vertexPosition = toVec4(tokens);
                res.vertexPositions.push_back(vertexPosition);
            } else if (tokens[0] == "vt"){ // vertex texture coordinates
                vec3 textureCoord = toVec3(tokens);
                res.textureCoords.push_back(textureCoord);
            } else if (tokens[0] == "vn"){ // vertex normal
                vec3 normal = toVec3(tokens);
                res.normals.push_back(normal);
            } else if (tokens[0] == "f"){ // face
                res.faces.push_back(toObjFace(tokens));
            } else if (tokens[0] == "mtllib"){ // material library
                string materialLib = materialMap(tokens[1]);
                parseMaterialLib(materialLib, res);
            } else if (tokens[0] == "usemtl"){ // use material
                res.materialChanges.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "o"){ // named object
                res.namedObjects.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "g"){ // polygon group
                res.polygonGroups.push_back({currentIndex, tokens[1]});
            } else if (tokens[0] == "s"){ // smoothing groups
                int smoothingGroup = 0; // 0 = no smoothing
                if (tokens[1] != "off"){
                    smoothingGroup = atoi(tokens[1].c_str());
                }
                res.smoothGroups.push_back({currentIndex, smoothingGroup});
            }
        }

        return res;
    }

    std::string fixPathEnd(std::string &path){
        char lastChar = path[path.length()-1];
        if (lastChar != '/'){
            return path + "/";
        }
        return path;
    }

    ObjData loadObjData(std::string path, std::string filename){
        path = fixPathEnd(path);
        string file = getFileContents(path+filename);
        std::function<std::string (std::string)>  materialLoader = [&](string filename){
            return getFileContents(path+filename);
        };
        return loadObjData(file, materialLoader);
    }
}
<|endoftext|>


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

#include <pdal/Options.hpp>
#include <pdal/PDALUtils.hpp>

#include <iostream>
#include <sstream>
#include <iostream>

namespace pdal
{

Option::Option(const boost::property_tree::ptree& tree)
{
    using namespace boost::property_tree;

    m_name = tree.get<std::string>("Name");
    m_value = tree.get<std::string>("Value");
    m_description =
    tree.count("Description") ? tree.get<std::string>("Description") : "";
}

#if !defined(PDAL_COMPILER_MSVC)

// explicit specialization:
//   if insert a bool, we don't want it to be "0" or "1" (which is
//   what lexical_cast would do)
template<> void Option::setValue(const bool& value)
{
    m_value = value ? "true" : "false";
}

// explicit specialization:
//   if we want to insert a string, we don't need lexical_cast
template<> void Option::setValue(const std::string& value)
{
    m_value = value;
}
#endif

void Option::toMetadata(MetadataNode& parent) const
{
    MetadataNode child = parent.add(getName());
    child.add("value", getValue<std::string>());
    child.add("description", getDescription());
}

//---------------------------------------------------------------------------

Options::Options(const Options& rhs)
    : m_options(rhs.m_options)
{}

Options::Options(const Option& opt)
{
    add(opt);
}

bool Option::nameValid(const std::string& name, bool reportError)
{
    bool valid = (parse(name, 0) == name.size());
    if (reportError)
    {
        std::ostringstream oss;
        oss << "Invalid option name '" << name << "'.  Options must "
            "consist of only lowercase letters, numbers and '_'.";
        Utils::printError(oss.str());
    }
    return valid;
}

Options::Options(const boost::property_tree::ptree& tree)
{
    for (auto iter = tree.begin(); iter != tree.end(); ++iter)
    {
        assert(iter->first == "Option");
        Option opt(iter->second);
        add(opt);
    }
}

void Options::add(const Option& option)
{
    assert(Option::nameValid(option.getName(), bool doReport = true));
    m_options.insert(std::pair<std::string, Option>(option.getName(), option));
}

void Options::remove(const Option& option)
{
    m_options.erase(option.getName());
}

Option& Options::getOptionByRef(const std::string& name)
{
    auto iter = m_options.find(name);
    if (iter == m_options.end())
    {
        std::ostringstream oss;
        oss << "Options::getOptionByRef: Required option '" << name <<
            "' was not found on this stage";
        throw Option::not_found(oss.str());
    }
    return iter->second;
}

const Option& Options::getOption(const std::string& name) const
{
    assert(Option::nameValid(name, bool doReport = true));
    auto iter = m_options.find(name);
    if (iter == m_options.end())
    {
        std::ostringstream oss;
        oss << "Options::getOption: Required option '" << name <<
            "' was not found on this stage";
        throw Option::not_found(oss.str());
    }
    return iter->second;
}

std::vector<Option> Options::getOptions(std::string const& name) const
{
    std::vector<Option> output;

    // If we have an empty name, return them all
    if (name.empty())
    {
        for (auto it = m_options.begin(); it != m_options.end(); ++it)
        {
            output.push_back(it->second);
        }
    }
    else
    {
        auto ret = m_options.equal_range(name);
        for (auto it = ret.first; it != ret.second; ++it)
        {
            output.push_back(it->second);
        }
    }
    return output;
}

bool Options::hasOption(std::string const& name) const
{
    try
    {
        (void)getOption(name);
        return true;
    }
    catch (Option::not_found)
    {}
    return false;
}

void Options::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& ostr, const Options& options)
{
    const boost::property_tree::ptree tree = pdal::Utils::toPTree(options);

    boost::property_tree::write_json(ostr, tree);

    return ostr;
}

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

#include <pdal/Options.hpp>
#include <pdal/PDALUtils.hpp>

#include <iostream>
#include <sstream>
#include <iostream>

namespace pdal
{

Option::Option(const boost::property_tree::ptree& tree)
{
    using namespace boost::property_tree;

    m_name = tree.get<std::string>("Name");
    m_value = tree.get<std::string>("Value");
    m_description =
    tree.count("Description") ? tree.get<std::string>("Description") : "";
}

#if !defined(PDAL_COMPILER_MSVC)

// explicit specialization:
//   if insert a bool, we don't want it to be "0" or "1" (which is
//   what lexical_cast would do)
template<> void Option::setValue(const bool& value)
{
    m_value = value ? "true" : "false";
}

// explicit specialization:
//   if we want to insert a string, we don't need lexical_cast
template<> void Option::setValue(const std::string& value)
{
    m_value = value;
}
#endif

void Option::toMetadata(MetadataNode& parent) const
{
    MetadataNode child = parent.add(getName());
    child.add("value", getValue<std::string>());
    child.add("description", getDescription());
}

//---------------------------------------------------------------------------

Options::Options(const Options& rhs)
    : m_options(rhs.m_options)
{}

Options::Options(const Option& opt)
{
    add(opt);
}

bool Option::nameValid(const std::string& name, bool reportError)
{
    bool valid = (parse(name, 0) == name.size());
    if (reportError)
    {
        std::ostringstream oss;
        oss << "Invalid option name '" << name << "'.  Options must "
            "consist of only lowercase letters, numbers and '_'.";
        Utils::printError(oss.str());
    }
    return valid;
}

Options::Options(const boost::property_tree::ptree& tree)
{
    for (auto iter = tree.begin(); iter != tree.end(); ++iter)
    {
        assert(iter->first == "Option");
        Option opt(iter->second);
        add(opt);
    }
}

void Options::add(const Option& option)
{
    assert(Option::nameValid(option.getName(), true));
    m_options.insert(std::pair<std::string, Option>(option.getName(), option));
}

void Options::remove(const Option& option)
{
    m_options.erase(option.getName());
}

Option& Options::getOptionByRef(const std::string& name)
{
    auto iter = m_options.find(name);
    if (iter == m_options.end())
    {
        std::ostringstream oss;
        oss << "Options::getOptionByRef: Required option '" << name <<
            "' was not found on this stage";
        throw Option::not_found(oss.str());
    }
    return iter->second;
}

const Option& Options::getOption(const std::string& name) const
{
    assert(Option::nameValid(name, true));
    auto iter = m_options.find(name);
    if (iter == m_options.end())
    {
        std::ostringstream oss;
        oss << "Options::getOption: Required option '" << name <<
            "' was not found on this stage";
        throw Option::not_found(oss.str());
    }
    return iter->second;
}

std::vector<Option> Options::getOptions(std::string const& name) const
{
    std::vector<Option> output;

    // If we have an empty name, return them all
    if (name.empty())
    {
        for (auto it = m_options.begin(); it != m_options.end(); ++it)
        {
            output.push_back(it->second);
        }
    }
    else
    {
        auto ret = m_options.equal_range(name);
        for (auto it = ret.first; it != ret.second; ++it)
        {
            output.push_back(it->second);
        }
    }
    return output;
}

bool Options::hasOption(std::string const& name) const
{
    try
    {
        (void)getOption(name);
        return true;
    }
    catch (Option::not_found)
    {}
    return false;
}

void Options::dump() const
{
    std::cout << *this;
}

std::ostream& operator<<(std::ostream& ostr, const Options& options)
{
    const boost::property_tree::ptree tree = pdal::Utils::toPTree(options);

    boost::property_tree::write_json(ostr, tree);

    return ostr;
}

} // namespace pdal
<|endoftext|>