<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <tools/errcode.hxx>
#include <svl/svdde.hxx>
#include "ddectrl.hxx"
#include <basic/sberrors.hxx>

#define DDE_FREECHANNEL (reinterpret_cast<DdeConnection*>(sal_IntPtr(-1)))

#define DDE_FIRSTERR    0x4000
#define DDE_LASTERR     0x4011

static const SbError nDdeErrMap[] =
{
    /* DMLERR_ADVACKTIMEOUT       */  0x4000, SbERR_DDE_TIMEOUT,
    /* DMLERR_BUSY                */  0x4001, SbERR_DDE_BUSY,
    /* DMLERR_DATAACKTIMEOUT      */  0x4002, SbERR_DDE_TIMEOUT,
    /* DMLERR_DLL_NOT_INITIALIZED */  0x4003, SbERR_DDE_ERROR,
    /* DMLERR_DLL_USAGE           */  0x4004, SbERR_DDE_ERROR,
    /* DMLERR_EXECACKTIMEOUT      */  0x4005, SbERR_DDE_TIMEOUT,
    /* DMLERR_INVALIDPARAMETER    */  0x4006, SbERR_DDE_ERROR,
    /* DMLERR_LOW_MEMORY          */  0x4007, SbERR_DDE_ERROR,
    /* DMLERR_MEMORY_ERROR        */  0x4008, SbERR_DDE_ERROR,
    /* DMLERR_NOTPROCESSED        */  0x4009, SbERR_DDE_NOTPROCESSED,
    /* DMLERR_NO_CONV_ESTABLISHED */  0x400a, SbERR_DDE_NO_CHANNEL,
    /* DMLERR_POKEACKTIMEOUT      */  0x400b, SbERR_DDE_TIMEOUT,
    /* DMLERR_POSTMSG_FAILED      */  0x400c, SbERR_DDE_QUEUE_OVERFLOW,
    /* DMLERR_REENTRANCY          */  0x400d, SbERR_DDE_ERROR,
    /* DMLERR_SERVER_DIED         */  0x400e, SbERR_DDE_PARTNER_QUIT,
    /* DMLERR_SYS_ERROR           */  0x400f, SbERR_DDE_ERROR,
    /* DMLERR_UNADVACKTIMEOUT     */  0x4010, SbERR_DDE_TIMEOUT,
    /* DMLERR_UNFOUND_QUEUE_ID    */  0x4011, SbERR_DDE_NO_CHANNEL
};

SbError SbiDdeControl::GetLastErr( DdeConnection* pConv )
{
    if( !pConv )
    {
        return 0;
    }
    long nErr = pConv->GetError();
    if( !nErr )
    {
        return 0;
    }
    if( nErr < DDE_FIRSTERR || nErr > DDE_LASTERR )
    {
        return SbERR_DDE_ERROR;
    }
    return nDdeErrMap[ 2 * (nErr - DDE_FIRSTERR) + 1 ];
}

IMPL_LINK_INLINE( SbiDdeControl,Data , DdeData*, pData,
{
    aData = OUString::createFromAscii( (const char*)(const void*)*pData );
    return 1;
}
)

SbiDdeControl::SbiDdeControl()
{
}

SbiDdeControl::~SbiDdeControl()
{
    TerminateAll();
}

size_t SbiDdeControl::GetFreeChannel()
{
    size_t nChannel = 0;
    size_t nListSize = aConvList.size();

    for (; nChannel < nListSize; ++nChannel)
    {
        if (aConvList[nChannel] == DDE_FREECHANNEL)
        {
            return nChannel+1;
        }
    }

    aConvList.push_back(DDE_FREECHANNEL);
    return nChannel+1;
}

SbError SbiDdeControl::Initiate( const OUString& rService, const OUString& rTopic,
                                 size_t& rnHandle )
{
    SbError nErr;
    DdeConnection* pConv = new DdeConnection( rService, rTopic );
    nErr = GetLastErr( pConv );
    if( nErr )
    {
        delete pConv;
        rnHandle = 0;
    }
    else
    {
        size_t nChannel = GetFreeChannel();
        aConvList[nChannel-1] = pConv;
        rnHandle = nChannel;
    }
    return 0;
}

SbError SbiDdeControl::Terminate( size_t nChannel )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    delete pConv;

    return 0L;
}

SbError SbiDdeControl::TerminateAll()
{
    for (size_t nChannel = 0; nChannel < aConvList.size(); ++nChannel)
    {
        DdeConnection *conv = aConvList[nChannel];

        if (conv != DDE_FREECHANNEL)
        {
            delete conv;
        }
    }

    aConvList.clear();

    return 0;
}

SbError SbiDdeControl::Request( size_t nChannel, const OUString& rItem, OUString& rResult )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeRequest aRequest( *pConv, rItem, 30000 );
    aRequest.SetDataHdl( LINK( this, SbiDdeControl, Data ) );
    aRequest.Execute();
    rResult = aData;
    return GetLastErr( pConv );
}

SbError SbiDdeControl::Execute( size_t nChannel, const OUString& rCommand )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeExecute aRequest( *pConv, rCommand, 30000 );
    aRequest.Execute();
    return GetLastErr( pConv );
}

SbError SbiDdeControl::Poke( size_t nChannel, const OUString& rItem, const OUString& rData )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdePoke aRequest( *pConv, rItem, DdeData(rData), 30000 );
    aRequest.Execute();
    return GetLastErr( pConv );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>fix marking of free slots in array<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <tools/errcode.hxx>
#include <svl/svdde.hxx>
#include "ddectrl.hxx"
#include <basic/sberrors.hxx>

#define DDE_FREECHANNEL (reinterpret_cast<DdeConnection*>(sal_IntPtr(-1)))

#define DDE_FIRSTERR    0x4000
#define DDE_LASTERR     0x4011

static const SbError nDdeErrMap[] =
{
    /* DMLERR_ADVACKTIMEOUT       */  0x4000, SbERR_DDE_TIMEOUT,
    /* DMLERR_BUSY                */  0x4001, SbERR_DDE_BUSY,
    /* DMLERR_DATAACKTIMEOUT      */  0x4002, SbERR_DDE_TIMEOUT,
    /* DMLERR_DLL_NOT_INITIALIZED */  0x4003, SbERR_DDE_ERROR,
    /* DMLERR_DLL_USAGE           */  0x4004, SbERR_DDE_ERROR,
    /* DMLERR_EXECACKTIMEOUT      */  0x4005, SbERR_DDE_TIMEOUT,
    /* DMLERR_INVALIDPARAMETER    */  0x4006, SbERR_DDE_ERROR,
    /* DMLERR_LOW_MEMORY          */  0x4007, SbERR_DDE_ERROR,
    /* DMLERR_MEMORY_ERROR        */  0x4008, SbERR_DDE_ERROR,
    /* DMLERR_NOTPROCESSED        */  0x4009, SbERR_DDE_NOTPROCESSED,
    /* DMLERR_NO_CONV_ESTABLISHED */  0x400a, SbERR_DDE_NO_CHANNEL,
    /* DMLERR_POKEACKTIMEOUT      */  0x400b, SbERR_DDE_TIMEOUT,
    /* DMLERR_POSTMSG_FAILED      */  0x400c, SbERR_DDE_QUEUE_OVERFLOW,
    /* DMLERR_REENTRANCY          */  0x400d, SbERR_DDE_ERROR,
    /* DMLERR_SERVER_DIED         */  0x400e, SbERR_DDE_PARTNER_QUIT,
    /* DMLERR_SYS_ERROR           */  0x400f, SbERR_DDE_ERROR,
    /* DMLERR_UNADVACKTIMEOUT     */  0x4010, SbERR_DDE_TIMEOUT,
    /* DMLERR_UNFOUND_QUEUE_ID    */  0x4011, SbERR_DDE_NO_CHANNEL
};

SbError SbiDdeControl::GetLastErr( DdeConnection* pConv )
{
    if( !pConv )
    {
        return 0;
    }
    long nErr = pConv->GetError();
    if( !nErr )
    {
        return 0;
    }
    if( nErr < DDE_FIRSTERR || nErr > DDE_LASTERR )
    {
        return SbERR_DDE_ERROR;
    }
    return nDdeErrMap[ 2 * (nErr - DDE_FIRSTERR) + 1 ];
}

IMPL_LINK_INLINE( SbiDdeControl,Data , DdeData*, pData,
{
    aData = OUString::createFromAscii( (const char*)(const void*)*pData );
    return 1;
}
)

SbiDdeControl::SbiDdeControl()
{
}

SbiDdeControl::~SbiDdeControl()
{
    TerminateAll();
}

size_t SbiDdeControl::GetFreeChannel()
{
    size_t nChannel = 0;
    size_t nListSize = aConvList.size();

    for (; nChannel < nListSize; ++nChannel)
    {
        if (aConvList[nChannel] == DDE_FREECHANNEL)
        {
            return nChannel+1;
        }
    }

    aConvList.push_back(DDE_FREECHANNEL);
    return nChannel+1;
}

SbError SbiDdeControl::Initiate( const OUString& rService, const OUString& rTopic,
                                 size_t& rnHandle )
{
    SbError nErr;
    DdeConnection* pConv = new DdeConnection( rService, rTopic );
    nErr = GetLastErr( pConv );
    if( nErr )
    {
        delete pConv;
        rnHandle = 0;
    }
    else
    {
        size_t nChannel = GetFreeChannel();
        aConvList[nChannel-1] = pConv;
        rnHandle = nChannel;
    }
    return 0;
}

SbError SbiDdeControl::Terminate( size_t nChannel )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    delete pConv;
    aConvList[nChannel-1] = DDE_FREECHANNEL;

    return 0L;
}

SbError SbiDdeControl::TerminateAll()
{
    for (size_t nChannel = 0; nChannel < aConvList.size(); ++nChannel)
    {
        DdeConnection *conv = aConvList[nChannel];

        if (conv != DDE_FREECHANNEL)
        {
            delete conv;
        }
    }

    aConvList.clear();

    return 0;
}

SbError SbiDdeControl::Request( size_t nChannel, const OUString& rItem, OUString& rResult )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeRequest aRequest( *pConv, rItem, 30000 );
    aRequest.SetDataHdl( LINK( this, SbiDdeControl, Data ) );
    aRequest.Execute();
    rResult = aData;
    return GetLastErr( pConv );
}

SbError SbiDdeControl::Execute( size_t nChannel, const OUString& rCommand )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }

    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeExecute aRequest( *pConv, rCommand, 30000 );
    aRequest.Execute();
    return GetLastErr( pConv );
}

SbError SbiDdeControl::Poke( size_t nChannel, const OUString& rItem, const OUString& rData )
{
    if (!nChannel || nChannel > aConvList.size())
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdeConnection* pConv = aConvList[nChannel-1];

    if( pConv == DDE_FREECHANNEL )
    {
        return SbERR_DDE_NO_CHANNEL;
    }
    DdePoke aRequest( *pConv, rItem, DdeData(rData), 30000 );
    aRequest.Execute();
    return GetLastErr( pConv );
}

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


<commit_before>#include "acmacs-base/pybind11.hh"
#include "acmacs-chart/ace.hh"
#include "variant-id.hh"
#include "vaccines.hh"
#include "hidb.hh"
#include "hidb-export.hh"

using namespace hidb;

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

PYBIND11_PLUGIN(hidb_backend)
{
    py::module m("hidb_backend", "HiDB access plugin");

      // ----------------------------------------------------------------------
      // acmacs_chart_backend
      // ----------------------------------------------------------------------

    auto acmacs_chart_backend = py::module::import("acmacs_chart_backend");
      //class hidb_Antigen : public Antigen {};
    using hidb_Antigen = Antigen;
    py::class_<hidb_Antigen>(m, "Antigen", acmacs_chart_backend.attr("Antigen"));
    // m.attr("Antigen") = acmacs_chart_backend.attr("Antigen");
    // py::class_<Antigen>(m, "Antigen", acmacs_chart_backend.attr("Antigen"));
    // py::class_<Serum>(m, "Serum", acmacs_chart_backend.attr("Serum"));

      // ----------------------------------------------------------------------
      // Vaccines
      // ----------------------------------------------------------------------

    py::class_<Vaccines::HomologousSerum>(m, "Vaccines_HomologousSerum")
            .def_readonly("serum", &Vaccines::HomologousSerum::serum)
            .def_readonly("serum_index", &Vaccines::HomologousSerum::serum_index)
            .def_readonly("most_recent_table", &Vaccines::HomologousSerum::most_recent_table_date)
            .def("number_of_tables", &Vaccines::HomologousSerum::number_of_tables)
            ;

    py::class_<Vaccines::Entry>(m, "Vaccines_Entry")
            .def_readonly("antigen", &Vaccines::Entry::antigen)
            .def_readonly("antigen_index", &Vaccines::Entry::antigen_index)
            .def_readonly("homologous_sera", &Vaccines::Entry::homologous_sera, py::return_value_policy::reference)
            ;

    py::class_<Vaccines>(m, "Vaccines")
            .def("report", &Vaccines::report, py::arg("indent") = 0)
            .def("egg", &Vaccines::egg, py::arg("no") = 0, py::return_value_policy::reference)
            .def("cell", &Vaccines::cell, py::arg("no") = 0, py::return_value_policy::reference)
            .def("reassortant", &Vaccines::reassortant, py::arg("no") = 0, py::return_value_policy::reference)
            .def("number_of_eggs", &Vaccines::number_of_eggs)
            .def("number_of_cells", &Vaccines::number_of_cells)
            .def("number_of_reassortants", &Vaccines::number_of_reassortants)
            ;

    m.def("find_vaccines_in_chart", &find_vaccines_in_chart, py::arg("name"), py::arg("chart"), py::arg("hidb"));

      // ----------------------------------------------------------------------
      // HiDb
      // ----------------------------------------------------------------------

    py::class_<PerTable>(m, "PerTable")
            .def("table_id", static_cast<const std::string (PerTable::*)() const>(&PerTable::table_id))
            ;

    py::class_<AntigenData>(m, "AntigenData")
            .def("data", py::overload_cast<>(&AntigenData::data))
            .def("number_of_tables", &AntigenData::number_of_tables)
            .def("most_recent_table", &AntigenData::most_recent_table)
            .def("oldest_table", &AntigenData::oldest_table)
            .def("date", &AntigenData::date)
            .def("tables", static_cast<const std::vector<PerTable>& (AntigenData::*)() const>(&AntigenData::per_table))
            ;

    py::class_<SerumData>(m, "SerumData")
            .def("data", py::overload_cast<>(&SerumData::data))
            .def("number_of_tables", &SerumData::number_of_tables)
            .def("most_recent_table", &SerumData::most_recent_table)
            .def("oldest_table", &SerumData::oldest_table)
            .def("tables", static_cast<const std::vector<PerTable>& (SerumData::*)() const>(&SerumData::per_table))
            .def("homologous", &SerumData::homologous)
            ;

    py::class_<AntigenRefs>(m, "AntigenRefs")
            .def("__len__", [](const AntigenRefs& ar) { return ar.size(); })
            .def("__getitem__", [](const AntigenRefs& ar, size_t i) { if (i >= ar.size()) throw py::index_error(); return ar[i]; }, py::return_value_policy::reference)
            .def("country", &AntigenRefs::country, py::arg("country"))
            .def("date_range", &AntigenRefs::date_range, py::arg("begin") = "", py::arg("end") = "")
            ;

      // --------------------------------------------------
      // lambdas below are to avoid python GC affecting data

    auto pointer_to_copy = [](const std::vector<const AntigenData*>& source) -> std::vector<AntigenData> {
        std::vector<AntigenData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_antigens_by_name = [&pointer_to_copy](const HiDb& aHiDb, std::string name) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens_by_name(name));
    };

    auto find_antigens = [&pointer_to_copy](const HiDb& aHiDb, std::string name) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens(name));
    };

    auto find_antigens_fuzzy = [&pointer_to_copy](const HiDb& aHiDb, std::string name) {
        return pointer_to_copy(aHiDb.find_antigens_fuzzy(name));
    };

    auto find_antigens_extra_fuzzy = [&pointer_to_copy](const HiDb& aHiDb, std::string name) {
        return pointer_to_copy(aHiDb.find_antigens_extra_fuzzy(name));
    };

    auto find_antigens_with_score = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_antigens_with_score(name);
        std::vector<std::pair<AntigenData, size_t>> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return std::make_pair(*e.first, e.second); });
        return result;
    };

    auto find_antigens_by_cdcid = [&pointer_to_copy](const HiDb& aHiDb, std::string cdcid) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens_by_cdcid(cdcid));
    };

    auto find_sera = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_sera(name);
        std::vector<SerumData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_homologous_sera = [](const HiDb& aHiDb, const AntigenData& aAntigen) {
        const auto source = aHiDb.find_homologous_sera(aAntigen);
        std::vector<SerumData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_sera_with_score = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_sera_with_score(name);
        std::vector<std::pair<SerumData, size_t>> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return std::make_pair(*e.first, e.second); });
        return result;
    };

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

    py::class_<HiDbStat>(m, "HiDbStat")
            .def(py::init<>())
            .def("compute_totals", &HiDbStat::compute_totals)
            .def("as_dict", [](HiDbStat& aStat) -> HiDbStatContainer& { return aStat; }, py::return_value_policy::reference)
            ;

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

    py::class_<HiDb>(m, "HiDb")
            .def(py::init<>())
            .def("add", &HiDb::add, py::arg("chart"))
            .def("export_to", &HiDb::exportTo, py::arg("filename"), py::arg("pretty") = false)
            .def("import_from", &HiDb::importFrom, py::arg("filename"))
            .def("import_locdb", &HiDb::importLocDb, py::arg("filename"))

            .def("all_antigens", &HiDb::all_antigens, py::return_value_policy::reference)
            .def("all_countries", &HiDb::all_countries)
            .def("unrecognized_locations", &HiDb::unrecognized_locations, py::doc("returns unrecognized locations found in all antigen/serum names"))

            .def("stat_antigens", &HiDb::stat_antigens, py::arg("stat"), py::arg("start_date") = "", py::arg("end_date") = "")
            .def("stat_sera", &HiDb::stat_sera, py::arg("stat"), py::arg("stat_unique"), py::arg("start_date") = "", py::arg("end_date") = "")

            .def("list_antigen_names", &HiDb::list_antigen_names, py::arg("lab") = "", py::arg("full_name") = false)
            .def("list_antigens", &HiDb::list_antigens, py::arg("lab"))
            .def("find_antigens", find_antigens, py::arg("name"))
            .def("find_antigens_fuzzy", find_antigens_fuzzy, py::arg("name"))
            .def("find_antigens_extra_fuzzy", find_antigens_extra_fuzzy, py::arg("name"))
            .def("find_antigens_with_score", find_antigens_with_score, py::arg("name"))
            .def("find_antigens_by_name", find_antigens_by_name, py::arg("name"))
            .def("find_antigens_by_cdcid", find_antigens_by_cdcid, py::arg("cdcid"))
            .def("list_serum_names", &HiDb::list_serum_names, py::arg("lab") = "", py::arg("full_name") = false)
            .def("list_sera", &HiDb::list_sera, py::arg("lab"))
            .def("find_sera", find_sera, py::arg("name"))
            .def("find_homologous_sera", find_homologous_sera, py::arg("antigen"))
            .def("find_sera_with_score", find_sera_with_score, py::arg("name"))
            .def("find_homologous_antigens_for_sera_of_chart", &HiDb::find_homologous_antigens_for_sera_of_chart, py::arg("chart"))
            ;

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

    py::class_<hidb::HiDbSet>(m, "HiDbSet")
            .def(py::init<std::string>(), py::arg("hidb_dir"))
            .def("get", &hidb::HiDbSet::get, py::arg("virus_type"), py::return_value_policy::reference)
            ;

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

    return m.ptr();
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>figuring out how to use class from another python module<commit_after>#include "acmacs-base/pybind11.hh"
#include "acmacs-chart/ace.hh"
#include "variant-id.hh"
#include "vaccines.hh"
#include "hidb.hh"
#include "hidb-export.hh"

using namespace hidb;

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

PYBIND11_PLUGIN(hidb_backend)
{
    py::module m("hidb_backend", "HiDB access plugin");

      // ----------------------------------------------------------------------
      // acmacs_chart_backend
      // ----------------------------------------------------------------------

    auto acmacs_chart_backend = py::module::import("acmacs_chart_backend");
    class hidb_Antigen : public Antigen {};
      // using hidb_Antigen = Antigen;
    py::class_<hidb_Antigen>(m, "Antigen", acmacs_chart_backend.attr("Antigen"));
    // m.attr("Antigen") = acmacs_chart_backend.attr("Antigen");
    // py::class_<Antigen>(m, "Antigen", acmacs_chart_backend.attr("Antigen"));
    // py::class_<Serum>(m, "Serum", acmacs_chart_backend.attr("Serum"));

      // ----------------------------------------------------------------------
      // Vaccines
      // ----------------------------------------------------------------------

    py::class_<Vaccines::HomologousSerum>(m, "Vaccines_HomologousSerum")
            .def_readonly("serum", &Vaccines::HomologousSerum::serum)
            .def_readonly("serum_index", &Vaccines::HomologousSerum::serum_index)
            .def_readonly("most_recent_table", &Vaccines::HomologousSerum::most_recent_table_date)
            .def("number_of_tables", &Vaccines::HomologousSerum::number_of_tables)
            ;

    py::class_<Vaccines::Entry>(m, "Vaccines_Entry")
            .def_readonly("antigen", &Vaccines::Entry::antigen)
            .def_readonly("antigen_index", &Vaccines::Entry::antigen_index)
            .def_readonly("homologous_sera", &Vaccines::Entry::homologous_sera, py::return_value_policy::reference)
            ;

    py::class_<Vaccines>(m, "Vaccines")
            .def("report", &Vaccines::report, py::arg("indent") = 0)
            .def("egg", &Vaccines::egg, py::arg("no") = 0, py::return_value_policy::reference)
            .def("cell", &Vaccines::cell, py::arg("no") = 0, py::return_value_policy::reference)
            .def("reassortant", &Vaccines::reassortant, py::arg("no") = 0, py::return_value_policy::reference)
            .def("number_of_eggs", &Vaccines::number_of_eggs)
            .def("number_of_cells", &Vaccines::number_of_cells)
            .def("number_of_reassortants", &Vaccines::number_of_reassortants)
            ;

    m.def("find_vaccines_in_chart", &find_vaccines_in_chart, py::arg("name"), py::arg("chart"), py::arg("hidb"));

      // ----------------------------------------------------------------------
      // HiDb
      // ----------------------------------------------------------------------

    py::class_<PerTable>(m, "PerTable")
            .def("table_id", static_cast<const std::string (PerTable::*)() const>(&PerTable::table_id))
            ;

    py::class_<AntigenData>(m, "AntigenData")
            .def("data", py::overload_cast<>(&AntigenData::data))
            .def("number_of_tables", &AntigenData::number_of_tables)
            .def("most_recent_table", &AntigenData::most_recent_table)
            .def("oldest_table", &AntigenData::oldest_table)
            .def("date", &AntigenData::date)
            .def("tables", static_cast<const std::vector<PerTable>& (AntigenData::*)() const>(&AntigenData::per_table))
            ;

    py::class_<SerumData>(m, "SerumData")
            .def("data", py::overload_cast<>(&SerumData::data))
            .def("number_of_tables", &SerumData::number_of_tables)
            .def("most_recent_table", &SerumData::most_recent_table)
            .def("oldest_table", &SerumData::oldest_table)
            .def("tables", static_cast<const std::vector<PerTable>& (SerumData::*)() const>(&SerumData::per_table))
            .def("homologous", &SerumData::homologous)
            ;

    py::class_<AntigenRefs>(m, "AntigenRefs")
            .def("__len__", [](const AntigenRefs& ar) { return ar.size(); })
            .def("__getitem__", [](const AntigenRefs& ar, size_t i) { if (i >= ar.size()) throw py::index_error(); return ar[i]; }, py::return_value_policy::reference)
            .def("country", &AntigenRefs::country, py::arg("country"))
            .def("date_range", &AntigenRefs::date_range, py::arg("begin") = "", py::arg("end") = "")
            ;

      // --------------------------------------------------
      // lambdas below are to avoid python GC affecting data

    auto pointer_to_copy = [](const std::vector<const AntigenData*>& source) -> std::vector<AntigenData> {
        std::vector<AntigenData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_antigens_by_name = [&pointer_to_copy](const HiDb& aHiDb, std::string name) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens_by_name(name));
    };

    auto find_antigens = [&pointer_to_copy](const HiDb& aHiDb, std::string name) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens(name));
    };

    auto find_antigens_fuzzy = [&pointer_to_copy](const HiDb& aHiDb, std::string name) {
        return pointer_to_copy(aHiDb.find_antigens_fuzzy(name));
    };

    auto find_antigens_extra_fuzzy = [&pointer_to_copy](const HiDb& aHiDb, std::string name) {
        return pointer_to_copy(aHiDb.find_antigens_extra_fuzzy(name));
    };

    auto find_antigens_with_score = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_antigens_with_score(name);
        std::vector<std::pair<AntigenData, size_t>> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return std::make_pair(*e.first, e.second); });
        return result;
    };

    auto find_antigens_by_cdcid = [&pointer_to_copy](const HiDb& aHiDb, std::string cdcid) -> std::vector<AntigenData> {
        return pointer_to_copy(aHiDb.find_antigens_by_cdcid(cdcid));
    };

    auto find_sera = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_sera(name);
        std::vector<SerumData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_homologous_sera = [](const HiDb& aHiDb, const AntigenData& aAntigen) {
        const auto source = aHiDb.find_homologous_sera(aAntigen);
        std::vector<SerumData> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return *e; });
        return result;
    };

    auto find_sera_with_score = [](const HiDb& aHiDb, std::string name) {
        const auto source = aHiDb.find_sera_with_score(name);
        std::vector<std::pair<SerumData, size_t>> result;
        std::transform(source.begin(), source.end(), std::back_inserter(result), [](const auto& e) { return std::make_pair(*e.first, e.second); });
        return result;
    };

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

    py::class_<HiDbStat>(m, "HiDbStat")
            .def(py::init<>())
            .def("compute_totals", &HiDbStat::compute_totals)
            .def("as_dict", [](HiDbStat& aStat) -> HiDbStatContainer& { return aStat; }, py::return_value_policy::reference)
            ;

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

    py::class_<HiDb>(m, "HiDb")
            .def(py::init<>())
            .def("add", &HiDb::add, py::arg("chart"))
            .def("export_to", &HiDb::exportTo, py::arg("filename"), py::arg("pretty") = false)
            .def("import_from", &HiDb::importFrom, py::arg("filename"))
            .def("import_locdb", &HiDb::importLocDb, py::arg("filename"))

            .def("all_antigens", &HiDb::all_antigens, py::return_value_policy::reference)
            .def("all_countries", &HiDb::all_countries)
            .def("unrecognized_locations", &HiDb::unrecognized_locations, py::doc("returns unrecognized locations found in all antigen/serum names"))

            .def("stat_antigens", &HiDb::stat_antigens, py::arg("stat"), py::arg("start_date") = "", py::arg("end_date") = "")
            .def("stat_sera", &HiDb::stat_sera, py::arg("stat"), py::arg("stat_unique"), py::arg("start_date") = "", py::arg("end_date") = "")

            .def("list_antigen_names", &HiDb::list_antigen_names, py::arg("lab") = "", py::arg("full_name") = false)
            .def("list_antigens", &HiDb::list_antigens, py::arg("lab"))
            .def("find_antigens", find_antigens, py::arg("name"))
            .def("find_antigens_fuzzy", find_antigens_fuzzy, py::arg("name"))
            .def("find_antigens_extra_fuzzy", find_antigens_extra_fuzzy, py::arg("name"))
            .def("find_antigens_with_score", find_antigens_with_score, py::arg("name"))
            .def("find_antigens_by_name", find_antigens_by_name, py::arg("name"))
            .def("find_antigens_by_cdcid", find_antigens_by_cdcid, py::arg("cdcid"))
            .def("list_serum_names", &HiDb::list_serum_names, py::arg("lab") = "", py::arg("full_name") = false)
            .def("list_sera", &HiDb::list_sera, py::arg("lab"))
            .def("find_sera", find_sera, py::arg("name"))
            .def("find_homologous_sera", find_homologous_sera, py::arg("antigen"))
            .def("find_sera_with_score", find_sera_with_score, py::arg("name"))
            .def("find_homologous_antigens_for_sera_of_chart", &HiDb::find_homologous_antigens_for_sera_of_chart, py::arg("chart"))
            ;

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

    py::class_<hidb::HiDbSet>(m, "HiDbSet")
            .def(py::init<std::string>(), py::arg("hidb_dir"))
            .def("get", &hidb::HiDbSet::get, py::arg("virus_type"), py::return_value_policy::reference)
            ;

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

    return m.ptr();
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before><commit_msg>show CTL preview if CTL is enabled<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Andrew Kallmeyer <fsmv@sapium.net>
// Provided under the MIT License: https://mit-license.org

/*
 * +-------------------+
 * |      NOTICE       |
 * +-------------------+
 *
 * This code is experimental and a work in progress.
 *
 * I am trying to avoid having the code do anything that isn't directly required
 * for accomplishing the current level of features.
 *
 * I intend to produce code which uses a minimal abstraction structure.
 *
 * In order to accomplish this, I am first writing code without creating
 * any abstraction systems. Once I see the code that needs to be executed, I
 * will design an appropriate system.
 *
 * Also in pursuit of this goal, I am attempting to avoid abstractions other
 * people have created. Although I will obviously require established
 * abstractions for outputting information for users and for CPUs. Finally, this
 * program also must acknowledge the fact that it runs on a real machine with
 * limited memory and inside an operating system which manages access to that
 * memory.
 */

#include <stdint.h> // int32_t etc
#include <stdarg.h> // varargs defines

#define Assert(cond) if (!(cond)) { *((int*)0) = 0; }
#define ArrayLength(arr) (sizeof(arr) / sizeof((arr)[0]))

#include "parser.cpp"
#include "x86_codegen.cpp"

// TODO: Linux version
#include <windows.h>

HANDLE Out;

// Write an integer to a string in the specified base (not using CRT)
size_t WriteInt(uint32_t A, char *Str, uint32_t base = 16) {
    size_t CharCount = 0;

    // Write the string backwards
    do {
        uint32_t digit = A % base;
        if (digit < 10) {
            *Str++ = '0' + (char) digit;
        } else {
            *Str++ = 'A' + (char) (digit - 10);
        }
        A /= base;
        CharCount += 1;
    } while (A > 0);

    // Reverse the string
    for (char *Start = Str - CharCount, *End = Str - 1;
         Start < End;
         ++Start, --End)
    {
        char Temp = *Start;
        *Start = *End;
        *End = Temp;
    }

    return CharCount;
}

// A printf clone with less features (not using CRT)
void Print(HANDLE Out, const char *FormatString, ...) {
    va_list args;
    va_start(args, FormatString);

    DWORD CharsWritten;
    DWORD Idx = 0;
    for (; FormatString[Idx]; ++Idx) {
        if (FormatString[Idx] == '%') {
            switch (FormatString[Idx + 1]) {
            case 's': {
                // Write the string up to the percent
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                char *Str = va_arg(args, char*);
                DWORD Len = 0;
                for (; Str[Len]; ++Len)
                    ;
                WriteConsoleA(Out, Str, Len, &CharsWritten, 0);

            } goto next;
            case 'c': {
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                char Char = va_arg(args, char);
                WriteConsoleA(Out, &Char, 1, &CharsWritten, 0);

            } goto next;
            case 'u': {
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                uint32_t Int = va_arg(args, uint32_t);
                char Buffer[10];
                DWORD Len = (DWORD) WriteInt(Int, Buffer, 10);
                WriteConsoleA(Out, Buffer, Len, &CharsWritten, 0);

            } goto next;
            next:
                // Skip the %s
                FormatString += Idx + 2;
                Idx = 0;
            default: ;
            }
        }
    }

    if (Idx != 0) {
        WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);
    }

    va_end(args);
}

#include "printers.cpp"

size_t ParseArgs(char *CommandLine, size_t NumExpecting, ...) {
    va_list args;
    va_start(args, NumExpecting);
    char **Arg;

    size_t Count = 0;
    // Program name
    char *Curr = CommandLine;
    if (*Curr == '"') { // Quoted program name
        Curr += 1;
        for (; *Curr; ++Curr) {
            if (*Curr == '"') {
                Curr += 1;
                break;
            }
        }
    } else { // Not quoted
        for (; *Curr; ++Curr) {
            if (*Curr == ' ' && *(Curr - 1) != '\\') {
                break;
            }
        }
    }
    if (*Curr == '\0') {
        goto ParseArgs_ret;
    }
    *Curr++ = '\0';
    // Skip any extra spaces
    for (; *Curr && *Curr == ' '; ++Curr)
        ;

    // Arguments
    while (*Curr) {
        if (Count < NumExpecting) {
            Arg = va_arg(args, char**);
            *Arg = Curr;
        }
        Count += 1;
        // Find the end of the arg
        for (; *Curr; ++Curr) {
            if (*Curr == ' ' && *(Curr - 1) != '\\') {
                break;
            }
        }
        if (*Curr == ' ') {
            *Curr++ = '\0';
            // Skip any extra spaces
            for (; *Curr && *Curr == ' '; ++Curr)
                ;
        }
    }

ParseArgs_ret:
    // Set any unfilled args to 0
    for (size_t Idx = Count; Idx < NumExpecting; ++Idx) {
        Arg = va_arg(args, char**);
        *Arg = 0;
    }
    va_end(args);
    return Count;
}

void *LoadCode(uint8_t *Code, size_t CodeWritten) {
    void *CodeExe = VirtualAlloc(0, CodeWritten, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    uint8_t *CodeDest = (uint8_t*) CodeExe;
    for (size_t i = 0; i < CodeWritten; ++i) {
        *CodeDest++ = Code[i];
    }
    VirtualProtect(CodeExe, CodeWritten, PAGE_EXECUTE_READ, 0);
    return CodeExe;
}

bool RunCode(uint8_t *Code, size_t CodeWritten, char *WordPtr) {
    void *CodeLoc = LoadCode(Code, CodeWritten);
    uint32_t IsMatch = 0;
    __asm {
        mov eax, WordPtr
        call CodeLoc
        mov IsMatch, ebx
    }
    return (IsMatch != 0);
}

int main() {
    // Get the file handle for the output stream
    Out = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!Out || Out == INVALID_HANDLE_VALUE) {
        // we can't print the message, so do a message box (plus boxes are fun)
        MessageBox(0, "Could not get print to standard output", 0, MB_OK | MB_ICONERROR);
        return 1;
    }

    char *CommandLine = GetCommandLineA();
    char *ProgName = CommandLine;
    char *Regex, *Word;
    ParseArgs(CommandLine, 2, &Regex, &Word);

    if (!Regex) { // if we didn't find an argument
        Print(Out, "Usage: %s [regex] [search string (optional)]\n", ProgName);
        return 1;
    }

    Print(Out, "------------------- Regex --------------------\n\n");
    Print(Out, Regex);
    Print(Out, "\n");

    // Allocate storage for and then run each stage of the compiler in order
    // TODO: build an allocator for the stages to use with flexible storage

    // Allocate NFA stage storage
    size_t ArcListSize = sizeof(nfa_arc_list) + 32 * sizeof(nfa_transition);
    size_t NFASize = sizeof(nfa) + 32 * ArcListSize;
    nfa *NFA = (nfa *) VirtualAlloc(0, NFASize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    NFA->SizeOfArcList = ArcListSize;
    if (!NFA) {
        Print(Out, "Could not allocate space for NFA\n");
        return 1;
    }

    // Convert regex to NFA
    ReParse(Regex, NFA);

    Print(Out, "\n-------------------- NFA ---------------------\n\n");
    PrintNFA(NFA);

    // Note: this is all x86-specific after this point
    // TODO: ARM support

    // Allocate storage for intermediate representation code gen
    size_t InstructionsSize = sizeof(instruction) * 1024;
    instruction *Instructions = (instruction*) VirtualAlloc(0, InstructionsSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (!Instructions) {
        Print(Out, "Could not allocate space for Instructions\n");
        return 1;
    }

    // Convert the NFA into an intermediate code representation
    size_t InstructionsGenerated = GenerateInstructions(NFA, Instructions);

    Print(Out, "\n---------------- Instructions ----------------\n\n");
    PrintInstructions(Instructions, InstructionsGenerated);

    // Allocate storage for the unpacked x86 opcodes
    size_t UnpackedOpcodesSize = sizeof(opcode_unpacked) * InstructionsGenerated;
    opcode_unpacked *UnpackedOpcodes = (opcode_unpacked*) VirtualAlloc(0, UnpackedOpcodesSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (!UnpackedOpcodes) {
        Print(Out, "Could not allocate space for Unpacked Opcodes");
        return 1;
    }

    // Turn the instructions into x86 op codes and resolve jump destinations
    AssembleInstructions(Instructions, InstructionsGenerated, UnpackedOpcodes);
    // Note: no more return count here, this keeps the same number of instructions

    // Allocate storage for the actual byte code
    size_t CodeSize = sizeof(opcode_unpacked) * InstructionsGenerated; // sizeof(opcode_unpacked) is an upper bound
    uint8_t *Code = (uint8_t*) VirtualAlloc(0, CodeSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    size_t CodeWritten = PackCode(UnpackedOpcodes, InstructionsGenerated, Code);

    Print(Out, "\n-------------------- Code --------------------\n\n");
    PrintByteCode(Code, CodeWritten);

    if (Word) {
        bool IsMatch = RunCode(Code, CodeWritten, Word);

        Print(Out, "\n\n------------------- Result -------------------\n\n");
        Print(Out, "Search Word: %s\n", Word);
        if (IsMatch) {
            Print(Out, "MATCH\n");
        }else{
            Print(Out, "NO MATCH\n");
        }
    }

    return 0;
}

// Not using the CRT, for fun I guess. The binary is smaller!
void __stdcall mainCRTStartup() {
    int Result;
    Result = main();
    ExitProcess(Result);
}
<commit_msg>Added extra inline asm to make sure the compiler knows which registers I clobber<commit_after>// Copyright (c) 2016-2017 Andrew Kallmeyer <fsmv@sapium.net>
// Provided under the MIT License: https://mit-license.org

/*
 * +-------------------+
 * |      NOTICE       |
 * +-------------------+
 *
 * This code is experimental and a work in progress.
 *
 * I am trying to avoid having the code do anything that isn't directly required
 * for accomplishing the current level of features.
 *
 * I intend to produce code which uses a minimal abstraction structure.
 *
 * In order to accomplish this, I am first writing code without creating
 * any abstraction systems. Once I see the code that needs to be executed, I
 * will design an appropriate system.
 *
 * Also in pursuit of this goal, I am attempting to avoid abstractions other
 * people have created. Although I will obviously require established
 * abstractions for outputting information for users and for CPUs. Finally, this
 * program also must acknowledge the fact that it runs on a real machine with
 * limited memory and inside an operating system which manages access to that
 * memory.
 */

#include <stdint.h> // int32_t etc
#include <stdarg.h> // varargs defines

#define Assert(cond) if (!(cond)) { *((int*)0) = 0; }
#define ArrayLength(arr) (sizeof(arr) / sizeof((arr)[0]))

#include "parser.cpp"
#include "x86_codegen.cpp"

// TODO: Linux version
#include <windows.h>

HANDLE Out;

// Write an integer to a string in the specified base (not using CRT)
size_t WriteInt(uint32_t A, char *Str, uint32_t base = 16) {
    size_t CharCount = 0;

    // Write the string backwards
    do {
        uint32_t digit = A % base;
        if (digit < 10) {
            *Str++ = '0' + (char) digit;
        } else {
            *Str++ = 'A' + (char) (digit - 10);
        }
        A /= base;
        CharCount += 1;
    } while (A > 0);

    // Reverse the string
    for (char *Start = Str - CharCount, *End = Str - 1;
         Start < End;
         ++Start, --End)
    {
        char Temp = *Start;
        *Start = *End;
        *End = Temp;
    }

    return CharCount;
}

// A printf clone with less features (not using CRT)
void Print(HANDLE Out, const char *FormatString, ...) {
    va_list args;
    va_start(args, FormatString);

    DWORD CharsWritten;
    DWORD Idx = 0;
    for (; FormatString[Idx]; ++Idx) {
        if (FormatString[Idx] == '%') {
            switch (FormatString[Idx + 1]) {
            case 's': {
                // Write the string up to the percent
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                char *Str = va_arg(args, char*);
                DWORD Len = 0;
                for (; Str[Len]; ++Len)
                    ;
                WriteConsoleA(Out, Str, Len, &CharsWritten, 0);

            } goto next;
            case 'c': {
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                char Char = va_arg(args, char);
                WriteConsoleA(Out, &Char, 1, &CharsWritten, 0);

            } goto next;
            case 'u': {
                WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);

                uint32_t Int = va_arg(args, uint32_t);
                char Buffer[10];
                DWORD Len = (DWORD) WriteInt(Int, Buffer, 10);
                WriteConsoleA(Out, Buffer, Len, &CharsWritten, 0);

            } goto next;
            next:
                // Skip the %s
                FormatString += Idx + 2;
                Idx = 0;
            default: ;
            }
        }
    }

    if (Idx != 0) {
        WriteConsoleA(Out, FormatString, Idx, &CharsWritten, 0);
    }

    va_end(args);
}

#include "printers.cpp"

size_t ParseArgs(char *CommandLine, size_t NumExpecting, ...) {
    va_list args;
    va_start(args, NumExpecting);
    char **Arg;

    size_t Count = 0;
    // Program name
    char *Curr = CommandLine;
    if (*Curr == '"') { // Quoted program name
        Curr += 1;
        for (; *Curr; ++Curr) {
            if (*Curr == '"') {
                Curr += 1;
                break;
            }
        }
    } else { // Not quoted
        for (; *Curr; ++Curr) {
            if (*Curr == ' ' && *(Curr - 1) != '\\') {
                break;
            }
        }
    }
    if (*Curr == '\0') {
        goto ParseArgs_ret;
    }
    *Curr++ = '\0';
    // Skip any extra spaces
    for (; *Curr && *Curr == ' '; ++Curr)
        ;

    // Arguments
    while (*Curr) {
        if (Count < NumExpecting) {
            Arg = va_arg(args, char**);
            *Arg = Curr;
        }
        Count += 1;
        // Find the end of the arg
        for (; *Curr; ++Curr) {
            if (*Curr == ' ' && *(Curr - 1) != '\\') {
                break;
            }
        }
        if (*Curr == ' ') {
            *Curr++ = '\0';
            // Skip any extra spaces
            for (; *Curr && *Curr == ' '; ++Curr)
                ;
        }
    }

ParseArgs_ret:
    // Set any unfilled args to 0
    for (size_t Idx = Count; Idx < NumExpecting; ++Idx) {
        Arg = va_arg(args, char**);
        *Arg = 0;
    }
    va_end(args);
    return Count;
}

void *LoadCode(uint8_t *Code, size_t CodeWritten) {
    void *CodeExe = VirtualAlloc(0, CodeWritten, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    uint8_t *CodeDest = (uint8_t*) CodeExe;
    for (size_t i = 0; i < CodeWritten; ++i) {
        *CodeDest++ = Code[i];
    }
    VirtualProtect(CodeExe, CodeWritten, PAGE_EXECUTE_READ, 0);
    return CodeExe;
}

bool RunCode(uint8_t *Code, size_t CodeWritten, char *WordPtr) {
    void *CodeLoc = LoadCode(Code, CodeWritten);
    uint32_t IsMatch = 0;
    __asm {
        // Use the registers used in the code so the compiler knows we use them
        xor ebx, ebx
        xor ecx, ecx
        xor edx, edx

        mov eax, WordPtr
        call CodeLoc
        mov IsMatch, ebx
    }
    return (IsMatch != 0);
}

int main() {
    // Get the file handle for the output stream
    Out = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!Out || Out == INVALID_HANDLE_VALUE) {
        // we can't print the message, so do a message box (plus boxes are fun)
        MessageBox(0, "Could not get print to standard output", 0, MB_OK | MB_ICONERROR);
        return 1;
    }

    char *CommandLine = GetCommandLineA();
    char *ProgName = CommandLine;
    char *Regex, *Word;
    ParseArgs(CommandLine, 2, &Regex, &Word);

    if (!Regex) { // if we didn't find an argument
        Print(Out, "Usage: %s [regex] [search string (optional)]\n", ProgName);
        return 1;
    }

    Print(Out, "------------------- Regex --------------------\n\n");
    Print(Out, Regex);
    Print(Out, "\n");

    // Allocate storage for and then run each stage of the compiler in order
    // TODO: build an allocator for the stages to use with flexible storage

    // Allocate NFA stage storage
    size_t ArcListSize = sizeof(nfa_arc_list) + 32 * sizeof(nfa_transition);
    size_t NFASize = sizeof(nfa) + 32 * ArcListSize;
    nfa *NFA = (nfa *) VirtualAlloc(0, NFASize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    NFA->SizeOfArcList = ArcListSize;
    if (!NFA) {
        Print(Out, "Could not allocate space for NFA\n");
        return 1;
    }

    // Convert regex to NFA
    ReParse(Regex, NFA);

    Print(Out, "\n-------------------- NFA ---------------------\n\n");
    PrintNFA(NFA);

    // Note: this is all x86-specific after this point
    // TODO: ARM support

    // Allocate storage for intermediate representation code gen
    size_t InstructionsSize = sizeof(instruction) * 1024;
    instruction *Instructions = (instruction*) VirtualAlloc(0, InstructionsSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (!Instructions) {
        Print(Out, "Could not allocate space for Instructions\n");
        return 1;
    }

    // Convert the NFA into an intermediate code representation
    size_t InstructionsGenerated = GenerateInstructions(NFA, Instructions);

    Print(Out, "\n---------------- Instructions ----------------\n\n");
    PrintInstructions(Instructions, InstructionsGenerated);

    // Allocate storage for the unpacked x86 opcodes
    size_t UnpackedOpcodesSize = sizeof(opcode_unpacked) * InstructionsGenerated;
    opcode_unpacked *UnpackedOpcodes = (opcode_unpacked*) VirtualAlloc(0, UnpackedOpcodesSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (!UnpackedOpcodes) {
        Print(Out, "Could not allocate space for Unpacked Opcodes");
        return 1;
    }

    // Turn the instructions into x86 op codes and resolve jump destinations
    AssembleInstructions(Instructions, InstructionsGenerated, UnpackedOpcodes);
    // Note: no more return count here, this keeps the same number of instructions

    // Allocate storage for the actual byte code
    size_t CodeSize = sizeof(opcode_unpacked) * InstructionsGenerated; // sizeof(opcode_unpacked) is an upper bound
    uint8_t *Code = (uint8_t*) VirtualAlloc(0, CodeSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

    size_t CodeWritten = PackCode(UnpackedOpcodes, InstructionsGenerated, Code);

    Print(Out, "\n-------------------- Code --------------------\n\n");
    PrintByteCode(Code, CodeWritten);

    if (Word) {
        bool IsMatch = RunCode(Code, CodeWritten, Word);

        Print(Out, "\n\n------------------- Result -------------------\n\n");
        Print(Out, "Search Word: %s\n", Word);
        if (IsMatch) {
            Print(Out, "MATCH\n");
        }else{
            Print(Out, "NO MATCH\n");
        }
    }

    return 0;
}

// Not using the CRT, for fun I guess. The binary is smaller!
void __stdcall mainCRTStartup() {
    int Result;
    Result = main();
    ExitProcess(Result);
}
<|endoftext|>


<commit_before>/* /% C++ %/ */
/***********************************************************************
 * cint (C/C++ interpreter)
 ************************************************************************
 * Source file CallFunc.cxx
 ************************************************************************
 * Description:
 *  Extended Run Time Type Identification API
 ************************************************************************
 * Copyright(c) 1995~1999  Masaharu Goto (MXJ02154@niftyserve.or.jp)
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 ************************************************************************/

#include "Api.h"
#include "common.h"

/*********************************************************************
* class G__CallFunc
*
* Usage1:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method and argument
*   func.SetFunc(&canvas,"Draw","\"ABC\",1234,3.14",&offset);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*
* Usage2:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method
*   func.SetFunc(canvas.GetMethod("Draw","char*,int,double",&offset).InterfaceMethod());
*   // set arguments
*   char *title="ABC";
*   func.SetArg((long)title);
*   func.SetArg((long)1234);
*   func.SetArg((double)3.14);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*********************************************************************/
///////////////////////////////////////////////////////////////////////////
G__CallFunc::G__CallFunc()
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  Init();
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Init()
{
  pfunc = (G__InterfaceMethod)NULL;
  para.paran = 0;
#ifndef G__OLDIMPLEMENTATION1547
  result = G__null;
#ifdef G__ASM_WHOLEFUNC
  bytecode = (struct G__bytecodefunc*)NULL;
#endif
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__InterfaceMethod f)
{
  pfunc = f; // Set pointer to interface method
}
#ifdef G__ASM_WHOLEFUNC
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetBytecode(struct G__bytecodefunc* bc)
{
  bytecode = bc;
  if(bytecode) pfunc = (G__InterfaceMethod)G__exec_bytecode;
  else {
    pfunc = (G__InterfaceMethod)NULL;
#ifndef G__ROOT
    G__fprinterr(G__serr,"Warning: Bytecode compilation of %s failed. G__CallFunc::Exec may be slow\n",method.Name());
#endif
  }
  para.paran=0;
}
#endif
#ifndef G__OLDIMPLEMENTATION533
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgArray(long *p)
{
  int i,n;
  if(method.IsValid()) {
    n = method.NArg();
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
    G__MethodArgInfo arginfo;
    arginfo.Init(method);
#endif
    for(i=0;i<n;i++) {
      para.para[i].obj.i = p[i];
      para.para[i].ref = p[i];
      // Following data shouldn't matter, but set just in case
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
      arginfo.Next();
      para.para[i].type = arginfo.Type()->Type();
#else
      para.para[i].type = 'l';
#endif
      para.para[i].tagnum = -1;
      para.para[i].typenum = -1;
    }
    para.paran=n;
  }
  else {
    G__fprinterr(G__serr,"Error: G__CallFunc::SetArgArray() must be initialized with 'G__CallFunc::SetFunc(G__ClassInfo* cls,char* fname,char* args,long* poffset)' first\n");
  }
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(long l)
{
  para.para[para.paran].obj.i = l;
  para.para[para.paran].ref = l;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].type = 'l';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(double d)
{
  para.para[para.paran].obj.d = d;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].ref = 0 ;
  para.para[para.paran].type = 'd';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
#ifndef G__FONS51
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgs(const char* args)
{
  int isrc=0;
  char *endmark=(char*)",";

  // separate and evaluate argument list
  para.paran=0;
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      ++para.paran; // increment argument count
    }
  } while (','==c);
}
#endif
#ifndef G__OLDIMPLEMENTATION540
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFuncProto(G__ClassInfo* cls
			  ,const char* fname  ,const char* argtype
			  ,long* poffset)
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
#ifdef G__OLDIMPLEMENTATION862
  if((G__InterfaceMethod)NULL==pfunc) {
    SetBytecode(method.GetBytecode()); // try to compile bytecode
  }
#endif
  para.paran=0; // reset parameters, not needed actually, done in SetBytecode

#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__ClassInfo* cls
			  ,const char* fname  ,const char* args
			  ,long* poffset)
{
  // G__getstream(), G__type2string()
  int isrc=0;
  char *endmark=(char*)",";
  char argtype[G__ONELINE];
  int pos=0;
  G__value *buf;
#ifdef G__OLDIMPLEMENTATION533
#ifdef G__ASM_WHOLEFUNC
  G__MethodInfo method;
#endif
#endif

  // separate and evaluate argument list
  para.paran=0;
  argtype[0]='\0';
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      buf = &para.para[para.paran];
      // set type string
      if(pos) argtype[pos++]=',';
      strcpy(argtype+pos
	     ,G__type2string(buf->type,buf->tagnum,buf->typenum,(int)buf->ref
			   ,0));
      pos = strlen(argtype);
      ++para.paran; // increment argument count
    }
  } while (','==c);

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
  if((G__InterfaceMethod)NULL==pfunc) {
    int store_paran=para.paran;
    SetBytecode(method.GetBytecode()); // try to compile bytecode
    para.paran=store_paran;
  }
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Exec(void *pobject)
{
  int ret;
  long store_struct_offset;
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
long G__CallFunc::ExecInt(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__int(result));
}
///////////////////////////////////////////////////////////////////////////
double G__CallFunc::ExecDouble(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__double(result));
}
///////////////////////////////////////////////////////////////////////////
int G__CallFunc::ExecInterpretedFunc(G__value* presult)
{
  int ret=0;
  if(method.IsValid()) {
    int store_asm_exec=G__asm_exec;
    int store_asm_index=G__asm_index;
    int store_asm_noverflow = G__asm_noverflow;
    G__asm_exec=1;
    G__asm_index = method.Index();
    G__asm_noverflow = 0;
    ret = G__interpret_func(presult,(char*)method.Name()
		            ,&para,method.Hash(),method.ifunc()
			    ,G__EXACT,G__TRYNORMAL);
    G__asm_exec = store_asm_exec;
    G__asm_index= store_asm_index;
    G__asm_noverflow = store_asm_noverflow;
  }
  return(ret);
}
///////////////////////////////////////////////////////////////////////////
#ifndef G__OLDIMPLEMENTATION1591
void G__CallFunc::SetFuncType() {
  if(method.IsValid()) {
    struct G__ifunc_table *ifunc = method.ifunc();
    int ifn = method.Index();
    result.type = ifunc->type[ifn];
    result.tagnum = ifunc->p_tagtable[ifn];
    result.typenum = ifunc->p_typetable[ifn];
    result.isconst = ifunc->isconst[ifn];
    if('d'!=result.type&&'f'!=result.type) {
      result.obj.reftype.reftype = ifunc->reftype[ifn];
    }
  }
}
#endif
///////////////////////////////////////////////////////////////////////////

<commit_msg>latest version of Masa (just reorder of one call to SetFuncType()).<commit_after>/* /% C++ %/ */
/***********************************************************************
 * cint (C/C++ interpreter)
 ************************************************************************
 * Source file CallFunc.cxx
 ************************************************************************
 * Description:
 *  Extended Run Time Type Identification API
 ************************************************************************
 * Copyright(c) 1995~1999  Masaharu Goto (MXJ02154@niftyserve.or.jp)
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 ************************************************************************/

#include "Api.h"
#include "common.h"

/*********************************************************************
* class G__CallFunc
*
* Usage1:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method and argument
*   func.SetFunc(&canvas,"Draw","\"ABC\",1234,3.14",&offset);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*
* Usage2:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method
*   func.SetFunc(canvas.GetMethod("Draw","char*,int,double",&offset).InterfaceMethod());
*   // set arguments
*   char *title="ABC";
*   func.SetArg((long)title);
*   func.SetArg((long)1234);
*   func.SetArg((double)3.14);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*********************************************************************/
///////////////////////////////////////////////////////////////////////////
G__CallFunc::G__CallFunc()
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  Init();
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Init()
{
  pfunc = (G__InterfaceMethod)NULL;
  para.paran = 0;
#ifndef G__OLDIMPLEMENTATION1547
  result = G__null;
#ifdef G__ASM_WHOLEFUNC
  bytecode = (struct G__bytecodefunc*)NULL;
#endif
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__InterfaceMethod f)
{
  pfunc = f; // Set pointer to interface method
}
#ifdef G__ASM_WHOLEFUNC
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetBytecode(struct G__bytecodefunc* bc)
{
  bytecode = bc;
  if(bytecode) pfunc = (G__InterfaceMethod)G__exec_bytecode;
  else {
    pfunc = (G__InterfaceMethod)NULL;
#ifndef G__ROOT
    G__fprinterr(G__serr,"Warning: Bytecode compilation of %s failed. G__CallFunc::Exec may be slow\n",method.Name());
#endif
  }
  para.paran=0;
}
#endif
#ifndef G__OLDIMPLEMENTATION533
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgArray(long *p)
{
  int i,n;
  if(method.IsValid()) {
    n = method.NArg();
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
    G__MethodArgInfo arginfo;
    arginfo.Init(method);
#endif
    for(i=0;i<n;i++) {
      para.para[i].obj.i = p[i];
      para.para[i].ref = p[i];
      // Following data shouldn't matter, but set just in case
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
      arginfo.Next();
      para.para[i].type = arginfo.Type()->Type();
#else
      para.para[i].type = 'l';
#endif
      para.para[i].tagnum = -1;
      para.para[i].typenum = -1;
    }
    para.paran=n;
  }
  else {
    G__fprinterr(G__serr,"Error: G__CallFunc::SetArgArray() must be initialized with 'G__CallFunc::SetFunc(G__ClassInfo* cls,char* fname,char* args,long* poffset)' first\n");
  }
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(long l)
{
  para.para[para.paran].obj.i = l;
  para.para[para.paran].ref = l;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].type = 'l';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(double d)
{
  para.para[para.paran].obj.d = d;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].ref = 0 ;
  para.para[para.paran].type = 'd';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
#ifndef G__FONS51
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgs(const char* args)
{
  int isrc=0;
  char *endmark=(char*)",";

  // separate and evaluate argument list
  para.paran=0;
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      ++para.paran; // increment argument count
    }
  } while (','==c);
}
#endif
#ifndef G__OLDIMPLEMENTATION540
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFuncProto(G__ClassInfo* cls
			  ,const char* fname  ,const char* argtype
			  ,long* poffset)
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
#ifdef G__OLDIMPLEMENTATION862
  if((G__InterfaceMethod)NULL==pfunc) {
    SetBytecode(method.GetBytecode()); // try to compile bytecode
  }
#endif
  para.paran=0; // reset parameters, not needed actually, done in SetBytecode

#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__ClassInfo* cls
			  ,const char* fname  ,const char* args
			  ,long* poffset)
{
  // G__getstream(), G__type2string()
  int isrc=0;
  char *endmark=(char*)",";
  char argtype[G__ONELINE];
  int pos=0;
  G__value *buf;
#ifdef G__OLDIMPLEMENTATION533
#ifdef G__ASM_WHOLEFUNC
  G__MethodInfo method;
#endif
#endif

  // separate and evaluate argument list
  para.paran=0;
  argtype[0]='\0';
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      buf = &para.para[para.paran];
      // set type string
      if(pos) argtype[pos++]=',';
      strcpy(argtype+pos
	     ,G__type2string(buf->type,buf->tagnum,buf->typenum,(int)buf->ref
			   ,0));
      pos = strlen(argtype);
      ++para.paran; // increment argument count
    }
  } while (','==c);

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
  if((G__InterfaceMethod)NULL==pfunc) {
    int store_paran=para.paran;
    SetBytecode(method.GetBytecode()); // try to compile bytecode
    para.paran=store_paran;
  }
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Exec(void *pobject)
{
  int ret;
  long store_struct_offset;
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
long G__CallFunc::ExecInt(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__int(result));
}
///////////////////////////////////////////////////////////////////////////
double G__CallFunc::ExecDouble(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__double(result));
}
///////////////////////////////////////////////////////////////////////////
int G__CallFunc::ExecInterpretedFunc(G__value* presult)
{
  int ret=0;
  if(method.IsValid()) {
    int store_asm_exec=G__asm_exec;
    int store_asm_index=G__asm_index;
    int store_asm_noverflow = G__asm_noverflow;
    G__asm_exec=1;
    G__asm_index = method.Index();
    G__asm_noverflow = 0;
    ret = G__interpret_func(presult,(char*)method.Name()
		            ,&para,method.Hash(),method.ifunc()
			    ,G__EXACT,G__TRYNORMAL);
    G__asm_exec = store_asm_exec;
    G__asm_index= store_asm_index;
    G__asm_noverflow = store_asm_noverflow;
  }
  return(ret);
}
///////////////////////////////////////////////////////////////////////////
#ifndef G__OLDIMPLEMENTATION1591
void G__CallFunc::SetFuncType() {
  if(method.IsValid()) {
    struct G__ifunc_table *ifunc = method.ifunc();
    int ifn = method.Index();
    result.type = ifunc->type[ifn];
    result.tagnum = ifunc->p_tagtable[ifn];
    result.typenum = ifunc->p_typetable[ifn];
    result.isconst = ifunc->isconst[ifn];
    if('d'!=result.type&&'f'!=result.type) {
      result.obj.reftype.reftype = ifunc->reftype[ifn];
    }
  }
}
#endif
///////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before><commit_msg>Reduce OUString temporaries<commit_after><|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <hintids.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentContentOperations.hxx>
#include <editsh.hxx>
#include <cntfrm.hxx>
#include <pam.hxx>
#include <swundo.hxx>
#include <edimp.hxx>
#include <IMark.hxx>
#include <docary.hxx>
#include <SwRewriter.hxx>
#include <globals.hrc>

#include <comcore.hrc>
#include <list>

void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
{
    bool bSelectAll = StartsWithTable() && ExtendedSelectedAll(/*bFootnotes =*/ false);
    // only for selections
    if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
        return;

    // Is the selection in a table? Then delete only the content of the selected boxes.
    // Here, there are two cases:
    // 1. Point and Mark are in one box, delete selection as usual
    // 2. Point and Mark are in different boxes, search all selected boxes and delete content
    // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
    if( rPam.GetNode().FindTableNode() &&
        rPam.GetNode().StartOfSectionNode() !=
        rPam.GetNode(false).StartOfSectionNode() && !bSelectAll )
    {
        // group the Undo in the table
        if( pUndo && !*pUndo )
        {
            GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
            *pUndo = true;
        }
        SwPaM aDelPam( *rPam.Start() );
        const SwPosition* pEndSelPos = rPam.End();
        do {
            aDelPam.SetMark();
            SwNode& rNd = aDelPam.GetNode();
            const SwNode& rEndNd = *rNd.EndOfSectionNode();
            if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
            {
                *aDelPam.GetPoint() = *pEndSelPos;
                pEndSelPos = 0;     // misuse a pointer as a flag
            }
            else
            {
                // then go to the end of the selection
                aDelPam.GetPoint()->nNode = rEndNd;
                aDelPam.Move( fnMoveBackward, fnGoCntnt );
            }
            // skip protected boxes
            if( !rNd.IsCntntNode() ||
                !rNd.IsInProtectSect() )
            {
                // delete everything
                GetDoc()->getIDocumentContentOperations().DeleteAndJoin( aDelPam );
                SaveTblBoxCntnt( aDelPam.GetPoint() );
            }

            if( !pEndSelPos ) // at the end of a selection
                break;
            aDelPam.DeleteMark();
            aDelPam.Move( fnMoveForward, fnGoCntnt ); // next box
        } while( pEndSelPos );
    }
    else
    {
        SwPaM aPam(rPam);
        if (bSelectAll)
            // Selection starts at the first para of the first cell, but we
            // want to delete the table node before the first cell as well.
            aPam.Start()->nNode = aPam.Start()->nNode.GetNode().FindTableNode()->GetIndex();
        // delete everything
        GetDoc()->getIDocumentContentOperations().DeleteAndJoin( aPam );
        SaveTblBoxCntnt( aPam.GetPoint() );
    }

    // Selection is not needed anymore
    rPam.DeleteMark();
}

long SwEditShell::Delete()
{
    SET_CURR_SHELL( this );
    long nRet = 0;
    if ( !HasReadonlySel() || CrsrInsideInputFld() )
    {
        StartAllAction();

        bool bUndo = GetCrsr()->GetNext() != GetCrsr();
        if( bUndo ) // more than one selection?
        {
            SwRewriter aRewriter;
            aRewriter.AddRule(UndoArg1, SW_RESSTR(STR_MULTISEL));

            GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_DELETE, &aRewriter);
        }

        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            DeleteSel( rPaM, &bUndo );
        }

        // If undo container then close here
        if( bUndo )
        {
            GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
        }
        EndAllAction();
        nRet = 1;
    }
    return nRet;
}

long SwEditShell::Copy( SwEditShell* pDestShell )
{
    if( !pDestShell )
        pDestShell = this;

    SET_CURR_SHELL( pDestShell );

    // List of insert positions for smart insert of block selections
    std::list< boost::shared_ptr<SwPosition> > aInsertList;

    // Fill list of insert positions
    {
        SwPosition * pPos = 0;
        boost::shared_ptr<SwPosition> pInsertPos;
        sal_uInt16 nMove = 0;
        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            if( !pPos )
            {
                if( pDestShell == this )
                {
                    // First cursor represents the target position!!
                    rPaM.DeleteMark();
                    pPos = (SwPosition*)rPaM.GetPoint();
                    continue;
                }
                else
                    pPos = pDestShell->GetCrsr()->GetPoint();
            }
            if( IsBlockMode() )
            {   // In block mode different insert positions will be calculated
                // by simulated cursor movements from the given first insert position
                if( nMove )
                {
                    SwCursor aCrsr( *pPos, 0, false);
                    if( aCrsr.UpDown( false, nMove, 0, 0 ) )
                    {
                        pInsertPos.reset( new SwPosition( *aCrsr.GetPoint() ) );
                        aInsertList.push_back( pInsertPos );
                    }
                }
                else
                    pInsertPos.reset( new SwPosition( *pPos ) );
                ++nMove;
            }
            SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
            // Check if a selection would be copied into itself
            if( pDestShell->GetDoc() == GetDoc() &&
                *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
                return sal_False;
        }
    }

    pDestShell->StartAllAction();
    SwPosition *pPos = 0;
    bool bRet = false;
    bool bFirstMove = true;
    SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
    sal_Int32 nSttCntIdx = 0;
    // For block selection this list is filled with the insert positions
    std::list< boost::shared_ptr<SwPosition> >::iterator pNextInsert = aInsertList.begin();

    pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
    for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
    {
        if( !pPos )
        {
            if( pDestShell == this )
            {
                // First cursor represents the target position!!
                rPaM.DeleteMark();
                pPos = (SwPosition*)rPaM.GetPoint();
                continue;
            }
            else
                pPos = pDestShell->GetCrsr()->GetPoint();
        }
        if( !bFirstMove )
        {
            if( pNextInsert != aInsertList.end() )
            {
                pPos = pNextInsert->get();
                ++pNextInsert;
            }
            else if( IsBlockMode() )
                GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
        }

        // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
        if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
            continue;

        if( bFirstMove )
        {
            // Store start position of the new area
            aSttNdIdx = pPos->nNode.GetIndex()-1;
            nSttCntIdx = pPos->nContent.GetIndex();
            bFirstMove = false;
        }

        const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange( rPaM, *pPos, false ) );
        if (!bSuccess)
            continue;

        SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
        pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);

        bRet = true;
    }

    // Maybe nothing has been moved?
    if( !bFirstMove )
    {
        SwPaM* pCrsr = pDestShell->GetCrsr();
        pCrsr->SetMark();
        pCrsr->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
        pCrsr->GetPoint()->nContent.Assign( pCrsr->GetCntntNode(),nSttCntIdx);
        pCrsr->Exchange();
    }
    else
    {
        // If the cursor moved during move process, move also its GetMark
        pDestShell->GetCrsr()->SetMark();
        pDestShell->GetCrsr()->DeleteMark();
    }
#if OSL_DEBUG_LEVEL > 0
// check if the indices are registered in the correct nodes
{
    for(SwPaM& rCmp : pDestShell->GetCrsr()->GetRingContainer())
    {
        OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
                    == rCmp.GetCntntNode(), "Point in wrong Node" );
        OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
                    == rCmp.GetCntntNode(false), "Mark in wrong Node" );
        bool bTst = *rCmp.GetPoint() == *rCmp.GetMark();
        (void) bTst;
    }
}
#endif

    // close Undo container here
    pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
    pDestShell->EndAllAction();

    pDestShell->SaveTblBoxCntnt( pDestShell->GetCrsr()->GetPoint() );

    return (long)bRet;
}

/** Replace a selected area in a text node with a given string.
 *
 * Intended for "search & replace".
 *
 * @param bRegExpRplc if <true> replace tabs (\\t) and replace with found string (not \&).
 *                    E.g. [Fnd: "zzz", Repl: "xx\t\\t..&..\&"] --> "xx\t<Tab>..zzz..&"
 */
bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
{
    SET_CURR_SHELL( this );

    bool bRet = false;
    if( !HasReadonlySel() )
    {
        StartAllAction();
        GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);

        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
            {
                bRet = GetDoc()->getIDocumentContentOperations().ReplaceRange( rPaM, rNewStr, bRegExpRplc )
                    || bRet;
                SaveTblBoxCntnt( rPaM.GetPoint() );
            }
        }

        // close Undo container here
        GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
        EndAllAction();
    }
    return bRet;
}

/// special method for JOE's wizards
bool SwEditShell::DelFullPara()
{
    bool bRet = false;
    if( !IsTableMode() )
    {
        SwPaM* pCrsr = GetCrsr();
        // no multi selection
        if( !pCrsr->IsMultiSelection() && !HasReadonlySel() )
        {
            SET_CURR_SHELL( this );
            StartAllAction();
            bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCrsr );
            EndAllAction();
        }
    }
    return bRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>tdf#87400: sw: fix ~SwIndexReg assertion in AutoCorrect<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include <hintids.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentContentOperations.hxx>
#include <editsh.hxx>
#include <cntfrm.hxx>
#include <pam.hxx>
#include <swundo.hxx>
#include <edimp.hxx>
#include <IMark.hxx>
#include <docary.hxx>
#include <SwRewriter.hxx>
#include <globals.hrc>

#include <comcore.hrc>
#include <list>

void SwEditShell::DeleteSel( SwPaM& rPam, bool* pUndo )
{
    bool bSelectAll = StartsWithTable() && ExtendedSelectedAll(/*bFootnotes =*/ false);
    // only for selections
    if( !rPam.HasMark() || *rPam.GetPoint() == *rPam.GetMark())
        return;

    // Is the selection in a table? Then delete only the content of the selected boxes.
    // Here, there are two cases:
    // 1. Point and Mark are in one box, delete selection as usual
    // 2. Point and Mark are in different boxes, search all selected boxes and delete content
    // 3. Point and Mark are at the document start and end, Point is in a table: delete selection as usual
    if( rPam.GetNode().FindTableNode() &&
        rPam.GetNode().StartOfSectionNode() !=
        rPam.GetNode(false).StartOfSectionNode() && !bSelectAll )
    {
        // group the Undo in the table
        if( pUndo && !*pUndo )
        {
            GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
            *pUndo = true;
        }
        SwPaM aDelPam( *rPam.Start() );
        const SwPosition* pEndSelPos = rPam.End();
        do {
            aDelPam.SetMark();
            SwNode& rNd = aDelPam.GetNode();
            const SwNode& rEndNd = *rNd.EndOfSectionNode();
            if( pEndSelPos->nNode.GetIndex() <= rEndNd.GetIndex() )
            {
                *aDelPam.GetPoint() = *pEndSelPos;
                pEndSelPos = 0;     // misuse a pointer as a flag
            }
            else
            {
                // then go to the end of the selection
                aDelPam.GetPoint()->nNode = rEndNd;
                aDelPam.Move( fnMoveBackward, fnGoCntnt );
            }
            // skip protected boxes
            if( !rNd.IsCntntNode() ||
                !rNd.IsInProtectSect() )
            {
                // delete everything
                GetDoc()->getIDocumentContentOperations().DeleteAndJoin( aDelPam );
                SaveTblBoxCntnt( aDelPam.GetPoint() );
            }

            if( !pEndSelPos ) // at the end of a selection
                break;
            aDelPam.DeleteMark();
            aDelPam.Move( fnMoveForward, fnGoCntnt ); // next box
        } while( pEndSelPos );
    }
    else
    {
        std::unique_ptr<SwPaM> pNewPam;
        SwPaM * pPam = &rPam;
        if (bSelectAll)
        {
            assert(dynamic_cast<SwShellCrsr*>(&rPam)); // must be corrected pam
            pNewPam.reset(new SwPaM(rPam));
            // Selection starts at the first para of the first cell, but we
            // want to delete the table node before the first cell as well.
            pNewPam->Start()->nNode = pNewPam->Start()->nNode.GetNode().FindTableNode()->GetIndex();
            pPam = pNewPam.get();
        }
        // delete everything
        GetDoc()->getIDocumentContentOperations().DeleteAndJoin(*pPam);
        SaveTblBoxCntnt( pPam->GetPoint() );
    }

    // Selection is not needed anymore
    rPam.DeleteMark();
}

long SwEditShell::Delete()
{
    SET_CURR_SHELL( this );
    long nRet = 0;
    if ( !HasReadonlySel() || CrsrInsideInputFld() )
    {
        StartAllAction();

        bool bUndo = GetCrsr()->GetNext() != GetCrsr();
        if( bUndo ) // more than one selection?
        {
            SwRewriter aRewriter;
            aRewriter.AddRule(UndoArg1, SW_RESSTR(STR_MULTISEL));

            GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_DELETE, &aRewriter);
        }

        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            DeleteSel( rPaM, &bUndo );
        }

        // If undo container then close here
        if( bUndo )
        {
            GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_END, 0);
        }
        EndAllAction();
        nRet = 1;
    }
    return nRet;
}

long SwEditShell::Copy( SwEditShell* pDestShell )
{
    if( !pDestShell )
        pDestShell = this;

    SET_CURR_SHELL( pDestShell );

    // List of insert positions for smart insert of block selections
    std::list< boost::shared_ptr<SwPosition> > aInsertList;

    // Fill list of insert positions
    {
        SwPosition * pPos = 0;
        boost::shared_ptr<SwPosition> pInsertPos;
        sal_uInt16 nMove = 0;
        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            if( !pPos )
            {
                if( pDestShell == this )
                {
                    // First cursor represents the target position!!
                    rPaM.DeleteMark();
                    pPos = (SwPosition*)rPaM.GetPoint();
                    continue;
                }
                else
                    pPos = pDestShell->GetCrsr()->GetPoint();
            }
            if( IsBlockMode() )
            {   // In block mode different insert positions will be calculated
                // by simulated cursor movements from the given first insert position
                if( nMove )
                {
                    SwCursor aCrsr( *pPos, 0, false);
                    if( aCrsr.UpDown( false, nMove, 0, 0 ) )
                    {
                        pInsertPos.reset( new SwPosition( *aCrsr.GetPoint() ) );
                        aInsertList.push_back( pInsertPos );
                    }
                }
                else
                    pInsertPos.reset( new SwPosition( *pPos ) );
                ++nMove;
            }
            SwPosition *pTmp = IsBlockMode() ? pInsertPos.get() : pPos;
            // Check if a selection would be copied into itself
            if( pDestShell->GetDoc() == GetDoc() &&
                *rPaM.Start() <= *pTmp && *pTmp < *rPaM.End() )
                return sal_False;
        }
    }

    pDestShell->StartAllAction();
    SwPosition *pPos = 0;
    bool bRet = false;
    bool bFirstMove = true;
    SwNodeIndex aSttNdIdx( pDestShell->GetDoc()->GetNodes() );
    sal_Int32 nSttCntIdx = 0;
    // For block selection this list is filled with the insert positions
    std::list< boost::shared_ptr<SwPosition> >::iterator pNextInsert = aInsertList.begin();

    pDestShell->GetDoc()->GetIDocumentUndoRedo().StartUndo( UNDO_START, NULL );
    for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
    {
        if( !pPos )
        {
            if( pDestShell == this )
            {
                // First cursor represents the target position!!
                rPaM.DeleteMark();
                pPos = (SwPosition*)rPaM.GetPoint();
                continue;
            }
            else
                pPos = pDestShell->GetCrsr()->GetPoint();
        }
        if( !bFirstMove )
        {
            if( pNextInsert != aInsertList.end() )
            {
                pPos = pNextInsert->get();
                ++pNextInsert;
            }
            else if( IsBlockMode() )
                GetDoc()->getIDocumentContentOperations().SplitNode( *pPos, false );
        }

        // Only for a selection (non-text nodes have selection but Point/GetMark are equal)
        if( !rPaM.HasMark() || *rPaM.GetPoint() == *rPaM.GetMark() )
            continue;

        if( bFirstMove )
        {
            // Store start position of the new area
            aSttNdIdx = pPos->nNode.GetIndex()-1;
            nSttCntIdx = pPos->nContent.GetIndex();
            bFirstMove = false;
        }

        const bool bSuccess( GetDoc()->getIDocumentContentOperations().CopyRange( rPaM, *pPos, false ) );
        if (!bSuccess)
            continue;

        SwPaM aInsertPaM(*pPos, SwPosition(aSttNdIdx));
        pDestShell->GetDoc()->MakeUniqueNumRules(aInsertPaM);

        bRet = true;
    }

    // Maybe nothing has been moved?
    if( !bFirstMove )
    {
        SwPaM* pCrsr = pDestShell->GetCrsr();
        pCrsr->SetMark();
        pCrsr->GetPoint()->nNode = aSttNdIdx.GetIndex()+1;
        pCrsr->GetPoint()->nContent.Assign( pCrsr->GetCntntNode(),nSttCntIdx);
        pCrsr->Exchange();
    }
    else
    {
        // If the cursor moved during move process, move also its GetMark
        pDestShell->GetCrsr()->SetMark();
        pDestShell->GetCrsr()->DeleteMark();
    }
#if OSL_DEBUG_LEVEL > 0
// check if the indices are registered in the correct nodes
{
    for(SwPaM& rCmp : pDestShell->GetCrsr()->GetRingContainer())
    {
        OSL_ENSURE( rCmp.GetPoint()->nContent.GetIdxReg()
                    == rCmp.GetCntntNode(), "Point in wrong Node" );
        OSL_ENSURE( rCmp.GetMark()->nContent.GetIdxReg()
                    == rCmp.GetCntntNode(false), "Mark in wrong Node" );
        bool bTst = *rCmp.GetPoint() == *rCmp.GetMark();
        (void) bTst;
    }
}
#endif

    // close Undo container here
    pDestShell->GetDoc()->GetIDocumentUndoRedo().EndUndo( UNDO_END, NULL );
    pDestShell->EndAllAction();

    pDestShell->SaveTblBoxCntnt( pDestShell->GetCrsr()->GetPoint() );

    return (long)bRet;
}

/** Replace a selected area in a text node with a given string.
 *
 * Intended for "search & replace".
 *
 * @param bRegExpRplc if <true> replace tabs (\\t) and replace with found string (not \&).
 *                    E.g. [Fnd: "zzz", Repl: "xx\t\\t..&..\&"] --> "xx\t<Tab>..zzz..&"
 */
bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
{
    SET_CURR_SHELL( this );

    bool bRet = false;
    if( !HasReadonlySel() )
    {
        StartAllAction();
        GetDoc()->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);

        for(SwPaM& rPaM : GetCrsr()->GetRingContainer())
        {
            if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
            {
                bRet = GetDoc()->getIDocumentContentOperations().ReplaceRange( rPaM, rNewStr, bRegExpRplc )
                    || bRet;
                SaveTblBoxCntnt( rPaM.GetPoint() );
            }
        }

        // close Undo container here
        GetDoc()->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
        EndAllAction();
    }
    return bRet;
}

/// special method for JOE's wizards
bool SwEditShell::DelFullPara()
{
    bool bRet = false;
    if( !IsTableMode() )
    {
        SwPaM* pCrsr = GetCrsr();
        // no multi selection
        if( !pCrsr->IsMultiSelection() && !HasReadonlySel() )
        {
            SET_CURR_SHELL( this );
            StartAllAction();
            bRet = GetDoc()->getIDocumentContentOperations().DelFullPara( *pCrsr );
            EndAllAction();
        }
    }
    return bRet;
}

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


<commit_before><commit_msg>Fixes fdo#64237 by modifying the underlyning string<commit_after><|endoftext|>