<commit_before>/*
    sybase.cpp

    Sybase DB layer for QORE
    uses Sybase OpenClient C library

    Qore Programming language

    Copyright (C) 2003 - 2018 Qore Technologies, s.r.o.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

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

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

#include <ctpublic.h>
#include <assert.h>
#include <ctype.h>
#include <memory>
#include <string>
#include <vector>

#include "sybase.h"
#include "connection.h"
#include "encoding_helpers.h"

#include "minitest.hpp"

#ifdef SYBASE
DLLEXPORT char qore_module_name[] = "sybase";
DLLEXPORT char qore_module_description[] = "Sybase database driver";
#else
DLLEXPORT char qore_module_name[] = "freetds";
DLLEXPORT char qore_module_description[] = "FreeTDS-based database driver for MS-SQL Server and Sybase";
#endif
DLLEXPORT char qore_module_version[] = PACKAGE_VERSION;
DLLEXPORT char qore_module_author[] = "Qore Technologies";
DLLEXPORT char qore_module_url[] = "http://qore.org";
DLLEXPORT int qore_module_api_major = QORE_MODULE_API_MAJOR;
DLLEXPORT int qore_module_api_minor = QORE_MODULE_API_MINOR;
DLLEXPORT qore_module_init_t qore_module_init = sybase_module_init;
DLLEXPORT qore_module_ns_init_t qore_module_ns_init = sybase_module_ns_init;
DLLEXPORT qore_module_delete_t qore_module_delete = sybase_module_delete;
#ifdef _QORE_HAS_QL_MIT
DLLEXPORT qore_license_t qore_module_license = QL_MIT;
#else
DLLEXPORT qore_license_t qore_module_license = QL_LGPL;
#endif
DLLEXPORT char qore_module_license_str[] = "MIT";
static DBIDriver* DBID_SYBASE;

// capabilities of this driver
int DBI_SYBASE_CAPS =
   DBI_CAP_TRANSACTION_MANAGEMENT
   | DBI_CAP_CHARSET_SUPPORT
   | DBI_CAP_LOB_SUPPORT
   | DBI_CAP_STORED_PROCEDURES
   | DBI_CAP_BIND_BY_VALUE
   | DBI_CAP_BIND_BY_PLACEHOLDER
   | DBI_CAP_HAS_NUMBER_SUPPORT
   | DBI_CAP_AUTORECONNECT
   | DBI_CAP_HAS_EXECRAW
   | DBI_CAP_TIME_ZONE_SUPPORT
   | DBI_CAP_SERVER_TIME_ZONE
   ;

#define BEGIN_CALLBACK \
       do { \
           try { do {} while(0)

#define END_CALLBACK(RV) \
           } catch (const ss::Error &e) { \
               e.raise(xsink); \
               return RV; \
           }\
      } while(0)

/*
#ifdef DEBUG
// exported
AbstractQoreNode* runSybaseTests(const QoreListNode *params, ExceptionSink *xsink) {
   minitest::result res = minitest::execute_all_tests();
   if (res.all_tests_succeeded) {
      printf("************************************************\n");
      printf("Sybase module: %d tests succeeded\n", res.sucessful_tests_count);
      printf("************************************************\n");
      return 0;
   }

   xsink->raiseException("SYBASE-TEST-FAILURE", "Sybase test in file %s, line %d threw an exception.",
			 res.failed_test_file, res.failed_test_line);
   return 0;
}

AbstractQoreNode* runRecentSybaseTests(const QoreListNode *params, ExceptionSink *xsink) {
   minitest::result res = minitest::test_last_changed_files(1);
   if (res.all_tests_succeeded) {
      printf("************************************************\n");
      printf("Sybase module: %d recent tests succeeded\n", res.sucessful_tests_count);
      printf("************************************************\n");
      return 0;
   }

   xsink->raiseException("SYBASE-TEST-FAILURE", "Sybase test in file %s, line %d threw an exception.",
			 res.failed_test_file, res.failed_test_line);
   return 0;
}
#endif
*/

static int sybase_open(Datasource *ds, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    // username is a required parameter
    if (!ds->getUsername()) {
        xsink->raiseException("DATASOURCE-MISSING-USERNAME", "Datasource has an empty username parameter");
        return -1;
    }

    // DB name is a required parameter
    if (!ds->getDBName()) {
        xsink->raiseException("DATASOURCE-MISSING-DBNAME", "Datasource has an empty dbname parameter");
        return -1;
    }

    // set the encoding for the connection
    if (ds->getDBEncoding()) {
        const QoreEncoding *enc = name_to_QoreEncoding(ds->getDBEncoding());
        ds->setQoreEncoding(enc);
    }
    else {
        const char *enc = QoreEncoding_to_SybaseName(QCS_DEFAULT);
        // if the encoding cannot be mapped, throw a Qore-language exception and return
        if (!enc) {
            xsink->raiseException("TDS-UNKNOWN-CHARACTER-SET", "cannot find the Sybase character encoding equivalent for '%s'", QCS_DEFAULT->getCode());
            return -1;
        }
        ds->setDBEncoding(enc);
        ds->setQoreEncoding(QCS_DEFAULT);
    }

    // create the connection object
    std::unique_ptr<connection> sc(new connection(ds, xsink));
    if (*xsink)
        return -1;

#ifdef QORE_HAS_DATASOURCE_PORT
    int port = ds->getPort();
#else
    int port = 0;
#endif

    if (port && !ds->getHostName()) {
        xsink->raiseException("TDS-CONNECT-ERROR", "port is set to %d, but no hostname is set; both hostname and port must be set to override the interfaces file", port);
        return -1;
    }

    if (!port && ds->getHostName()) {
        xsink->raiseException("TDS-CONNECT-ERROR", "hostname is set to '%s', but no port is set; both hostname and port must be set to override the interfaces file", ds->getHostName());
        return -1;
    }

    // make the actual connection to the database
    sc->init(ds->getUsername(), ds->getPassword() ? ds->getPassword() : "", ds->getDBName(), ds->getDBEncoding(), ds->getQoreEncoding(), ds->getHostName(), port, xsink);
    // return with an error if it didn't work
    if (*xsink)
        return -1;

    // set the private data
    ds->setPrivateData(sc.release());

    // return 0 for OK
    return 0;
    END_CALLBACK(-1);
}

static int sybase_close(Datasource *ds) {
   try {
       connection* sc = (connection*)ds->getPrivateData();
       ds->setPrivateData(0);
       delete sc;
   } catch (const ss::Error &e) {}
   return 0;
}

static AbstractQoreNode* sybase_select(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection *conn = (connection*)ds->getPrivateData();
   return conn->select(qstr, args, xsink).takeNode();
   END_CALLBACK(0);
}

static QoreHashNode* sybase_select_row(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection *conn = (connection*)ds->getPrivateData();
   ValueHolder holder(conn->exec_row(qstr, args, xsink), xsink);
   qore_type_t nt = holder->getType();
   if (nt != NT_HASH && nt != NT_NOTHING) {
      if (!*xsink)
         xsink->raiseException("DBI-SELECT-ROW-ERROR", "selectRow() returned type '%s'; expecting a hash for a single row", holder->getTypeName());
      holder.release().discard(xsink);
   }
   return holder ? holder.release().get<QoreHashNode>() : nullptr;
   END_CALLBACK(0);
}

static AbstractQoreNode* sybase_select_rows(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    QoreValue rv = conn->exec_rows(qstr, args, xsink);
    if (rv.getType() == NT_HASH) {
        QoreListNode* l = new QoreListNode(autoTypeInfo);
        l->push(rv, xsink);
        rv = l;
    }
    return rv.takeNode();
    //return conn->exec_rows(qstr, args, xsink);
    END_CALLBACK(0);
}

static AbstractQoreNode* sybase_exec(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection *conn = (connection*)ds->getPrivateData();
   QoreValue rv = conn->exec(qstr, args, xsink);
   if (!rv) {
       rv = 0;
   }
   return rv.takeNode();
   END_CALLBACK(0);
}

#ifdef _QORE_HAS_DBI_EXECRAW
static AbstractQoreNode* sybase_execRaw(Datasource *ds, const QoreString *qstr, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection *conn = (connection*)ds->getPrivateData();
   QoreValue rv = conn->execRaw(qstr, xsink);
   if (!rv) {
       rv = 0;
   }
   return rv.takeNode();
   END_CALLBACK(0);
}
#endif

static int sybase_commit(Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection* conn = (connection*)ds->getPrivateData();
   return conn->commit(xsink);
   END_CALLBACK(0);
}

static int sybase_rollback(Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection* conn = (connection*)ds->getPrivateData();
   return conn->rollback(xsink);
   END_CALLBACK(0);
}

static AbstractQoreNode *sybase_get_client_version(const Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   context m_context(xsink);
   if (!m_context)
      return 0;

   return m_context.get_client_version(xsink);
   END_CALLBACK(0);
}

static AbstractQoreNode *sybase_get_server_version(Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection* conn = (connection*)ds->getPrivateData();
   return conn->get_server_version(xsink).takeNode();
   END_CALLBACK(0);
}

static int sybase_opt_set(Datasource* ds, const char* opt, const AbstractQoreNode* val, ExceptionSink* xsink) {
   BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    return conn->setOption(opt, val, xsink);
   END_CALLBACK(0);
}

static AbstractQoreNode* sybase_opt_get(const Datasource* ds, const char* opt) {
    try {
        connection *conn = (connection*)ds->getPrivateData();
        return conn->getOption(opt).takeNode();
    } catch (const ss::Error &e) {
        return 0;
    }
}

namespace ss {
    void init(qore_dbi_method_list &methods);
}

QoreStringNode *sybase_module_init() {
   QORE_TRACE("sybase_module_init()");

   // init_namespace();

/*
#ifdef DEBUG
   builtinFunctions.add("runSybaseTests", runSybaseTests, QDOM_DATABASE);
   builtinFunctions.add("runRecentSybaseTests", runRecentSybaseTests, QDOM_DATABASE);
#endif
*/

   // register driver with DBI subsystem
   qore_dbi_method_list methods;
   methods.add(QDBI_METHOD_OPEN, sybase_open);
   methods.add(QDBI_METHOD_CLOSE, sybase_close);
   methods.add(QDBI_METHOD_SELECT, sybase_select);
   methods.add(QDBI_METHOD_SELECT_ROW, sybase_select_row);
   methods.add(QDBI_METHOD_SELECT_ROWS, sybase_select_rows);
   methods.add(QDBI_METHOD_EXEC, sybase_exec);
   methods.add(QDBI_METHOD_EXECRAW, sybase_execRaw);
   methods.add(QDBI_METHOD_COMMIT, sybase_commit);
   methods.add(QDBI_METHOD_ROLLBACK, sybase_rollback);
   methods.add(QDBI_METHOD_GET_CLIENT_VERSION, sybase_get_client_version);
   methods.add(QDBI_METHOD_GET_SERVER_VERSION, sybase_get_server_version);

   methods.add(QDBI_METHOD_OPT_SET, sybase_opt_set);
   methods.add(QDBI_METHOD_OPT_GET, sybase_opt_get);

   methods.registerOption(DBI_OPT_NUMBER_OPT, "when set, numeric/decimal values are returned as integers if possible, otherwise as arbitrary-precision number values; the argument is ignored; setting this option turns it on and turns off 'string-numbers' and 'numeric-numbers'");
   methods.registerOption(DBI_OPT_NUMBER_STRING, "when set, numeric/decimal values are returned as strings for backwards-compatibility; the argument is ignored; setting this option turns it on and turns off 'optimal-numbers' and 'numeric-numbers'");
   methods.registerOption(DBI_OPT_NUMBER_NUMERIC, "when set, numeric/decimal values are returned as arbitrary-precision number values; the argument is ignored; setting this option turns it on and turns off 'string-numbers' and 'optimal-numbers'");
   methods.registerOption(DBI_OPT_TIMEZONE, "set the server-side timezone,"
           " value must be a string in the format accepted by"
           " Timezone::constructor() on the client (ie either a region"
           " name or a UTC offset like \"+01:00\"), if not set the"
           " server's time zone will be assumed to be the same as"
           " the client's", stringTypeInfo);

   ss::init(methods);

#ifdef SYBASE
   DBID_SYBASE = DBI.registerDriver("sybase", methods, DBI_SYBASE_CAPS);
#else
   DBID_SYBASE = DBI.registerDriver("freetds", methods, DBI_SYBASE_CAPS);
#endif

   return 0;
}

void sybase_module_ns_init(QoreNamespace *rns, QoreNamespace *qns) {
}

void sybase_module_delete() {
   QORE_TRACE("sybase_module_delete()");
}
<commit_msg>refs qorelanguage/qore#1573 updated to QoreValue DBI API<commit_after>/*
    sybase.cpp

    Sybase DB layer for QORE
    uses Sybase OpenClient C library

    Qore Programming language

    Copyright (C) 2003 - 2018 Qore Technologies, s.r.o.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

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

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

#include <ctpublic.h>
#include <assert.h>
#include <ctype.h>
#include <memory>
#include <string>
#include <vector>

#include "sybase.h"
#include "connection.h"
#include "encoding_helpers.h"

#include "minitest.hpp"

#ifdef SYBASE
DLLEXPORT char qore_module_name[] = "sybase";
DLLEXPORT char qore_module_description[] = "Sybase database driver";
#else
DLLEXPORT char qore_module_name[] = "freetds";
DLLEXPORT char qore_module_description[] = "FreeTDS-based database driver for MS-SQL Server and Sybase";
#endif
DLLEXPORT char qore_module_version[] = PACKAGE_VERSION;
DLLEXPORT char qore_module_author[] = "Qore Technologies";
DLLEXPORT char qore_module_url[] = "http://qore.org";
DLLEXPORT int qore_module_api_major = QORE_MODULE_API_MAJOR;
DLLEXPORT int qore_module_api_minor = QORE_MODULE_API_MINOR;
DLLEXPORT qore_module_init_t qore_module_init = sybase_module_init;
DLLEXPORT qore_module_ns_init_t qore_module_ns_init = sybase_module_ns_init;
DLLEXPORT qore_module_delete_t qore_module_delete = sybase_module_delete;
DLLEXPORT qore_license_t qore_module_license = QL_MIT;
DLLEXPORT char qore_module_license_str[] = "MIT";
static DBIDriver* DBID_SYBASE;

// capabilities of this driver
int DBI_SYBASE_CAPS =
   DBI_CAP_TRANSACTION_MANAGEMENT
   | DBI_CAP_CHARSET_SUPPORT
   | DBI_CAP_LOB_SUPPORT
   | DBI_CAP_STORED_PROCEDURES
   | DBI_CAP_BIND_BY_VALUE
   | DBI_CAP_BIND_BY_PLACEHOLDER
   | DBI_CAP_HAS_NUMBER_SUPPORT
   | DBI_CAP_AUTORECONNECT
   | DBI_CAP_HAS_EXECRAW
   | DBI_CAP_TIME_ZONE_SUPPORT
   | DBI_CAP_SERVER_TIME_ZONE
   ;

#define BEGIN_CALLBACK \
       do { \
           try { do {} while(0)

#define END_CALLBACK(RV) \
           } catch (const ss::Error &e) { \
               e.raise(xsink); \
               return RV; \
           }\
      } while(0)

/*
#ifdef DEBUG
// exported
AbstractQoreNode* runSybaseTests(const QoreListNode *params, ExceptionSink *xsink) {
   minitest::result res = minitest::execute_all_tests();
   if (res.all_tests_succeeded) {
      printf("************************************************\n");
      printf("Sybase module: %d tests succeeded\n", res.sucessful_tests_count);
      printf("************************************************\n");
      return 0;
   }

   xsink->raiseException("SYBASE-TEST-FAILURE", "Sybase test in file %s, line %d threw an exception.",
			 res.failed_test_file, res.failed_test_line);
   return 0;
}

AbstractQoreNode* runRecentSybaseTests(const QoreListNode *params, ExceptionSink *xsink) {
   minitest::result res = minitest::test_last_changed_files(1);
   if (res.all_tests_succeeded) {
      printf("************************************************\n");
      printf("Sybase module: %d recent tests succeeded\n", res.sucessful_tests_count);
      printf("************************************************\n");
      return 0;
   }

   xsink->raiseException("SYBASE-TEST-FAILURE", "Sybase test in file %s, line %d threw an exception.",
			 res.failed_test_file, res.failed_test_line);
   return 0;
}
#endif
*/

static int sybase_open(Datasource *ds, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    // username is a required parameter
    if (!ds->getUsername()) {
        xsink->raiseException("DATASOURCE-MISSING-USERNAME", "Datasource has an empty username parameter");
        return -1;
    }

    // DB name is a required parameter
    if (!ds->getDBName()) {
        xsink->raiseException("DATASOURCE-MISSING-DBNAME", "Datasource has an empty dbname parameter");
        return -1;
    }

    // set the encoding for the connection
    if (ds->getDBEncoding()) {
        const QoreEncoding *enc = name_to_QoreEncoding(ds->getDBEncoding());
        ds->setQoreEncoding(enc);
    }
    else {
        const char *enc = QoreEncoding_to_SybaseName(QCS_DEFAULT);
        // if the encoding cannot be mapped, throw a Qore-language exception and return
        if (!enc) {
            xsink->raiseException("TDS-UNKNOWN-CHARACTER-SET", "cannot find the Sybase character encoding equivalent for '%s'", QCS_DEFAULT->getCode());
            return -1;
        }
        ds->setDBEncoding(enc);
        ds->setQoreEncoding(QCS_DEFAULT);
    }

    // create the connection object
    std::unique_ptr<connection> sc(new connection(ds, xsink));
    if (*xsink)
        return -1;

    int port = ds->getPort();

    if (port && !ds->getHostName()) {
        xsink->raiseException("TDS-CONNECT-ERROR", "port is set to %d, but no hostname is set; both hostname and port must be set to override the interfaces file", port);
        return -1;
    }

    if (!port && ds->getHostName()) {
        xsink->raiseException("TDS-CONNECT-ERROR", "hostname is set to '%s', but no port is set; both hostname and port must be set to override the interfaces file", ds->getHostName());
        return -1;
    }

    // make the actual connection to the database
    sc->init(ds->getUsername(), ds->getPassword() ? ds->getPassword() : "", ds->getDBName(), ds->getDBEncoding(), ds->getQoreEncoding(), ds->getHostName(), port, xsink);
    // return with an error if it didn't work
    if (*xsink)
        return -1;

    // set the private data
    ds->setPrivateData(sc.release());

    // return 0 for OK
    return 0;
    END_CALLBACK(-1);
}

static int sybase_close(Datasource *ds) {
    try {
        connection* sc = (connection*)ds->getPrivateData();
        ds->setPrivateData(0);
        delete sc;
    } catch (const ss::Error &e) {}
    return 0;
}

static QoreValue sybase_select(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    return conn->select(qstr, args, xsink);
    END_CALLBACK(0);
}

static QoreHashNode* sybase_select_row(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection *conn = (connection*)ds->getPrivateData();
   ValueHolder holder(conn->exec_row(qstr, args, xsink), xsink);
   qore_type_t nt = holder->getType();
   if (nt != NT_HASH && nt != NT_NOTHING) {
      if (!*xsink)
         xsink->raiseException("DBI-SELECT-ROW-ERROR", "selectRow() returned type '%s'; expecting a hash for a single row", holder->getTypeName());
      holder.release().discard(xsink);
   }
   return holder ? holder.release().get<QoreHashNode>() : nullptr;
   END_CALLBACK(0);
}

static QoreValue sybase_select_rows(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    QoreValue rv = conn->exec_rows(qstr, args, xsink);
    if (rv.getType() == NT_HASH) {
        QoreListNode* l = new QoreListNode(autoTypeInfo);
        l->push(rv, xsink);
        rv = l;
    }
    return rv;
    //return conn->exec_rows(qstr, args, xsink);
    END_CALLBACK(0);
}

static QoreValue sybase_exec(Datasource *ds, const QoreString *qstr, const QoreListNode *args, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    QoreValue rv = conn->exec(qstr, args, xsink);
    if (!rv) {
        rv = 0;
    }
    return rv;
    END_CALLBACK(0);
}

static QoreValue sybase_execRaw(Datasource *ds, const QoreString *qstr, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    QoreValue rv = conn->execRaw(qstr, xsink);
    if (!rv) {
        rv = 0;
    }
    return rv;
    END_CALLBACK(0);
}

static int sybase_commit(Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection* conn = (connection*)ds->getPrivateData();
   return conn->commit(xsink);
   END_CALLBACK(0);
}

static int sybase_rollback(Datasource *ds, ExceptionSink *xsink) {
   BEGIN_CALLBACK;
   connection* conn = (connection*)ds->getPrivateData();
   return conn->rollback(xsink);
   END_CALLBACK(0);
}

static QoreValue sybase_get_client_version(const Datasource *ds, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    context m_context(xsink);
    if (!m_context)
        return QoreValue();

    return m_context.get_client_version(xsink);
    END_CALLBACK(0);
}

static QoreValue sybase_get_server_version(Datasource *ds, ExceptionSink *xsink) {
    BEGIN_CALLBACK;
    connection* conn = (connection*)ds->getPrivateData();
    return conn->get_server_version(xsink);
    END_CALLBACK(0);
}

static int sybase_opt_set(Datasource* ds, const char* opt, const QoreValue val, ExceptionSink* xsink) {
    BEGIN_CALLBACK;
    connection *conn = (connection*)ds->getPrivateData();
    return conn->setOption(opt, val, xsink);
    END_CALLBACK(0);
}

static QoreValue sybase_opt_get(const Datasource* ds, const char* opt) {
    try {
        connection *conn = (connection*)ds->getPrivateData();
        return conn->getOption(opt).takeNode();
    } catch (const ss::Error &e) {
        return QoreValue();
    }
}

namespace ss {
    void init(qore_dbi_method_list &methods);
}

QoreStringNode *sybase_module_init() {
   QORE_TRACE("sybase_module_init()");

   // init_namespace();

/*
#ifdef DEBUG
   builtinFunctions.add("runSybaseTests", runSybaseTests, QDOM_DATABASE);
   builtinFunctions.add("runRecentSybaseTests", runRecentSybaseTests, QDOM_DATABASE);
#endif
*/

   // register driver with DBI subsystem
   qore_dbi_method_list methods;
   methods.add(QDBI_METHOD_OPEN, sybase_open);
   methods.add(QDBI_METHOD_CLOSE, sybase_close);
   methods.add(QDBI_METHOD_SELECT, sybase_select);
   methods.add(QDBI_METHOD_SELECT_ROW, sybase_select_row);
   methods.add(QDBI_METHOD_SELECT_ROWS, sybase_select_rows);
   methods.add(QDBI_METHOD_EXEC, sybase_exec);
   methods.add(QDBI_METHOD_EXECRAW, sybase_execRaw);
   methods.add(QDBI_METHOD_COMMIT, sybase_commit);
   methods.add(QDBI_METHOD_ROLLBACK, sybase_rollback);
   methods.add(QDBI_METHOD_GET_CLIENT_VERSION, sybase_get_client_version);
   methods.add(QDBI_METHOD_GET_SERVER_VERSION, sybase_get_server_version);

   methods.add(QDBI_METHOD_OPT_SET, sybase_opt_set);
   methods.add(QDBI_METHOD_OPT_GET, sybase_opt_get);

   methods.registerOption(DBI_OPT_NUMBER_OPT, "when set, numeric/decimal values are returned as integers if possible, otherwise as arbitrary-precision number values; the argument is ignored; setting this option turns it on and turns off 'string-numbers' and 'numeric-numbers'");
   methods.registerOption(DBI_OPT_NUMBER_STRING, "when set, numeric/decimal values are returned as strings for backwards-compatibility; the argument is ignored; setting this option turns it on and turns off 'optimal-numbers' and 'numeric-numbers'");
   methods.registerOption(DBI_OPT_NUMBER_NUMERIC, "when set, numeric/decimal values are returned as arbitrary-precision number values; the argument is ignored; setting this option turns it on and turns off 'string-numbers' and 'optimal-numbers'");
   methods.registerOption(DBI_OPT_TIMEZONE, "set the server-side timezone,"
           " value must be a string in the format accepted by"
           " Timezone::constructor() on the client (ie either a region"
           " name or a UTC offset like \"+01:00\"), if not set the"
           " server's time zone will be assumed to be the same as"
           " the client's", stringTypeInfo);

   ss::init(methods);

#ifdef SYBASE
   DBID_SYBASE = DBI.registerDriver("sybase", methods, DBI_SYBASE_CAPS);
#else
   DBID_SYBASE = DBI.registerDriver("freetds", methods, DBI_SYBASE_CAPS);
#endif

   return 0;
}

void sybase_module_ns_init(QoreNamespace *rns, QoreNamespace *qns) {
}

void sybase_module_delete() {
   QORE_TRACE("sybase_module_delete()");
}
<|endoftext|>


<commit_before><commit_msg>Core: gdb detection<commit_after><|endoftext|>


<commit_before>/*
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include <vector>
#include <limits>
#include "kernel/environment.h"
#include "kernel/kernel_exception.h"

namespace lean {
/**
   \brief "Do nothing" normalizer extension.
*/
class noop_normalizer_extension : public normalizer_extension {
public:
    virtual optional<expr> operator()(expr const &, extension_context &) const {
        return none_expr();
    }
};

environment_header::environment_header(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative,
                                       list<name> const & cls_proof_irrel, std::unique_ptr<normalizer_extension const> ext):
    m_trust_lvl(trust_lvl), m_prop_proof_irrel(prop_proof_irrel), m_eta(eta), m_impredicative(impredicative),
    m_cls_proof_irrel(cls_proof_irrel), m_norm_ext(std::move(ext)) {}

environment_extension::~environment_extension() {}

environment_id::environment_id():m_trail(0, list<unsigned>()) {}

environment_id::environment_id(environment_id const & ancestor, bool):m_trail(car(ancestor.m_trail) + 1, ancestor.m_trail) {}

bool environment_id::is_descendant(environment_id const & id) const {
    list<unsigned> const * it = &m_trail;
    while (!is_nil(*it)) {
        if (is_eqp(*it, id.m_trail))
            return true;
        if (car(*it) < car(id.m_trail))
            return false;
        it = &cdr(*it);
    }
    return false;
}

environment::environment(header const & h, environment_id const & ancestor, definitions const & d, name_set const & g, extensions const & exts):
    m_header(h), m_id(environment_id::mk_descendant(ancestor)), m_definitions(d), m_global_levels(g), m_extensions(exts) {}

environment::environment(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative, list<name> const & cls_proof_irrel):
    environment(trust_lvl, prop_proof_irrel, eta, impredicative, cls_proof_irrel, std::unique_ptr<normalizer_extension>(new noop_normalizer_extension()))
{}

environment::environment(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative, list<name> const & cls_proof_irrel,
                         std::unique_ptr<normalizer_extension> ext):
    m_header(std::make_shared<environment_header>(trust_lvl, prop_proof_irrel, eta, impredicative, cls_proof_irrel, std::move(ext))),
    m_extensions(std::make_shared<environment_extensions const>())
{}

environment::~environment() {}

optional<definition> environment::find(name const & n) const {
    definition const * r = m_definitions.find(n);
    return r ? some_definition(*r) : none_definition();
}

definition environment::get(name const & n) const {
    definition const * r = m_definitions.find(n);
    if (!r)
        throw_unknown_declaration(*this, n);
    return *r;
}

[[ noreturn ]] void throw_incompatible_environment(environment const & env) {
    throw_kernel_exception(env, "invalid declaration, it was checked/certified in an incompatible environment");
}

environment environment::add(certified_definition const & d) const {
    if (!m_id.is_descendant(d.get_id()))
        throw_incompatible_environment(*this);
    name const & n = d.get_definition().get_name();
    if (find(n))
        throw_already_declared(*this, n);
    return environment(m_header, m_id, insert(m_definitions, n, d.get_definition()), m_global_levels, m_extensions);
}

environment environment::add_global_level(name const & n) const {
    if (m_global_levels.contains(n))
        throw_kernel_exception(*this,
                               "invalid global universe level declaration, environment already contains a universe level with the given name");
    return environment(m_header, m_id, m_definitions, insert(m_global_levels, n), m_extensions);
}

bool environment::is_global_level(name const & n) const {
    return m_global_levels.contains(n);
}

environment environment::replace(certified_definition const & t) const {
    if (!m_id.is_descendant(t.get_id()))
        throw_incompatible_environment(*this);
    name const & n = t.get_definition().get_name();
    auto ax = find(n);
    if (!ax)
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the environment does not have an axiom with the given name");
    if (!ax->is_axiom())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the current declaration in the environment is not an axiom");
    if (!t.get_definition().is_theorem())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the new declaration is not a theorem");
    if (ax->get_type() != t.get_definition().get_type())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the 'replace' operation can only be used when the axiom and theorem have the same type");
    return environment(m_header, m_id, insert(m_definitions, n, t.get_definition()), m_global_levels, m_extensions);
}

environment environment::forget() const {
    return environment(m_header, environment_id(), m_definitions, m_global_levels, m_extensions);
}

class extension_manager {
    std::vector<std::shared_ptr<environment_extension const>> m_exts;
    mutex                                                     m_mutex;
public:
    unsigned register_extension(std::shared_ptr<environment_extension const> const & ext) {
        lock_guard<mutex> lock(m_mutex);
        unsigned r = m_exts.size();
        m_exts.push_back(ext);
        return r;
    }

    bool has_ext(unsigned extid) const { return extid < m_exts.size(); }

    environment_extension const & get_initial(unsigned extid) {
        lock_guard<mutex> lock(m_mutex);
        return *(m_exts[extid].get());
    }
};

static std::unique_ptr<extension_manager> g_extension_manager;

static extension_manager & get_extension_manager() {
    if (!g_extension_manager)
        g_extension_manager.reset(new extension_manager());
    return *g_extension_manager;
}

unsigned environment::register_extension(std::shared_ptr<environment_extension const> const & initial) {
    return get_extension_manager().register_extension(initial);
}

[[ noreturn ]] void throw_invalid_extension(environment const & env) {
    throw_kernel_exception(env, "invalid environment extension identifier");
}

environment_extension const & environment::get_extension(unsigned id) const {
    if (id >= get_extension_manager().has_ext(id))
        throw_invalid_extension(*this);
    if (id < m_extensions->size() || !(*m_extensions)[id])
        return get_extension_manager().get_initial(id);
    return *((*m_extensions)[id].get());
}

environment environment::update(unsigned id, std::shared_ptr<environment_extension const> const & ext) const {
    if (id >= get_extension_manager().has_ext(id))
        throw_invalid_extension(*this);
    auto new_exts = std::make_shared<environment_extensions>(*m_extensions);
    if (id >= new_exts->size())
        new_exts->resize(id+1);
    (*new_exts)[id] = ext;
    return environment(m_header, m_id, m_definitions, m_global_levels, new_exts);
}
}
<commit_msg>fix(kernel/environment): bug in get_extension<commit_after>/*
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include <vector>
#include <limits>
#include "kernel/environment.h"
#include "kernel/kernel_exception.h"

namespace lean {
/**
   \brief "Do nothing" normalizer extension.
*/
class noop_normalizer_extension : public normalizer_extension {
public:
    virtual optional<expr> operator()(expr const &, extension_context &) const {
        return none_expr();
    }
};

environment_header::environment_header(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative,
                                       list<name> const & cls_proof_irrel, std::unique_ptr<normalizer_extension const> ext):
    m_trust_lvl(trust_lvl), m_prop_proof_irrel(prop_proof_irrel), m_eta(eta), m_impredicative(impredicative),
    m_cls_proof_irrel(cls_proof_irrel), m_norm_ext(std::move(ext)) {}

environment_extension::~environment_extension() {}

environment_id::environment_id():m_trail(0, list<unsigned>()) {}

environment_id::environment_id(environment_id const & ancestor, bool):m_trail(car(ancestor.m_trail) + 1, ancestor.m_trail) {}

bool environment_id::is_descendant(environment_id const & id) const {
    list<unsigned> const * it = &m_trail;
    while (!is_nil(*it)) {
        if (is_eqp(*it, id.m_trail))
            return true;
        if (car(*it) < car(id.m_trail))
            return false;
        it = &cdr(*it);
    }
    return false;
}

environment::environment(header const & h, environment_id const & ancestor, definitions const & d, name_set const & g, extensions const & exts):
    m_header(h), m_id(environment_id::mk_descendant(ancestor)), m_definitions(d), m_global_levels(g), m_extensions(exts) {}

environment::environment(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative, list<name> const & cls_proof_irrel):
    environment(trust_lvl, prop_proof_irrel, eta, impredicative, cls_proof_irrel, std::unique_ptr<normalizer_extension>(new noop_normalizer_extension()))
{}

environment::environment(unsigned trust_lvl, bool prop_proof_irrel, bool eta, bool impredicative, list<name> const & cls_proof_irrel,
                         std::unique_ptr<normalizer_extension> ext):
    m_header(std::make_shared<environment_header>(trust_lvl, prop_proof_irrel, eta, impredicative, cls_proof_irrel, std::move(ext))),
    m_extensions(std::make_shared<environment_extensions const>())
{}

environment::~environment() {}

optional<definition> environment::find(name const & n) const {
    definition const * r = m_definitions.find(n);
    return r ? some_definition(*r) : none_definition();
}

definition environment::get(name const & n) const {
    definition const * r = m_definitions.find(n);
    if (!r)
        throw_unknown_declaration(*this, n);
    return *r;
}

[[ noreturn ]] void throw_incompatible_environment(environment const & env) {
    throw_kernel_exception(env, "invalid declaration, it was checked/certified in an incompatible environment");
}

environment environment::add(certified_definition const & d) const {
    if (!m_id.is_descendant(d.get_id()))
        throw_incompatible_environment(*this);
    name const & n = d.get_definition().get_name();
    if (find(n))
        throw_already_declared(*this, n);
    return environment(m_header, m_id, insert(m_definitions, n, d.get_definition()), m_global_levels, m_extensions);
}

environment environment::add_global_level(name const & n) const {
    if (m_global_levels.contains(n))
        throw_kernel_exception(*this,
                               "invalid global universe level declaration, environment already contains a universe level with the given name");
    return environment(m_header, m_id, m_definitions, insert(m_global_levels, n), m_extensions);
}

bool environment::is_global_level(name const & n) const {
    return m_global_levels.contains(n);
}

environment environment::replace(certified_definition const & t) const {
    if (!m_id.is_descendant(t.get_id()))
        throw_incompatible_environment(*this);
    name const & n = t.get_definition().get_name();
    auto ax = find(n);
    if (!ax)
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the environment does not have an axiom with the given name");
    if (!ax->is_axiom())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the current declaration in the environment is not an axiom");
    if (!t.get_definition().is_theorem())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the new declaration is not a theorem");
    if (ax->get_type() != t.get_definition().get_type())
        throw_kernel_exception(*this, "invalid replacement of axiom with theorem, the 'replace' operation can only be used when the axiom and theorem have the same type");
    return environment(m_header, m_id, insert(m_definitions, n, t.get_definition()), m_global_levels, m_extensions);
}

environment environment::forget() const {
    return environment(m_header, environment_id(), m_definitions, m_global_levels, m_extensions);
}

class extension_manager {
    std::vector<std::shared_ptr<environment_extension const>> m_exts;
    mutex                                                     m_mutex;
public:
    unsigned register_extension(std::shared_ptr<environment_extension const> const & ext) {
        lock_guard<mutex> lock(m_mutex);
        unsigned r = m_exts.size();
        m_exts.push_back(ext);
        return r;
    }

    bool has_ext(unsigned extid) const { return extid < m_exts.size(); }

    environment_extension const & get_initial(unsigned extid) {
        lock_guard<mutex> lock(m_mutex);
        return *(m_exts[extid].get());
    }
};

static std::unique_ptr<extension_manager> g_extension_manager;

static extension_manager & get_extension_manager() {
    if (!g_extension_manager)
        g_extension_manager.reset(new extension_manager());
    return *g_extension_manager;
}

unsigned environment::register_extension(std::shared_ptr<environment_extension const> const & initial) {
    return get_extension_manager().register_extension(initial);
}

[[ noreturn ]] void throw_invalid_extension(environment const & env) {
    throw_kernel_exception(env, "invalid environment extension identifier");
}

environment_extension const & environment::get_extension(unsigned id) const {
    if (id >= get_extension_manager().has_ext(id))
        throw_invalid_extension(*this);
    if (id >= m_extensions->size() || !(*m_extensions)[id])
        return get_extension_manager().get_initial(id);
    return *((*m_extensions)[id].get());
}

environment environment::update(unsigned id, std::shared_ptr<environment_extension const> const & ext) const {
    if (id >= get_extension_manager().has_ext(id))
        throw_invalid_extension(*this);
    auto new_exts = std::make_shared<environment_extensions>(*m_extensions);
    if (id >= new_exts->size())
        new_exts->resize(id+1);
    (*new_exts)[id] = ext;
    return environment(m_header, m_id, m_definitions, m_global_levels, new_exts);
}
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <algorithm>
#include <limits>
#include "kernel/free_vars.h"
#include "kernel/replace_fn.h"
#include "kernel/declaration.h"
#include "kernel/instantiate.h"

namespace lean {
template<bool rev>
struct instantiate_easy_fn {
    unsigned n;
    expr const * subst;
    instantiate_easy_fn(unsigned _n, expr const * _subst):n(_n), subst(_subst) {}
    optional<expr> operator()(expr const & a, bool app) const {
        if (closed(a))
            return some_expr(a);
        if (is_var(a) && var_idx(a) < n)
            return some_expr(subst[rev ? n - var_idx(a) - 1 : var_idx(a)]);
        if (app && is_app(a))
        if (auto new_a = operator()(app_arg(a), false))
        if (auto new_f = operator()(app_fn(a), true))
            return some_expr(copy_tag(a, mk_app(*new_f, *new_a)));
        return none_expr();
    }
};

expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
    if (s >= get_free_var_range(a) || n == 0)
        return a;
    if (s == 0)
        if (auto r = instantiate_easy_fn<false>(n, subst)(a, true))
            return *r;
    return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
            unsigned s1 = s + offset;
            if (s1 < s)
                return some_expr(m); // overflow, vidx can't be >= max unsigned
            if (s1 >= get_free_var_range(m))
                return some_expr(m); // expression m does not contain free variables with idx >= s1
            if (is_var(m)) {
                unsigned vidx = var_idx(m);
                if (vidx >= s1) {
                    unsigned h = s1 + n;
                    if (h < s1 /* overflow, h is bigger than any vidx */ || vidx < h) {
                        return some_expr(lift_free_vars(subst[vidx - s1], offset));
                    } else {
                        return some_expr(mk_var(vidx - n));
                    }
                }
            }
            return none_expr();
        });
}

expr instantiate(expr const & e, unsigned n, expr const * s) { return instantiate(e, 0, n, s); }
expr instantiate(expr const & e, std::initializer_list<expr> const & l) {  return instantiate(e, l.size(), l.begin()); }
expr instantiate(expr const & e, unsigned i, expr const & s) { return instantiate(e, i, 1, &s); }
expr instantiate(expr const & e, expr const & s) { return instantiate(e, 0, s); }

expr instantiate_rev(expr const & a, unsigned n, expr const * subst) {
    if (closed(a))
        return a;
    if (auto r = instantiate_easy_fn<true>(n, subst)(a, true))
        return *r;
    return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
            if (offset >= get_free_var_range(m))
                return some_expr(m); // expression m does not contain free variables with idx >= offset
            if (is_var(m)) {
                unsigned vidx = var_idx(m);
                if (vidx >= offset) {
                    unsigned h = offset + n;
                    if (h < offset /* overflow, h is bigger than any vidx */ || vidx < h) {
                        return some_expr(lift_free_vars(subst[n - (vidx - offset) - 1], offset));
                    } else {
                        return some_expr(mk_var(vidx - n));
                    }
                }
            }
            return none_expr();
        });
}

bool is_head_beta(expr const & t) {
    expr const * it = &t;
    while (is_app(*it)) {
        expr const & f = app_fn(*it);
        if (is_lambda(f)) {
            return true;
        } else if (is_app(f)) {
            it = &f;
        } else {
            return false;
        }
    }
    return false;
}

expr apply_beta(expr f, unsigned num_args, expr const * args) {
    if (num_args == 0) {
        return f;
    } else if (!is_lambda(f)) {
        return mk_rev_app(f, num_args, args);
    } else {
        unsigned m = 1;
        while (is_lambda(binding_body(f)) && m < num_args) {
            f = binding_body(f);
            m++;
        }
        lean_assert(m <= num_args);
        return mk_rev_app(instantiate(binding_body(f), m, args + (num_args - m)), num_args - m, args);
    }
}

expr head_beta_reduce(expr const & t) {
    if (!is_head_beta(t)) {
        return t;
    } else {
        buffer<expr> args;
        expr const * it = &t;
        while (true) {
            lean_assert(is_app(*it));
            expr const & f = app_fn(*it);
            args.push_back(app_arg(*it));
            if (is_lambda(f)) {
                return apply_beta(f, args.size(), args.data());
            } else {
                lean_assert(is_app(f));
                it = &f;
            }
        }
    }
}

expr beta_reduce(expr t) {
    auto f = [=](expr const & m, unsigned) -> optional<expr> {
        if (is_head_beta(m))
            return some_expr(head_beta_reduce(m));
        else if (is_local(m) || is_metavar(m))
            return some_expr(m); // do not simplify local constants and metavariables types.
        else
            return none_expr();
    };
    while (true) {
        expr new_t = replace(t, f);
        if (new_t == t)
            return new_t;
        else
            t = new_t;
    }
}

expr instantiate_univ_params(expr const & e, level_param_names const & ps, levels const & ls) {
    if (!has_param_univ(e))
        return e;
    return replace(e, [&](expr const & e) -> optional<expr> {
            if (!has_param_univ(e))
                return some_expr(e);
            if (is_constant(e)) {
                return some_expr(update_constant(e, map_reuse(const_levels(e),
                                                              [&](level const & l) { return instantiate(l, ps, ls); },
                                                              [](level const & l1, level const & l2) { return is_eqp(l1, l2); })));
            } else if (is_sort(e)) {
                return some_expr(update_sort(e, instantiate(sort_level(e), ps, ls)));
            } else {
                return none_expr();
            }
        });
}

expr instantiate_type_univ_params(declaration const & d, levels const & ls) {
    lean_assert(length(d.get_univ_params()) == length(ls));
    return instantiate_univ_params(d.get_type(), d.get_univ_params(), ls);
}

expr instantiate_value_univ_params(declaration const & d, levels const & ls) {
    lean_assert(length(d.get_univ_params()) == length(ls));
    return instantiate_univ_params(d.get_value(), d.get_univ_params(), ls);
}
}
<commit_msg>perf(kernel/instantiate): cache result of instantiate_type_univ_params and instantiate_value_univ_params<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <algorithm>
#include <limits>
#include <vector>
#include "kernel/free_vars.h"
#include "kernel/replace_fn.h"
#include "kernel/declaration.h"
#include "kernel/instantiate.h"

#ifndef LEAN_INST_UNIV_CACHE_SIZE
#define LEAN_INST_UNIV_CACHE_SIZE 1023
#endif

namespace lean {
template<bool rev>
struct instantiate_easy_fn {
    unsigned n;
    expr const * subst;
    instantiate_easy_fn(unsigned _n, expr const * _subst):n(_n), subst(_subst) {}
    optional<expr> operator()(expr const & a, bool app) const {
        if (closed(a))
            return some_expr(a);
        if (is_var(a) && var_idx(a) < n)
            return some_expr(subst[rev ? n - var_idx(a) - 1 : var_idx(a)]);
        if (app && is_app(a))
        if (auto new_a = operator()(app_arg(a), false))
        if (auto new_f = operator()(app_fn(a), true))
            return some_expr(copy_tag(a, mk_app(*new_f, *new_a)));
        return none_expr();
    }
};

expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
    if (s >= get_free_var_range(a) || n == 0)
        return a;
    if (s == 0)
        if (auto r = instantiate_easy_fn<false>(n, subst)(a, true))
            return *r;
    return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
            unsigned s1 = s + offset;
            if (s1 < s)
                return some_expr(m); // overflow, vidx can't be >= max unsigned
            if (s1 >= get_free_var_range(m))
                return some_expr(m); // expression m does not contain free variables with idx >= s1
            if (is_var(m)) {
                unsigned vidx = var_idx(m);
                if (vidx >= s1) {
                    unsigned h = s1 + n;
                    if (h < s1 /* overflow, h is bigger than any vidx */ || vidx < h) {
                        return some_expr(lift_free_vars(subst[vidx - s1], offset));
                    } else {
                        return some_expr(mk_var(vidx - n));
                    }
                }
            }
            return none_expr();
        });
}

expr instantiate(expr const & e, unsigned n, expr const * s) { return instantiate(e, 0, n, s); }
expr instantiate(expr const & e, std::initializer_list<expr> const & l) {  return instantiate(e, l.size(), l.begin()); }
expr instantiate(expr const & e, unsigned i, expr const & s) { return instantiate(e, i, 1, &s); }
expr instantiate(expr const & e, expr const & s) { return instantiate(e, 0, s); }

expr instantiate_rev(expr const & a, unsigned n, expr const * subst) {
    if (closed(a))
        return a;
    if (auto r = instantiate_easy_fn<true>(n, subst)(a, true))
        return *r;
    return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
            if (offset >= get_free_var_range(m))
                return some_expr(m); // expression m does not contain free variables with idx >= offset
            if (is_var(m)) {
                unsigned vidx = var_idx(m);
                if (vidx >= offset) {
                    unsigned h = offset + n;
                    if (h < offset /* overflow, h is bigger than any vidx */ || vidx < h) {
                        return some_expr(lift_free_vars(subst[n - (vidx - offset) - 1], offset));
                    } else {
                        return some_expr(mk_var(vidx - n));
                    }
                }
            }
            return none_expr();
        });
}

bool is_head_beta(expr const & t) {
    expr const * it = &t;
    while (is_app(*it)) {
        expr const & f = app_fn(*it);
        if (is_lambda(f)) {
            return true;
        } else if (is_app(f)) {
            it = &f;
        } else {
            return false;
        }
    }
    return false;
}

expr apply_beta(expr f, unsigned num_args, expr const * args) {
    if (num_args == 0) {
        return f;
    } else if (!is_lambda(f)) {
        return mk_rev_app(f, num_args, args);
    } else {
        unsigned m = 1;
        while (is_lambda(binding_body(f)) && m < num_args) {
            f = binding_body(f);
            m++;
        }
        lean_assert(m <= num_args);
        return mk_rev_app(instantiate(binding_body(f), m, args + (num_args - m)), num_args - m, args);
    }
}

expr head_beta_reduce(expr const & t) {
    if (!is_head_beta(t)) {
        return t;
    } else {
        buffer<expr> args;
        expr const * it = &t;
        while (true) {
            lean_assert(is_app(*it));
            expr const & f = app_fn(*it);
            args.push_back(app_arg(*it));
            if (is_lambda(f)) {
                return apply_beta(f, args.size(), args.data());
            } else {
                lean_assert(is_app(f));
                it = &f;
            }
        }
    }
}

expr beta_reduce(expr t) {
    auto f = [=](expr const & m, unsigned) -> optional<expr> {
        if (is_head_beta(m))
            return some_expr(head_beta_reduce(m));
        else if (is_local(m) || is_metavar(m))
            return some_expr(m); // do not simplify local constants and metavariables types.
        else
            return none_expr();
    };
    while (true) {
        expr new_t = replace(t, f);
        if (new_t == t)
            return new_t;
        else
            t = new_t;
    }
}

expr instantiate_univ_params(expr const & e, level_param_names const & ps, levels const & ls) {
    if (!has_param_univ(e))
        return e;
    return replace(e, [&](expr const & e) -> optional<expr> {
            if (!has_param_univ(e))
                return some_expr(e);
            if (is_constant(e)) {
                return some_expr(update_constant(e, map_reuse(const_levels(e),
                                                              [&](level const & l) { return instantiate(l, ps, ls); },
                                                              [](level const & l1, level const & l2) { return is_eqp(l1, l2); })));
            } else if (is_sort(e)) {
                return some_expr(update_sort(e, instantiate(sort_level(e), ps, ls)));
            } else {
                return none_expr();
            }
        });
}

class instantiate_univ_cache {
    typedef std::tuple<declaration, levels, expr> entry;
    std::vector<optional<entry>> m_cache;
public:
    instantiate_univ_cache() {
        m_cache.resize(LEAN_INST_UNIV_CACHE_SIZE);
    }

    optional<expr> is_cached(declaration const & d, levels const & ls) {
        unsigned idx = d.get_name().hash() % LEAN_INST_UNIV_CACHE_SIZE;
        if (auto it = m_cache[idx]) {
            declaration d_c; levels ls_c; expr r_c;
            std::tie(d_c, ls_c, r_c) = *it;
            if (!is_eqp(d_c, d))
                return none_expr();
            if (ls == ls_c)
                return some_expr(r_c);
            else
                return none_expr();
        }
        return none_expr();
    }
    void save(declaration const & d, levels const & ls, expr const & r) {
        unsigned idx = d.get_name().hash() % LEAN_INST_UNIV_CACHE_SIZE;
        m_cache[idx] = entry(d, ls, r);
    }
};

MK_THREAD_LOCAL_GET_DEF(instantiate_univ_cache, get_type_univ_cache);
MK_THREAD_LOCAL_GET_DEF(instantiate_univ_cache, get_value_univ_cache);

expr instantiate_type_univ_params(declaration const & d, levels const & ls) {
    lean_assert(length(d.get_univ_params()) == length(ls));
    if (is_nil(ls) || !has_param_univ(d.get_type()))
        return d.get_type();
    instantiate_univ_cache & cache = get_type_univ_cache();
    if (auto r = cache.is_cached(d, ls))
        return *r;
    expr r = instantiate_univ_params(d.get_type(), d.get_univ_params(), ls);
    cache.save(d, ls, r);
    return r;
}

expr instantiate_value_univ_params(declaration const & d, levels const & ls) {
    lean_assert(length(d.get_univ_params()) == length(ls));
    if (is_nil(ls) || !has_param_univ(d.get_value()))
        return d.get_value();
    instantiate_univ_cache & cache = get_value_univ_cache();
    if (auto r = cache.is_cached(d, ls))
        return *r;
    expr r = instantiate_univ_params(d.get_value(), d.get_univ_params(), ls);
    cache.save(d, ls, r);
    return r;
}
}
<|endoftext|>


<commit_before>// REQUIRES: asan-64-bits
// RUN: %clangxx_asan -O3 %s -o %t
// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1  | FileCheck %s --check-prefix=COOKIE
// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1  | FileCheck %s --check-prefix=NO_COOKIE
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int dtor_counter;
struct C {
  int x;
  ~C() {
    fprintf(stderr, "DTOR\n");
    dtor_counter++;
    if (dtor_counter >= 100) {
      fprintf(stderr, "Called DTOR too many times\n");
// NO_COOKIE: Called DTOR too many times
      exit(1);
    }
  }
};

int main(int argc, char **argv) {
  C *buffer = new C[argc];
  delete [] buffer;
  delete [] buffer;
// COOKIE: AddressSanitizer: loaded array cookie from free-d memory
// COOKIE: AddressSanitizer: attempting double-free
}
<commit_msg>[asan] trying to de-flake new_array_cookie_uaf_test.cc<commit_after>// REQUIRES: asan-64-bits
// RUN: %clangxx_asan -O3 %s -o %t
// RUN: ASAN_OPTIONS=poison_array_cookie=1 not %run %t 2>&1  | FileCheck %s --check-prefix=COOKIE
// RUN: ASAN_OPTIONS=poison_array_cookie=0 not %run %t 2>&1  | FileCheck %s --check-prefix=NO_COOKIE
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int dtor_counter;
struct C {
  int x;
  ~C() {
    dtor_counter++;
    fprintf(stderr, "DTOR %d\n", dtor_counter);
  }
};

__attribute__((noinline)) void Delete(C *c) { delete[] c; }
__attribute__((no_sanitize_address)) void Write42ToCookie(C *c) {
  long *p = reinterpret_cast<long*>(c);
  p[-1] = 42;
}

int main(int argc, char **argv) {
  C *buffer = new C[argc];
  delete [] buffer;
  Write42ToCookie(buffer);
  delete [] buffer;
// COOKIE: DTOR 1
// COOKIE-NOT: DTOR 2
// COOKIE: AddressSanitizer: loaded array cookie from free-d memory
// COOKIE: AddressSanitizer: attempting double-free
// NO_COOKIE: DTOR 1
// NO_COOKIE: DTOR 43
// NO_COOKIE-NOT: DTOR 44
// NO_COOKIE-NOT: AddressSanitizer: loaded array cookie from free-d memory
// NO_COOKIE: AddressSanitizer: attempting double-free

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: pview.hxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: rt $ $Date: 2004-08-23 09:01:09 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SWPVIEW_HXX
#define _SWPVIEW_HXX

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif
#ifndef _WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX //autogen
#include <sfx2/viewfrm.hxx>
#endif
#ifndef _VIEWFAC_HXX //autogen
#include <sfx2/viewfac.hxx>
#endif
#ifndef _SFXVIEWSH_HXX //autogen
#include <sfx2/viewsh.hxx>
#endif
#ifndef _SVX_ZOOMITEM_HXX
#include <svx/zoomitem.hxx>
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif
#ifndef _SHELLID_HXX
#include "shellid.hxx"
#endif

class SwViewOption;
class SwDocShell;
class SwScrollbar;
class ViewShell;
class SwPagePreView;
class ImageButton;
class Button;
class SwRect;
class DataChangedEvent;
class CommandEvent;
class SvtAccessibilityOptions;
// OD 12.12.2002 #103492#
class SwPagePreviewLayout;

// OD 24.03.2003 #108282# - delete member <mnVirtPage> and its accessor.
class SwPagePreViewWin : public Window
{
    ViewShell*          mpViewShell;
    USHORT              mnSttPage;
    BYTE                mnRow, mnCol;
    Size                maPxWinSize;
    Fraction            maScale;
    SwPagePreView&      mrView;
    // OD 02.12.2002 #103492#
    bool                mbCalcScaleForPreviewLayout;
    Rectangle           maPaintedPreviewDocRect;
    // OD 12.12.2002 #103492#
    SwPagePreviewLayout* mpPgPrevwLayout;

    void SetPagePreview( BYTE nRow, BYTE nCol );

public:
    SwPagePreViewWin( Window* pParent, SwPagePreView& rView );
    ~SwPagePreViewWin();

    //Ruft ViewShell::Paint
    virtual void Paint( const Rectangle& rRect );
    virtual void KeyInput( const KeyEvent & );
    virtual void Command( const CommandEvent& rCEvt );
    virtual void MouseButtonDown(const MouseEvent& rMEvt);
    virtual void DataChanged( const DataChangedEvent& );

    void SetViewShell( ViewShell* pShell );

    ViewShell* GetViewShell() const { return mpViewShell; }

    BYTE    GetRow() const      { return mnRow; }
    void    SetRow( BYTE n )    { if( n ) mnRow = n; }

    BYTE    GetCol() const      { return mnCol; }
    void    SetCol( BYTE n )    { if( n ) mnCol = n; }

    USHORT  GetSttPage() const      { return mnSttPage; }
    void    SetSttPage( USHORT n )  { mnSttPage = n; }

    /** get selected page number of document preview

        OD 13.12.2002 #103492#

        @author OD

        @return selected page number
    */
    sal_uInt16 SelectedPage() const;

    /** set selected page number in document preview

        OD 13.12.2002 #103492#

        @author OD

        @param _nSelectedPageNum
        input parameter - physical page number of page that will be the selected one.
    */
    void SetSelectedPage( sal_uInt16 _nSelectedPageNum );

    //JP 19.08.98: bei Einspaltigkeit gibt es keine 0. Seite!
    USHORT  GetDefSttPage() const   { return 1 == mnCol ? 1 : 0; }

    void CalcWish( BYTE nNewRow, BYTE nNewCol );

    const Size& GetWinSize() const  { return maPxWinSize; }
    void SetWinSize( const Size& rNewSize );

    // OD 18.12.2002 #103492# - add <MV_SELPAGE>, <MV_SCROLL>
    enum MoveMode{ MV_CALC, MV_PAGE_UP, MV_PAGE_DOWN, MV_DOC_STT, MV_DOC_END,
                   MV_SELPAGE, MV_SCROLL, MV_NEWWINSIZE };
    int MovePage( int eMoveMode );

    // erzeuge den String fuer die StatusLeiste
    void GetStatusStr( String& rStr, USHORT nPageCount ) const;

    void RepaintCoreRect( const SwRect& rRect );

    /** method to adjust preview to a new zoom factor

        OD 02.12.2002 #103492#
        paint of preview is prepared for a new zoom factor
        OD 24.09.2003 #i19975# - zoom type has also been considered.
        Thus, add new parameter <_eZoomType>

        @author OD
    */
    void AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
                                 const SvxZoomType _eZoomType );

    const Rectangle& GetPaintedPreviewDocRect() const
    {
        return maPaintedPreviewDocRect;
    }

    void Scroll(long nXMove, long nYMove);

    /** method to enable/disable book preview

        OD 2004-03-05 #i18143#

        @author OD

        @param _bBookPreview
        input parameter - boolean indicating, if book preview mode has to
        switch on <TRUE> or of <FALSE>

        @return boolean indicating, if book preview mode has changed.
    */
    bool SetBookPreviewMode( const bool _bBookPreview );

    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>
                    CreateAccessible();
};

/*--------------------------------------------------------------------
    Beschreibung:   Sicht auf ein Dokument
 --------------------------------------------------------------------*/

class SW_DLLPUBLIC SwPagePreView: public SfxViewShell
{
    // ViewWindow und Henkel zur Core
    // aktuelle Dispatcher-Shell
    SwPagePreViewWin        aViewWin;
    //viewdata of the previous SwView and the new crsrposition
    String                  sSwViewData,
    //and the new cursor position if the user double click in the PagePreView
                            sNewCrsrPos;
    // to support keyboard the number of the page to go to can be set too
    USHORT                  nNewPage;
    // Sichtbarer Bereich
    String                  sPageStr;
    Size                    aDocSz;
    Rectangle               aVisArea;

    // MDI Bedienelemente
    SwScrollbar             *pHScrollbar;
    SwScrollbar             *pVScrollbar;
    ImageButton             *pPageUpBtn,
                            *pPageDownBtn;
    // Dummy-Window zum Fllen der rechten unteren Ecke, wenn beide Scrollbars
    // aktiv sind
    Window                  *pScrollFill;

    USHORT                  mnPageCount;
    BOOL                    bNormalPrint;

    // OD 09.01.2003 #106334#
    // new members to reset design mode at draw view for form shell on switching
    // back from writer page preview to normal view.
    sal_Bool                mbResetFormDesignMode:1;
    sal_Bool                mbFormDesignModeToReset:1;

    SW_DLLPRIVATE void            Init(const SwViewOption* = 0);
    SW_DLLPRIVATE Point           AlignToPixel(const Point& rPt) const;

    SW_DLLPRIVATE int             _CreateScrollbar( int bHori );
    SW_DLLPRIVATE DECL_LINK( ScrollHdl, SwScrollbar * );
    SW_DLLPRIVATE DECL_LINK( EndScrollHdl, SwScrollbar * );
    SW_DLLPRIVATE DECL_LINK( BtnPage, Button * );
    SW_DLLPRIVATE int             ChgPage( int eMvMode, int bUpdateScrollbar = TRUE );

    SW_DLLPRIVATE virtual USHORT          Print( SfxProgress &rProgress,
                                   PrintDialog *pPrintDialog = 0 );
    SW_DLLPRIVATE virtual SfxPrinter*     GetPrinter( BOOL bCreate = FALSE );
    SW_DLLPRIVATE virtual USHORT          SetPrinter( SfxPrinter *pNewPrinter, USHORT nDiffFlags = SFX_PRINTER_ALL );
    SW_DLLPRIVATE virtual SfxTabPage*     CreatePrintOptionsPage( Window *pParent,
                                                const SfxItemSet &rOptions );
    SW_DLLPRIVATE virtual PrintDialog*    CreatePrintDialog( Window *pParent );

    SW_DLLPRIVATE void CalcAndSetBorderPixel( SvBorder &rToFill, FASTBOOL bInner );

    /** help method to execute SfxRequest FN_PAGE_UP and FN_PAGE_DOWN

        OD 04.03.2003 #107369#

        @param _bPgUp
        input parameter - boolean that indicates, if FN_PAGE_UP or FN_PAGE_DOWN
        has to be executed.

        @param _pReq
        optional input parameter - pointer to the <SfxRequest> instance, if existing.

        @author OD
    */
    SW_DLLPRIVATE void _ExecPgUpAndPgDown( const bool  _bPgUp,
                             SfxRequest* _pReq = 0 );

protected:
    virtual void    InnerResizePixel( const Point &rOfs, const Size &rSize );
    virtual void    OuterResizePixel( const Point &rOfs, const Size &rSize );
    virtual Size    GetOptimalSizePixel() const;

    void         SetZoom(SvxZoomType eSet, USHORT nFactor);

public:
    SFX_DECL_VIEWFACTORY(SwPagePreView);
    SFX_DECL_INTERFACE(SW_PAGEPREVIEW);
    TYPEINFO();

    inline Window*          GetFrameWindow() const { return &(GetViewFrame())->GetWindow(); }
    inline ViewShell*       GetViewShell() const { return aViewWin.GetViewShell(); }
    inline const Rectangle& GetVisArea() const { return aVisArea; }
    inline void             GrabFocusViewWin() { aViewWin.GrabFocus(); }
    inline void             RepaintCoreRect( const SwRect& rRect )
                                { aViewWin.RepaintCoreRect( rRect ); }

    void            DocSzChgd(const Size& rNewSize);
    const Size&     GetDocSz() const { return aDocSz; }

    virtual void    SetVisArea( const Rectangle&, BOOL bUpdateScrollbar = TRUE);

    inline void     AdjustEditWin();

    void            ScrollViewSzChg();
    void            ScrollDocSzChg();
    void            ShowHScrollbar(sal_Bool bShow);

    void            ShowVScrollbar(sal_Bool bShow);

    USHORT          GetPageCount() const        { return mnPageCount; }

    BOOL            HandleWheelCommands( const CommandEvent& );

    const String&   GetPrevSwViewData() const       { return sSwViewData; }
    void            SetNewCrsrPos( const String& rStr ) { sNewCrsrPos = rStr; }
    const String&   GetNewCrsrPos() const           { return sNewCrsrPos; }

    USHORT          GetNewPage() const {return nNewPage;}
    void            SetNewPage(USHORT nSet)  {nNewPage = nSet;}

        // Handler
    void            Execute(SfxRequest&);
    void            GetState(SfxItemSet&);
    void            StateUndo(SfxItemSet&);

    SwDocShell*     GetDocShell();

    //apply Accessiblity options
    void ApplyAccessiblityOptions(SvtAccessibilityOptions& rAccessibilityOptions);

    // OD 09.01.2003 #106334# - inline method to request values of new members
    // <mbResetFormDesignMode> and <mbFormDesignModeToReset>
    inline sal_Bool ResetFormDesignMode() const
    {
        return mbResetFormDesignMode;
    }

    inline sal_Bool FormDesignModeToReset() const
    {
        return mbFormDesignModeToReset;
    }

    /** adjust position of vertical scrollbar

        OD 19.02.2003 #107369
        Currently used, if the complete preview layout rows fit into to the given
        window, if a new page is selected and this page is visible.

        @author OD

        @param _nNewThumbPos
        input parameter - new position, which will be assigned to the vertical
        scrollbar.
    */
    void SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos );

    SwPagePreView( SfxViewFrame* pFrame, SfxViewShell* );
    ~SwPagePreView();
};

// ----------------- inline Methoden ----------------------

inline void SwPagePreView::AdjustEditWin()
{
    OuterResizePixel( Point(), GetFrameWindow()->GetOutputSizePixel() );
}

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.17.596); FILE MERGED 2005/09/05 13:45:33 rt 1.17.596.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pview.hxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:58:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    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
 *
 ************************************************************************/
#ifndef _SWPVIEW_HXX
#define _SWPVIEW_HXX

#ifndef _LINK_HXX //autogen
#include <tools/link.hxx>
#endif
#ifndef _WINDOW_HXX //autogen
#include <vcl/window.hxx>
#endif
#ifndef _SFXVIEWFRM_HXX //autogen
#include <sfx2/viewfrm.hxx>
#endif
#ifndef _VIEWFAC_HXX //autogen
#include <sfx2/viewfac.hxx>
#endif
#ifndef _SFXVIEWSH_HXX //autogen
#include <sfx2/viewsh.hxx>
#endif
#ifndef _SVX_ZOOMITEM_HXX
#include <svx/zoomitem.hxx>
#endif

#ifndef INCLUDED_SWDLLAPI_H
#include "swdllapi.h"
#endif
#ifndef _SHELLID_HXX
#include "shellid.hxx"
#endif

class SwViewOption;
class SwDocShell;
class SwScrollbar;
class ViewShell;
class SwPagePreView;
class ImageButton;
class Button;
class SwRect;
class DataChangedEvent;
class CommandEvent;
class SvtAccessibilityOptions;
// OD 12.12.2002 #103492#
class SwPagePreviewLayout;

// OD 24.03.2003 #108282# - delete member <mnVirtPage> and its accessor.
class SwPagePreViewWin : public Window
{
    ViewShell*          mpViewShell;
    USHORT              mnSttPage;
    BYTE                mnRow, mnCol;
    Size                maPxWinSize;
    Fraction            maScale;
    SwPagePreView&      mrView;
    // OD 02.12.2002 #103492#
    bool                mbCalcScaleForPreviewLayout;
    Rectangle           maPaintedPreviewDocRect;
    // OD 12.12.2002 #103492#
    SwPagePreviewLayout* mpPgPrevwLayout;

    void SetPagePreview( BYTE nRow, BYTE nCol );

public:
    SwPagePreViewWin( Window* pParent, SwPagePreView& rView );
    ~SwPagePreViewWin();

    //Ruft ViewShell::Paint
    virtual void Paint( const Rectangle& rRect );
    virtual void KeyInput( const KeyEvent & );
    virtual void Command( const CommandEvent& rCEvt );
    virtual void MouseButtonDown(const MouseEvent& rMEvt);
    virtual void DataChanged( const DataChangedEvent& );

    void SetViewShell( ViewShell* pShell );

    ViewShell* GetViewShell() const { return mpViewShell; }

    BYTE    GetRow() const      { return mnRow; }
    void    SetRow( BYTE n )    { if( n ) mnRow = n; }

    BYTE    GetCol() const      { return mnCol; }
    void    SetCol( BYTE n )    { if( n ) mnCol = n; }

    USHORT  GetSttPage() const      { return mnSttPage; }
    void    SetSttPage( USHORT n )  { mnSttPage = n; }

    /** get selected page number of document preview

        OD 13.12.2002 #103492#

        @author OD

        @return selected page number
    */
    sal_uInt16 SelectedPage() const;

    /** set selected page number in document preview

        OD 13.12.2002 #103492#

        @author OD

        @param _nSelectedPageNum
        input parameter - physical page number of page that will be the selected one.
    */
    void SetSelectedPage( sal_uInt16 _nSelectedPageNum );

    //JP 19.08.98: bei Einspaltigkeit gibt es keine 0. Seite!
    USHORT  GetDefSttPage() const   { return 1 == mnCol ? 1 : 0; }

    void CalcWish( BYTE nNewRow, BYTE nNewCol );

    const Size& GetWinSize() const  { return maPxWinSize; }
    void SetWinSize( const Size& rNewSize );

    // OD 18.12.2002 #103492# - add <MV_SELPAGE>, <MV_SCROLL>
    enum MoveMode{ MV_CALC, MV_PAGE_UP, MV_PAGE_DOWN, MV_DOC_STT, MV_DOC_END,
                   MV_SELPAGE, MV_SCROLL, MV_NEWWINSIZE };
    int MovePage( int eMoveMode );

    // erzeuge den String fuer die StatusLeiste
    void GetStatusStr( String& rStr, USHORT nPageCount ) const;

    void RepaintCoreRect( const SwRect& rRect );

    /** method to adjust preview to a new zoom factor

        OD 02.12.2002 #103492#
        paint of preview is prepared for a new zoom factor
        OD 24.09.2003 #i19975# - zoom type has also been considered.
        Thus, add new parameter <_eZoomType>

        @author OD
    */
    void AdjustPreviewToNewZoom( const sal_uInt16 _nZoomFactor,
                                 const SvxZoomType _eZoomType );

    const Rectangle& GetPaintedPreviewDocRect() const
    {
        return maPaintedPreviewDocRect;
    }

    void Scroll(long nXMove, long nYMove);

    /** method to enable/disable book preview

        OD 2004-03-05 #i18143#

        @author OD

        @param _bBookPreview
        input parameter - boolean indicating, if book preview mode has to
        switch on <TRUE> or of <FALSE>

        @return boolean indicating, if book preview mode has changed.
    */
    bool SetBookPreviewMode( const bool _bBookPreview );

    virtual ::com::sun::star::uno::Reference<
        ::com::sun::star::accessibility::XAccessible>
                    CreateAccessible();
};

/*--------------------------------------------------------------------
    Beschreibung:   Sicht auf ein Dokument
 --------------------------------------------------------------------*/

class SW_DLLPUBLIC SwPagePreView: public SfxViewShell
{
    // ViewWindow und Henkel zur Core
    // aktuelle Dispatcher-Shell
    SwPagePreViewWin        aViewWin;
    //viewdata of the previous SwView and the new crsrposition
    String                  sSwViewData,
    //and the new cursor position if the user double click in the PagePreView
                            sNewCrsrPos;
    // to support keyboard the number of the page to go to can be set too
    USHORT                  nNewPage;
    // Sichtbarer Bereich
    String                  sPageStr;
    Size                    aDocSz;
    Rectangle               aVisArea;

    // MDI Bedienelemente
    SwScrollbar             *pHScrollbar;
    SwScrollbar             *pVScrollbar;
    ImageButton             *pPageUpBtn,
                            *pPageDownBtn;
    // Dummy-Window zum Fllen der rechten unteren Ecke, wenn beide Scrollbars
    // aktiv sind
    Window                  *pScrollFill;

    USHORT                  mnPageCount;
    BOOL                    bNormalPrint;

    // OD 09.01.2003 #106334#
    // new members to reset design mode at draw view for form shell on switching
    // back from writer page preview to normal view.
    sal_Bool                mbResetFormDesignMode:1;
    sal_Bool                mbFormDesignModeToReset:1;

    SW_DLLPRIVATE void            Init(const SwViewOption* = 0);
    SW_DLLPRIVATE Point           AlignToPixel(const Point& rPt) const;

    SW_DLLPRIVATE int             _CreateScrollbar( int bHori );
    SW_DLLPRIVATE DECL_LINK( ScrollHdl, SwScrollbar * );
    SW_DLLPRIVATE DECL_LINK( EndScrollHdl, SwScrollbar * );
    SW_DLLPRIVATE DECL_LINK( BtnPage, Button * );
    SW_DLLPRIVATE int             ChgPage( int eMvMode, int bUpdateScrollbar = TRUE );

    SW_DLLPRIVATE virtual USHORT          Print( SfxProgress &rProgress,
                                   PrintDialog *pPrintDialog = 0 );
    SW_DLLPRIVATE virtual SfxPrinter*     GetPrinter( BOOL bCreate = FALSE );
    SW_DLLPRIVATE virtual USHORT          SetPrinter( SfxPrinter *pNewPrinter, USHORT nDiffFlags = SFX_PRINTER_ALL );
    SW_DLLPRIVATE virtual SfxTabPage*     CreatePrintOptionsPage( Window *pParent,
                                                const SfxItemSet &rOptions );
    SW_DLLPRIVATE virtual PrintDialog*    CreatePrintDialog( Window *pParent );

    SW_DLLPRIVATE void CalcAndSetBorderPixel( SvBorder &rToFill, FASTBOOL bInner );

    /** help method to execute SfxRequest FN_PAGE_UP and FN_PAGE_DOWN

        OD 04.03.2003 #107369#

        @param _bPgUp
        input parameter - boolean that indicates, if FN_PAGE_UP or FN_PAGE_DOWN
        has to be executed.

        @param _pReq
        optional input parameter - pointer to the <SfxRequest> instance, if existing.

        @author OD
    */
    SW_DLLPRIVATE void _ExecPgUpAndPgDown( const bool  _bPgUp,
                             SfxRequest* _pReq = 0 );

protected:
    virtual void    InnerResizePixel( const Point &rOfs, const Size &rSize );
    virtual void    OuterResizePixel( const Point &rOfs, const Size &rSize );
    virtual Size    GetOptimalSizePixel() const;

    void         SetZoom(SvxZoomType eSet, USHORT nFactor);

public:
    SFX_DECL_VIEWFACTORY(SwPagePreView);
    SFX_DECL_INTERFACE(SW_PAGEPREVIEW);
    TYPEINFO();

    inline Window*          GetFrameWindow() const { return &(GetViewFrame())->GetWindow(); }
    inline ViewShell*       GetViewShell() const { return aViewWin.GetViewShell(); }
    inline const Rectangle& GetVisArea() const { return aVisArea; }
    inline void             GrabFocusViewWin() { aViewWin.GrabFocus(); }
    inline void             RepaintCoreRect( const SwRect& rRect )
                                { aViewWin.RepaintCoreRect( rRect ); }

    void            DocSzChgd(const Size& rNewSize);
    const Size&     GetDocSz() const { return aDocSz; }

    virtual void    SetVisArea( const Rectangle&, BOOL bUpdateScrollbar = TRUE);

    inline void     AdjustEditWin();

    void            ScrollViewSzChg();
    void            ScrollDocSzChg();
    void            ShowHScrollbar(sal_Bool bShow);

    void            ShowVScrollbar(sal_Bool bShow);

    USHORT          GetPageCount() const        { return mnPageCount; }

    BOOL            HandleWheelCommands( const CommandEvent& );

    const String&   GetPrevSwViewData() const       { return sSwViewData; }
    void            SetNewCrsrPos( const String& rStr ) { sNewCrsrPos = rStr; }
    const String&   GetNewCrsrPos() const           { return sNewCrsrPos; }

    USHORT          GetNewPage() const {return nNewPage;}
    void            SetNewPage(USHORT nSet)  {nNewPage = nSet;}

        // Handler
    void            Execute(SfxRequest&);
    void            GetState(SfxItemSet&);
    void            StateUndo(SfxItemSet&);

    SwDocShell*     GetDocShell();

    //apply Accessiblity options
    void ApplyAccessiblityOptions(SvtAccessibilityOptions& rAccessibilityOptions);

    // OD 09.01.2003 #106334# - inline method to request values of new members
    // <mbResetFormDesignMode> and <mbFormDesignModeToReset>
    inline sal_Bool ResetFormDesignMode() const
    {
        return mbResetFormDesignMode;
    }

    inline sal_Bool FormDesignModeToReset() const
    {
        return mbFormDesignModeToReset;
    }

    /** adjust position of vertical scrollbar

        OD 19.02.2003 #107369
        Currently used, if the complete preview layout rows fit into to the given
        window, if a new page is selected and this page is visible.

        @author OD

        @param _nNewThumbPos
        input parameter - new position, which will be assigned to the vertical
        scrollbar.
    */
    void SetVScrollbarThumbPos( const sal_uInt16 _nNewThumbPos );

    SwPagePreView( SfxViewFrame* pFrame, SfxViewShell* );
    ~SwPagePreView();
};

// ----------------- inline Methoden ----------------------

inline void SwPagePreView::AdjustEditWin()
{
    OuterResizePixel( Point(), GetFrameWindow()->GetOutputSizePixel() );
}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <cassert>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>      // incluye "time(....)"
#include <unistd.h>    // incluye "usleep(...)"
#include <stdlib.h>    // incluye "rand(...)" y "srand"

using namespace std;

////////////////////////////////////////////////////////////////////////////////
// FUNCIÓN FUMAR
// Simula la acción de fumar como un retardo aleatorio de la hebra

void fumar()
{
   // calcular un numero aleatorio de milisegundos (entre 1/10 y 2 segundos)
   const unsigned miliseg = 100U + (rand() % 1900U) ;

   // retraso bloqueado durante 'miliseg' milisegundos
   usleep (1000U*miliseg);
}

/******************************************************************************/
// Declaración de los semáforos

sem_t
    puede_consumir1,
    puede_consumir2,
    puede_consumir3,
    puede_producir,
    control;

/******************************************************************************/
// Contabilización de veces que el estanquero produce ingredientes y de las
// veces que se fuma

int veces_estanquero;
int veces_fumar;

////////////////////////////////////////////////////////////////////////////////
// FUNCIONES DE LOS FUMADORES
// Encargados de consumir los ingredientes despechados
// Deciden aleatoriamente si fumar o no

void * fumador1 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir1);
        cout << "El fumador 1 ha recibido cerillas\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 1 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

void * fumador2 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir2);
        cout << "El fumador 2 ha recibido tabaco\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 2 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

void * fumador3 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir3);
        cout << "El fumador 3 ha recibido papel\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 3 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// FUNCION DEL ESTANQUERO
// Encargada de despechar ingredientes

void * estanquero (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_producir);

        cout << "Despechando ";

        int producto = rand() % 3;

        switch (producto)
        {
            case 0:
                cout << "cerillas...\n";
                sem_post(&puede_consumir1);
                veces_estanquero++;
            break;

            case 1:
                cout << "tabaco...\n";
                sem_post(&puede_consumir2);
                veces_estanquero++;
            break;

            case 2:
                cout << "papel...\n";
                sem_post(&puede_consumir3);
                veces_estanquero++;
            break;

            default:
                cerr << "...ERROR\n";
                exit(1);
            break;
        }
    }

    return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// FUNCION CONTADORA
// Muestra cada 2 segundos los contadores de cigarros fumados e ingredientes
// despechados

void * contador (void *)
{
    while (2 > 1)
    {
        sleep (2);
        cout << endl << "CONTADORES:" << endl;
        cout << "Ingredientes despechados: " << veces_estanquero << endl;
        cout << "Cigarros fumados: " << veces_fumar << endl << endl;
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int main()
{
    srand (time (NULL));

    veces_estanquero = 0;
    veces_fumar = 0;

    // Creación de hebras

    pthread_t
        p_fumador1,
        p_fumador2,
        p_fumador3,
        p_estanquero,
        p_contadores;

    // Inicialización de semáforos

    sem_init (&puede_consumir1, 0, 0);
    sem_init (&puede_consumir2, 0, 0);
    sem_init (&puede_consumir3, 0, 0);
    sem_init (&puede_producir, 0, 1);
    sem_init (&control, 0, 1);

    // Inicialización de las hebras

    pthread_create (&p_fumador1, NULL, fumador1, NULL);
    pthread_create (&p_fumador2, NULL, fumador2, NULL);
    pthread_create (&p_fumador3, NULL, fumador3, NULL);
    pthread_create (&p_estanquero, NULL, estanquero, NULL);
    pthread_create (&p_contadores, NULL, contador, NULL);

    // Finalización de las hebras

    pthread_join (p_fumador1, NULL);
    pthread_join (p_fumador2, NULL);
    pthread_join (p_fumador3, NULL);
    pthread_join (p_estanquero, NULL);
    pthread_join (p_contadores, NULL);

    // Finalización de los semáforos

    sem_destroy (&puede_consumir1);
    sem_destroy (&puede_consumir2);
    sem_destroy (&puede_consumir3);
    sem_destroy (&puede_producir);
    sem_destroy (&control);

    return (0);
}
<commit_msg>Updated<commit_after>/*****************************************************************************/
// Prácticas de Sistemas Concurrentes y Distribuidos
// Por David Vargas Carrillo, 2015
/*****************************************************************************/

#include <iostream>
#include <cassert>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>      // incluye "time(....)"
#include <unistd.h>    // incluye "usleep(...)"
#include <stdlib.h>    // incluye "rand(...)" y "srand"

using namespace std;

////////////////////////////////////////////////////////////////////////////////
// FUNCIÓN FUMAR
// Simula la acción de fumar como un retardo aleatorio de la hebra

void fumar()
{
   // calcular un numero aleatorio de milisegundos (entre 1/10 y 2 segundos)
   const unsigned miliseg = 100U + (rand() % 1900U) ;

   // retraso bloqueado durante 'miliseg' milisegundos
   usleep (1000U*miliseg);
}

/******************************************************************************/
// Declaración de los semáforos

sem_t
    puede_consumir1,
    puede_consumir2,
    puede_consumir3,
    puede_producir,
    control;

/******************************************************************************/
// Contabilización de veces que el estanquero produce ingredientes y de las
// veces que se fuma

int veces_estanquero;
int veces_fumar;

////////////////////////////////////////////////////////////////////////////////
// FUNCIONES DE LOS FUMADORES
// Encargados de consumir los ingredientes despechados
// Deciden aleatoriamente si fumar o no

void * fumador1 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir1);
        cout << "El fumador 1 ha recibido cerillas\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 1 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

void * fumador2 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir2);
        cout << "El fumador 2 ha recibido tabaco\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 2 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

void * fumador3 (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_consumir3);
        cout << "El fumador 3 ha recibido papel\n";
        sem_post(&puede_producir);

        int random = rand() % 2;

        if (random == 1) {
            sem_wait (&control);

            fumar();
            cout << "El fumador 3 ha fumado un cigarro\n";
            veces_fumar++;

            sem_post (&control);
        }
    }

    return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// FUNCION DEL ESTANQUERO
// Encargada de despechar ingredientes

void * estanquero (void *)
{
    while (2 > 1)
    {
        sem_wait(&puede_producir);

        cout << "Despechando ";

        int producto = rand() % 3;

        switch (producto)
        {
            case 0:
                cout << "cerillas...\n";
                sem_post(&puede_consumir1);
                veces_estanquero++;
            break;

            case 1:
                cout << "tabaco...\n";
                sem_post(&puede_consumir2);
                veces_estanquero++;
            break;

            case 2:
                cout << "papel...\n";
                sem_post(&puede_consumir3);
                veces_estanquero++;
            break;

            default:
                cerr << "...ERROR\n";
                exit(1);
            break;
        }
    }

    return NULL;
}

////////////////////////////////////////////////////////////////////////////////
// FUNCION CONTADORA
// Muestra cada 2 segundos los contadores de cigarros fumados e ingredientes
// despechados

void * contador (void *)
{
    while (2 > 1)
    {
        sleep (2);
        cout << endl << "CONTADORES:" << endl;
        cout << "Ingredientes despechados: " << veces_estanquero << endl;
        cout << "Cigarros fumados: " << veces_fumar << endl << endl;
    }
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

int main()
{
    srand (time (NULL));

    veces_estanquero = 0;
    veces_fumar = 0;

    // Creación de hebras

    pthread_t
        p_fumador1,
        p_fumador2,
        p_fumador3,
        p_estanquero,
        p_contadores;

    // Inicialización de semáforos

    sem_init (&puede_consumir1, 0, 0);
    sem_init (&puede_consumir2, 0, 0);
    sem_init (&puede_consumir3, 0, 0);
    sem_init (&puede_producir, 0, 1);
    sem_init (&control, 0, 1);

    // Inicialización de las hebras

    pthread_create (&p_fumador1, NULL, fumador1, NULL);
    pthread_create (&p_fumador2, NULL, fumador2, NULL);
    pthread_create (&p_fumador3, NULL, fumador3, NULL);
    pthread_create (&p_estanquero, NULL, estanquero, NULL);
    pthread_create (&p_contadores, NULL, contador, NULL);

    // Finalización de las hebras

    pthread_join (p_fumador1, NULL);
    pthread_join (p_fumador2, NULL);
    pthread_join (p_fumador3, NULL);
    pthread_join (p_estanquero, NULL);
    pthread_join (p_contadores, NULL);

    // Finalización de los semáforos

    sem_destroy (&puede_consumir1);
    sem_destroy (&puede_consumir2);
    sem_destroy (&puede_consumir3);
    sem_destroy (&puede_producir);
    sem_destroy (&control);

    return (0);
}
<|endoftext|>


<commit_before>
#include "uiTags.h"

#include <iostream>

uiTags::uiTags()
{

}

uiTags::~uiTags() {}

std::vector<Glib::ustring> uiTags::tags()
{
	return m_tags;
}

void uiTags::tags(std::vector<Glib::ustring> tags)
{
	m_tags = tags;

	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
		delete m_tag_widgets[i];

	m_tag_widgets.clear();

	for(unsigned int i = 0; i < m_tags.size(); i++)
		m_tag_widgets.push_back(new Tag(m_tags[i]));

	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
	{
		this->put(*m_tag_widgets[i],50,0);
		m_tag_widgets[i]->show();
	}
	redraw();
}

void uiTags::redraw()
{
	int x=0;
	int y=0;
	int w,h;
	int width = this->get_width();
	m_AddNew.set_label("+ Add Tag");
	this->put(m_AddNew, 0,0);
	m_AddNew.show();
	x += m_AddNew.get_width();
	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
	{
		//TODO: Figure out how to get actual dimensions of tag.
		//      get_width() and get_allocation() returning 1.
		Gdk::Rectangle rec = m_tag_widgets[i]->get_allocation();
		w = rec.get_width();
		h = rec.get_height();
		if (x > 0 && x+w > width) { x = 0; y += h; }
		this->move(*m_tag_widgets[i],x,y);
		x += w;
	}
	show_all_children();
}

uiTags::Tag::Tag(Glib::ustring tag)
{
	m_Value.set_text(tag);
	m_Close.set_label("X");
	m_Close.set_relief(Gtk::RELIEF_NONE);
	m_hbox.pack_start(m_Close, false, false);
	m_hbox.pack_start(m_Value, false, false);
	this->add(m_hbox);
	this->set_shadow_type(Gtk::SHADOW_NONE);
	this->set_border_width(2);
	show_all_children();
}
<commit_msg>Getting tag size works<commit_after>
#include "uiTags.h"

#include <iostream>

uiTags::uiTags()
{

}

uiTags::~uiTags() {}

std::vector<Glib::ustring> uiTags::tags()
{
	return m_tags;
}

void uiTags::tags(std::vector<Glib::ustring> tags)
{
	m_tags = tags;

	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
		delete m_tag_widgets[i];

	m_tag_widgets.clear();

	for(unsigned int i = 0; i < m_tags.size(); i++)
		m_tag_widgets.push_back(new Tag(m_tags[i]));

	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
	{
		this->put(*m_tag_widgets[i],50,0);
		m_tag_widgets[i]->show();
	}
	redraw();
}

void uiTags::redraw()
{
	int x=0;
	int y=0;
	int w,h;
	int width = this->get_width();
	m_AddNew.set_label("+ Add Tag");
	Gtk::Requisition rec = m_AddNew.size_request();
	x += rec.width;
	this->put(m_AddNew, 0,0);
	for(unsigned int i = 0; i < m_tag_widgets.size(); i++)
	{
		//TODO: Figure out how to get actual dimensions of tag.
		//      get_width() and get_allocation() returning 1.
		rec = m_tag_widgets[i]->size_request();
		w = rec.width;
		h = rec.height;
		if (x > 0 && x+w > width) { x = 0; y += h; }
		this->move(*m_tag_widgets[i],x,y);
		x += w;
	}
	show_all_children();
}

uiTags::Tag::Tag(Glib::ustring tag)
{
	m_Value.set_text(tag);
	m_Close.set_label("X");
	m_Close.set_relief(Gtk::RELIEF_NONE);
	m_hbox.pack_start(m_Close, false, false);
	m_hbox.pack_start(m_Value, false, false);
	this->add(m_hbox);
	this->set_shadow_type(Gtk::SHADOW_NONE);
	this->set_border_width(2);
	show_all_children();
}
<|endoftext|>