<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cellkeytranslator.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-24 09:23:06 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "cellkeytranslator.hxx"
#include "rtl/ustring.hxx"

using ::com::sun::star::lang::Locale;
using ::std::list;
using ::std::hash_map;
using ::rtl::OUString;

enum LocaleMatch
{
    LOCALE_MATCH_NONE = 0,
    LOCALE_MATCH_LANG,
    LOCALE_MATCH_LANG_COUNTRY,
    LOCALE_MATCH_ALL
};

static LocaleMatch lclLocaleCompare(const Locale& rLocale1, const Locale& rLocale2)
{
    LocaleMatch eMatchLevel = LOCALE_MATCH_NONE;
    if ( !rLocale1.Language.compareTo(rLocale1.Language) )
        eMatchLevel = LOCALE_MATCH_LANG;
    else
        return eMatchLevel;

    if ( !rLocale1.Country.compareTo(rLocale2.Country) )
        eMatchLevel = LOCALE_MATCH_LANG_COUNTRY;
    else
        return eMatchLevel;

    if ( !rLocale1.Variant.compareTo(rLocale2.Variant) )
        eMatchLevel = LOCALE_MATCH_ALL;

    return eMatchLevel;
}

ScCellKeyword::ScCellKeyword(const sal_Char* pName, OpCode eOpCode, const Locale& rLocale) :
    mpName(pName),
    meOpCode(eOpCode),
    mrLocale(rLocale)
{
}

::std::auto_ptr<ScCellKeywordTranslator> ScCellKeywordTranslator::spInstance(NULL);

static void lclMatchKeyword(String& rName, const ScCellKeywordHashMap& aMap, OpCode eOpCode = ocNone, const Locale* pLocale = NULL)
{
    ScCellKeywordHashMap::const_iterator itrEnd = aMap.end();
    ScCellKeywordHashMap::const_iterator itr = aMap.find(rName);

    if ( itr == itrEnd || itr->second.empty() )
        // No candidate strings exist.  Bail out.
        return;

    if ( eOpCode == ocNone && !pLocale )
    {
        // Since no locale nor opcode matching is needed, simply return
        // the first item on the list.
        rName = String::CreateFromAscii( itr->second.front().mpName );
        return;
    }

    const sal_Char* aBestMatchName = itr->second.front().mpName;
    LocaleMatch eLocaleMatchLevel = LOCALE_MATCH_NONE;
    bool bOpCodeMatched = false;

    list<ScCellKeyword>::const_iterator itrListEnd = itr->second.end();
    list<ScCellKeyword>::const_iterator itrList = itr->second.begin();
    for ( ; itrList != itrListEnd; ++itrList )
    {
        if ( eOpCode != ocNone && pLocale )
        {
            if ( itrList->meOpCode == eOpCode )
            {
                LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
                if ( eLevel == LOCALE_MATCH_ALL )
                {
                    // Name with matching opcode and locale found.
                    rName = String::CreateFromAscii( itrList->mpName );
                    return;
                }
                else if ( eLevel > eLocaleMatchLevel )
                {
                    // Name with a better matching locale.
                    eLocaleMatchLevel = eLevel;
                    aBestMatchName = itrList->mpName;
                }
                else if ( !bOpCodeMatched )
                    // At least the opcode matches.
                    aBestMatchName = itrList->mpName;

                bOpCodeMatched = true;
            }
        }
        else if ( eOpCode != ocNone && !pLocale )
        {
            if ( itrList->meOpCode == eOpCode )
            {
                // Name with a matching opcode preferred.
                rName = String::CreateFromAscii( itrList->mpName );
                return;
            }
        }
        else if ( !eOpCode && pLocale )
        {
            LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
            if ( eLevel == LOCALE_MATCH_ALL )
            {
                // Name with matching locale preferred.
                rName = String::CreateFromAscii( itrList->mpName );
                return;
            }
            else if ( eLevel > eLocaleMatchLevel )
            {
                // Name with a better matching locale.
                eLocaleMatchLevel = eLevel;
                aBestMatchName = itrList->mpName;
            }
        }
    }

    // No preferred strings found.  Return the best matching name.
    rName = String::CreateFromAscii(aBestMatchName);
}

void ScCellKeywordTranslator::transKeyword(String& rName, const Locale* pLocale, OpCode eOpCode)
{
    if ( !spInstance.get() )
        spInstance.reset( new ScCellKeywordTranslator );

    lclMatchKeyword(rName, spInstance->maStringNameMap, eOpCode, pLocale);
}

ScCellKeywordTranslator::ScCellKeywordTranslator()
{
    init();
}

ScCellKeywordTranslator::~ScCellKeywordTranslator()
{
}

struct TransItem
{
    const sal_Char* from;
    const sal_Char* to;
    OpCode          func;
};

void ScCellKeywordTranslator::init()
{
    // 1. Keywords must be all uppercase.
    // 2. Mapping must be <localized string name> to <English string name>.

    // French language locale.

    static const Locale aFr(OUString::createFromAscii("fr"), OUString(), OUString());
    static const TransItem pFr[] =
    {
        // CELL
        {"ADRESSE",    "ADDRESS",   ocCell},
        {"COLONNE",    "COL",       ocCell},
        {"CONTENU",    "CONTENTS",  ocCell},
        {"COULEUR",    "COLOR",     ocCell},
        {"LARGEUR",    "WIDTH",     ocCell},
        {"LIGNE",      "ROW",       ocCell},
        {"NOMFICHIER", "FILENAME",  ocCell},
        {"PREFIXE",    "PREFIX",    ocCell},
        {"PROTEGE",    "PROTECT",   ocCell},

        // INFO
        {"NBFICH",     "NUMFILE",   ocInfo},
        {"RECALCUL",   "RECALC",    ocInfo},
        {"SYSTEXPL",   "SYSTEM",    ocInfo},
        {"VERSION",    "RELEASE",   ocInfo},
        {"VERSIONSE",  "OSVERSION", ocInfo},

        {NULL, NULL, ocNone}
    };
    addToMap(pFr, aFr);
}

void ScCellKeywordTranslator::addToMap(const String& rKey, const sal_Char* pName, const Locale& rLocale, OpCode eOpCode)
{
    ScCellKeyword aKeyItem( pName, eOpCode, rLocale );

    ScCellKeywordHashMap::iterator itrEnd = maStringNameMap.end();
    ScCellKeywordHashMap::iterator itr = maStringNameMap.find(rKey);

    if ( itr == itrEnd )
    {
        // New keyword.
        list<ScCellKeyword> aList;
        aList.push_back(aKeyItem);
        maStringNameMap.insert( ScCellKeywordHashMap::value_type(rKey, aList) );
    }
    else
        itr->second.push_back(aKeyItem);
}

void ScCellKeywordTranslator::addToMap(const TransItem* pItems, const Locale& rLocale)
{
    for (sal_uInt16 i = 0; pItems[i].from != NULL; ++i)
        addToMap(String::CreateFromAscii(pItems[i].from), pItems[i].to, rLocale, pItems[i].func);
}
<commit_msg>INTEGRATION: CWS celltrans02 (1.2.50); FILE MERGED 2007/09/06 17:50:33 kohei 1.2.50.5: minor tweak in the in-line comment. 2007/09/06 16:36:52 kohei 1.2.50.4: Added more in-line comment about the keyword file. 2007/09/06 16:23:30 kohei 1.2.50.3: use transliteration object to upcase the strings, instead of character classification object. 2007/09/06 03:19:23 kohei 1.2.50.2: added mutex guard to protect statically instantiated variables. 2007/09/06 03:02:22 kohei 1.2.50.1: added Hungarian keywords & made changes so that the keywords are stored in unicode instead of in ascii.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cellkeytranslator.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-01 14:21:26 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "cellkeytranslator.hxx"
#include "comphelper/processfactory.hxx"
#include "i18npool/mslangid.hxx"
#include "i18npool/lang.h"
#include "rtl/ustring.hxx"

#include <com/sun/star/i18n/TransliterationModules.hpp>

using ::com::sun::star::lang::Locale;
using ::com::sun::star::uno::Sequence;
using ::std::list;
using ::std::hash_map;
using ::rtl::OUString;

using namespace ::com::sun::star;

enum LocaleMatch
{
    LOCALE_MATCH_NONE = 0,
    LOCALE_MATCH_LANG,
    LOCALE_MATCH_LANG_COUNTRY,
    LOCALE_MATCH_ALL
};

static LocaleMatch lclLocaleCompare(const Locale& rLocale1, const Locale& rLocale2)
{
    LocaleMatch eMatchLevel = LOCALE_MATCH_NONE;
    if ( !rLocale1.Language.compareTo(rLocale1.Language) )
        eMatchLevel = LOCALE_MATCH_LANG;
    else
        return eMatchLevel;

    if ( !rLocale1.Country.compareTo(rLocale2.Country) )
        eMatchLevel = LOCALE_MATCH_LANG_COUNTRY;
    else
        return eMatchLevel;

    if ( !rLocale1.Variant.compareTo(rLocale2.Variant) )
        eMatchLevel = LOCALE_MATCH_ALL;

    return eMatchLevel;
}

ScCellKeyword::ScCellKeyword(const sal_Char* pName, OpCode eOpCode, const Locale& rLocale) :
    mpName(pName),
    meOpCode(eOpCode),
    mrLocale(rLocale)
{
}

::std::auto_ptr<ScCellKeywordTranslator> ScCellKeywordTranslator::spInstance(NULL);

static void lclMatchKeyword(String& rName, const ScCellKeywordHashMap& aMap,
                            OpCode eOpCode = ocNone, const Locale* pLocale = NULL)
{
    ScCellKeywordHashMap::const_iterator itrEnd = aMap.end();
    ScCellKeywordHashMap::const_iterator itr = aMap.find(rName);

    if ( itr == itrEnd || itr->second.empty() )
        // No candidate strings exist.  Bail out.
        return;

    if ( eOpCode == ocNone && !pLocale )
    {
        // Since no locale nor opcode matching is needed, simply return
        // the first item on the list.
        rName = String::CreateFromAscii( itr->second.front().mpName );
        return;
    }

    const sal_Char* aBestMatchName = itr->second.front().mpName;
    LocaleMatch eLocaleMatchLevel = LOCALE_MATCH_NONE;
    bool bOpCodeMatched = false;

    list<ScCellKeyword>::const_iterator itrListEnd = itr->second.end();
    list<ScCellKeyword>::const_iterator itrList = itr->second.begin();
    for ( ; itrList != itrListEnd; ++itrList )
    {
        if ( eOpCode != ocNone && pLocale )
        {
            if ( itrList->meOpCode == eOpCode )
            {
                LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
                if ( eLevel == LOCALE_MATCH_ALL )
                {
                    // Name with matching opcode and locale found.
                    rName = String::CreateFromAscii( itrList->mpName );
                    return;
                }
                else if ( eLevel > eLocaleMatchLevel )
                {
                    // Name with a better matching locale.
                    eLocaleMatchLevel = eLevel;
                    aBestMatchName = itrList->mpName;
                }
                else if ( !bOpCodeMatched )
                    // At least the opcode matches.
                    aBestMatchName = itrList->mpName;

                bOpCodeMatched = true;
            }
        }
        else if ( eOpCode != ocNone && !pLocale )
        {
            if ( itrList->meOpCode == eOpCode )
            {
                // Name with a matching opcode preferred.
                rName = String::CreateFromAscii( itrList->mpName );
                return;
            }
        }
        else if ( !eOpCode && pLocale )
        {
            LocaleMatch eLevel = lclLocaleCompare(itrList->mrLocale, *pLocale);
            if ( eLevel == LOCALE_MATCH_ALL )
            {
                // Name with matching locale preferred.
                rName = String::CreateFromAscii( itrList->mpName );
                return;
            }
            else if ( eLevel > eLocaleMatchLevel )
            {
                // Name with a better matching locale.
                eLocaleMatchLevel = eLevel;
                aBestMatchName = itrList->mpName;
            }
        }
    }

    // No preferred strings found.  Return the best matching name.
    rName = String::CreateFromAscii(aBestMatchName);
}

void ScCellKeywordTranslator::transKeyword(String& rName, const Locale* pLocale, OpCode eOpCode)
{
    if ( !spInstance.get() )
        spInstance.reset( new ScCellKeywordTranslator );

    LanguageType eLang = pLocale ? MsLangId::convertLocaleToLanguageWithFallback(*pLocale) : LANGUAGE_SYSTEM;
    Sequence<sal_Int32> aOffsets;
    rName = spInstance->maTransWrapper.transliterate(rName, eLang, 0, rName.Len(), &aOffsets);
    lclMatchKeyword(rName, spInstance->maStringNameMap, eOpCode, pLocale);
}

ScCellKeywordTranslator::ScCellKeywordTranslator() :
    maTransWrapper( ::comphelper::getProcessServiceFactory(),
                    i18n::TransliterationModules_LOWERCASE_UPPERCASE )
{
    init();
}

ScCellKeywordTranslator::~ScCellKeywordTranslator()
{
}

struct TransItem
{
    const sal_Unicode*  from;
    const sal_Char*     to;
    OpCode              func;
};

void ScCellKeywordTranslator::init()
{
    ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );

    // The file below has been autogenerated by sc/workben/celltrans/parse.py.
    // To add new locale keywords, edit sc/workben/celltrans/keywords_utf16.txt
    // and re-run the parse.py script.
    //
    // All keywords must be uppercase, and the mapping must be from the
    // localized keyword to the English keyword.
    //
    // Make sure that the original keyword file (keywords_utf16.txt) is
    // encoded in UCS-2/UTF-16!

    #include "cellkeywords.inl"
}

void ScCellKeywordTranslator::addToMap(const String& rKey, const sal_Char* pName, const Locale& rLocale, OpCode eOpCode)
{
    ScCellKeyword aKeyItem( pName, eOpCode, rLocale );

    ScCellKeywordHashMap::iterator itrEnd = maStringNameMap.end();
    ScCellKeywordHashMap::iterator itr = maStringNameMap.find(rKey);

    if ( itr == itrEnd )
    {
        // New keyword.
        list<ScCellKeyword> aList;
        aList.push_back(aKeyItem);
        maStringNameMap.insert( ScCellKeywordHashMap::value_type(rKey, aList) );
    }
    else
        itr->second.push_back(aKeyItem);
}

void ScCellKeywordTranslator::addToMap(const TransItem* pItems, const Locale& rLocale)
{
    for (sal_uInt16 i = 0; pItems[i].from != NULL; ++i)
        addToMap(String(pItems[i].from), pItems[i].to, rLocale, pItems[i].func);
}
<|endoftext|>


<commit_before><commit_msg>fdo #50343: Fixed crash on xlsx import of file with array formula<commit_after><|endoftext|>


<commit_before><commit_msg>improve conditional formatting height calculations.<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/.
 */

#include "condformatmgr.hxx"
#include "scresid.hxx"
#include "globstr.hrc"
#include "condformatdlg.hxx"
#include <vcl/msgbox.hxx>
#include "document.hxx"

ScCondFormatManagerWindow::ScCondFormatManagerWindow(SvSimpleTableContainer& rParent,
    ScDocument* pDoc, ScConditionalFormatList* pFormatList)
    : SvSimpleTable(rParent, WB_HSCROLL | WB_SORT | WB_TABSTOP)
    , mpDoc(pDoc)
    , mpFormatList(pFormatList)
{
    OUString aConditionStr(ScGlobal::GetRscString(STR_HEADER_COND));
    OUString aRangeStr(ScGlobal::GetRscString(STR_HEADER_RANGE));

    OUStringBuffer sHeader;
    sHeader.append(aRangeStr).append("\t").append(aConditionStr);
    InsertHeaderEntry(sHeader.makeStringAndClear(), HEADERBAR_APPEND, HIB_LEFT | HIB_VCENTER);
    setColSizes();

    Init();
    Show();
    SetSelectionMode(MULTIPLE_SELECTION);
}

OUString ScCondFormatManagerWindow::createEntryString(const ScConditionalFormat& rFormat)
{
    ScRangeList aRange = rFormat.GetRange();
    OUString aStr;
    aRange.Format(aStr, SCA_VALID, mpDoc, mpDoc->GetAddressConvention());
    aStr += "\t";
    aStr += ScCondFormatHelper::GetExpression(rFormat, aRange.GetTopLeftCorner());
    return aStr;
}

void ScCondFormatManagerWindow::Init()
{
    SetUpdateMode(false);

    for(ScConditionalFormatList::iterator itr = mpFormatList->begin(); itr != mpFormatList->end(); ++itr)
    {
        SvTreeListEntry* pEntry = InsertEntryToColumn( createEntryString(*itr), TREELIST_APPEND, 0xffff );
        maMapLBoxEntryToCondIndex.insert(std::pair<SvTreeListEntry*,sal_Int32>(pEntry,itr->GetKey()));
    }

    SetUpdateMode(true);

    if (mpFormatList->size())
        SelectRow(0);
}

void ScCondFormatManagerWindow::Resize()
{
    SvSimpleTable::Resize();
    if (GetParentDialog()->isCalculatingInitialLayoutSize())
        setColSizes();
}

void ScCondFormatManagerWindow::DeleteSelection()
{
    if(GetSelectionCount())
    {
        for(SvTreeListEntry* pEntry = FirstSelected(); pEntry != NULL; pEntry = NextSelected(pEntry))
        {
            sal_Int32 nIndex = maMapLBoxEntryToCondIndex.find(pEntry)->second;
            mpFormatList->erase(nIndex);
        }
        RemoveSelection();
    }
}

ScConditionalFormat* ScCondFormatManagerWindow::GetSelection()
{
    SvTreeListEntry* pEntry = FirstSelected();
    if(!pEntry)
        return NULL;

    sal_Int32 nIndex = maMapLBoxEntryToCondIndex.find(pEntry)->second;
    return mpFormatList->GetFormat(nIndex);
}

void ScCondFormatManagerWindow::Update()
{
    Clear();
    maMapLBoxEntryToCondIndex.clear();
    Init();
}

void ScCondFormatManagerWindow::setColSizes()
{
    HeaderBar &rBar = GetTheHeaderBar();
    if (rBar.GetItemCount() < 2)
        return;
    long aStaticTabs[]= { 2, 0, 0 };
    aStaticTabs[2] = rBar.GetSizePixel().Width() / 2;
    SvSimpleTable::SetTabs(aStaticTabs, MAP_PIXEL);
}

ScCondFormatManagerDlg::ScCondFormatManagerDlg(vcl::Window* pParent, ScDocument* pDoc, const ScConditionalFormatList* pFormatList, const ScAddress& rPos):
    ModalDialog(pParent, "CondFormatManager", "modules/scalc/ui/condformatmanager.ui"),
    mpFormatList( pFormatList ? new ScConditionalFormatList(*pFormatList) : NULL),
    mpDoc(pDoc),
    maPos(rPos),
    mbModified(false)
{
    SvSimpleTableContainer *pContainer = get<SvSimpleTableContainer>("CONTAINER");
    Size aSize(LogicToPixel(Size(290, 220), MAP_APPFONT));
    pContainer->set_width_request(aSize.Width());
    pContainer->set_height_request(aSize.Height());
    m_pCtrlManager = new ScCondFormatManagerWindow(*pContainer, mpDoc, mpFormatList);
    get(m_pBtnAdd, "add");
    get(m_pBtnRemove, "remove");
    get(m_pBtnEdit, "edit");

    m_pBtnRemove->SetClickHdl(LINK(this, ScCondFormatManagerDlg, RemoveBtnHdl));
    m_pBtnEdit->SetClickHdl(LINK(this, ScCondFormatManagerDlg, EditBtnHdl));
    m_pBtnAdd->SetClickHdl(LINK(this, ScCondFormatManagerDlg, AddBtnHdl));
    m_pCtrlManager->SetDoubleClickHdl(LINK(this, ScCondFormatManagerDlg, EditBtnHdl));
}

ScCondFormatManagerDlg::~ScCondFormatManagerDlg()
{
    delete m_pCtrlManager;
    delete mpFormatList;
}

bool ScCondFormatManagerDlg::IsInRefMode() const
{
    return true;
}

ScConditionalFormatList* ScCondFormatManagerDlg::GetConditionalFormatList()
{
    ScConditionalFormatList* pList = mpFormatList;
    mpFormatList = NULL;
    return pList;
}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, RemoveBtnHdl)
{
    m_pCtrlManager->DeleteSelection();
    mbModified = true;
    return 0;
}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, EditBtnHdl)
{
    ScConditionalFormat* pFormat = m_pCtrlManager->GetSelection();

    if(!pFormat)
        return 0;

    sal_uInt16 nId = 1;
    ScModule* pScMod = SC_MOD();
    pScMod->SetRefDialog( nId, true );
    boost::scoped_ptr<ScCondFormatDlg> pDlg(new ScCondFormatDlg(this, mpDoc, pFormat, pFormat->GetRange(),
                                               pFormat->GetRange().GetTopLeftCorner(), condformat::dialog::NONE));
    Show(false, 0);
    if(pDlg->Execute() == RET_OK)
    {
        sal_Int32 nKey = pFormat->GetKey();
        mpFormatList->erase(nKey);
        ScConditionalFormat* pNewFormat = pDlg->GetConditionalFormat();
        if(pNewFormat)
        {
            pNewFormat->SetKey(nKey);
            mpFormatList->InsertNew(pNewFormat);
        }

        m_pCtrlManager->Update();
        mbModified = true;
    }
    Show(true, 0);

    pScMod->SetRefDialog( nId, false );

    return 0;
}

namespace {

sal_uInt32 FindKey(ScConditionalFormatList* pFormatList)
{
    sal_uInt32 nKey = 0;
    for(ScConditionalFormatList::const_iterator itr = pFormatList->begin(), itrEnd = pFormatList->end();
            itr != itrEnd; ++itr)
    {
        if(itr->GetKey() > nKey)
            nKey = itr->GetKey();
    }

    return nKey + 1;
}

}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, AddBtnHdl)
{
    sal_uInt16 nId = 1;
    ScModule* pScMod = SC_MOD();
    pScMod->SetRefDialog( nId, true );
    boost::scoped_ptr<ScCondFormatDlg> pDlg(new ScCondFormatDlg(this, mpDoc, NULL, ScRangeList(),
                                               maPos, condformat::dialog::CONDITION));
    Show(false, 0);
    if(pDlg->Execute() == RET_OK)
    {
        ScConditionalFormat* pNewFormat = pDlg->GetConditionalFormat();
        if(pNewFormat)
        {
            mpFormatList->InsertNew(pNewFormat);
            pNewFormat->SetKey(FindKey(mpFormatList));
            m_pCtrlManager->Update();

            mbModified = true;
        }
    }
    Show(true, 0);
    pScMod->SetRefDialog( nId, false );

    return 0;
}

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

#include "condformatmgr.hxx"
#include "scresid.hxx"
#include "globstr.hrc"
#include "condformatdlg.hxx"
#include <vcl/msgbox.hxx>
#include "document.hxx"

ScCondFormatManagerWindow::ScCondFormatManagerWindow(SvSimpleTableContainer& rParent,
    ScDocument* pDoc, ScConditionalFormatList* pFormatList)
    : SvSimpleTable(rParent, WB_HSCROLL | WB_SORT | WB_TABSTOP)
    , mpDoc(pDoc)
    , mpFormatList(pFormatList)
{
    OUString aConditionStr(ScGlobal::GetRscString(STR_HEADER_COND));
    OUString aRangeStr(ScGlobal::GetRscString(STR_HEADER_RANGE));

    OUStringBuffer sHeader;
    sHeader.append(aRangeStr).append("\t").append(aConditionStr);
    InsertHeaderEntry(sHeader.makeStringAndClear(), HEADERBAR_APPEND, HIB_LEFT | HIB_VCENTER);
    setColSizes();

    Init();
    Show();
    SetSelectionMode(MULTIPLE_SELECTION);
}

OUString ScCondFormatManagerWindow::createEntryString(const ScConditionalFormat& rFormat)
{
    ScRangeList aRange = rFormat.GetRange();
    OUString aStr;
    aRange.Format(aStr, SCA_VALID, mpDoc, mpDoc->GetAddressConvention());
    aStr += "\t";
    aStr += ScCondFormatHelper::GetExpression(rFormat, aRange.GetTopLeftCorner());
    return aStr;
}

void ScCondFormatManagerWindow::Init()
{
    SetUpdateMode(false);

    if (mpFormatList)
    {
        for(ScConditionalFormatList::iterator itr = mpFormatList->begin(); itr != mpFormatList->end(); ++itr)
        {
            SvTreeListEntry* pEntry = InsertEntryToColumn( createEntryString(*itr), TREELIST_APPEND, 0xffff );
            maMapLBoxEntryToCondIndex.insert(std::pair<SvTreeListEntry*,sal_Int32>(pEntry,itr->GetKey()));
        }
    }

    SetUpdateMode(true);

    if (mpFormatList && mpFormatList->size())
        SelectRow(0);
}

void ScCondFormatManagerWindow::Resize()
{
    SvSimpleTable::Resize();
    if (GetParentDialog()->isCalculatingInitialLayoutSize())
        setColSizes();
}

void ScCondFormatManagerWindow::DeleteSelection()
{
    if(GetSelectionCount())
    {
        for(SvTreeListEntry* pEntry = FirstSelected(); pEntry != NULL; pEntry = NextSelected(pEntry))
        {
            sal_Int32 nIndex = maMapLBoxEntryToCondIndex.find(pEntry)->second;
            mpFormatList->erase(nIndex);
        }
        RemoveSelection();
    }
}

ScConditionalFormat* ScCondFormatManagerWindow::GetSelection()
{
    SvTreeListEntry* pEntry = FirstSelected();
    if(!pEntry)
        return NULL;

    sal_Int32 nIndex = maMapLBoxEntryToCondIndex.find(pEntry)->second;
    return mpFormatList->GetFormat(nIndex);
}

void ScCondFormatManagerWindow::Update()
{
    Clear();
    maMapLBoxEntryToCondIndex.clear();
    Init();
}

void ScCondFormatManagerWindow::setColSizes()
{
    HeaderBar &rBar = GetTheHeaderBar();
    if (rBar.GetItemCount() < 2)
        return;
    long aStaticTabs[]= { 2, 0, 0 };
    aStaticTabs[2] = rBar.GetSizePixel().Width() / 2;
    SvSimpleTable::SetTabs(aStaticTabs, MAP_PIXEL);
}

ScCondFormatManagerDlg::ScCondFormatManagerDlg(vcl::Window* pParent, ScDocument* pDoc, const ScConditionalFormatList* pFormatList, const ScAddress& rPos):
    ModalDialog(pParent, "CondFormatManager", "modules/scalc/ui/condformatmanager.ui"),
    mpFormatList( pFormatList ? new ScConditionalFormatList(*pFormatList) : NULL),
    mpDoc(pDoc),
    maPos(rPos),
    mbModified(false)
{
    SvSimpleTableContainer *pContainer = get<SvSimpleTableContainer>("CONTAINER");
    Size aSize(LogicToPixel(Size(290, 220), MAP_APPFONT));
    pContainer->set_width_request(aSize.Width());
    pContainer->set_height_request(aSize.Height());
    m_pCtrlManager = new ScCondFormatManagerWindow(*pContainer, mpDoc, mpFormatList);
    get(m_pBtnAdd, "add");
    get(m_pBtnRemove, "remove");
    get(m_pBtnEdit, "edit");

    m_pBtnRemove->SetClickHdl(LINK(this, ScCondFormatManagerDlg, RemoveBtnHdl));
    m_pBtnEdit->SetClickHdl(LINK(this, ScCondFormatManagerDlg, EditBtnHdl));
    m_pBtnAdd->SetClickHdl(LINK(this, ScCondFormatManagerDlg, AddBtnHdl));
    m_pCtrlManager->SetDoubleClickHdl(LINK(this, ScCondFormatManagerDlg, EditBtnHdl));
}

ScCondFormatManagerDlg::~ScCondFormatManagerDlg()
{
    delete m_pCtrlManager;
    delete mpFormatList;
}

bool ScCondFormatManagerDlg::IsInRefMode() const
{
    return true;
}

ScConditionalFormatList* ScCondFormatManagerDlg::GetConditionalFormatList()
{
    ScConditionalFormatList* pList = mpFormatList;
    mpFormatList = NULL;
    return pList;
}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, RemoveBtnHdl)
{
    m_pCtrlManager->DeleteSelection();
    mbModified = true;
    return 0;
}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, EditBtnHdl)
{
    ScConditionalFormat* pFormat = m_pCtrlManager->GetSelection();

    if(!pFormat)
        return 0;

    sal_uInt16 nId = 1;
    ScModule* pScMod = SC_MOD();
    pScMod->SetRefDialog( nId, true );
    boost::scoped_ptr<ScCondFormatDlg> pDlg(new ScCondFormatDlg(this, mpDoc, pFormat, pFormat->GetRange(),
                                               pFormat->GetRange().GetTopLeftCorner(), condformat::dialog::NONE));
    Show(false, 0);
    if(pDlg->Execute() == RET_OK)
    {
        sal_Int32 nKey = pFormat->GetKey();
        mpFormatList->erase(nKey);
        ScConditionalFormat* pNewFormat = pDlg->GetConditionalFormat();
        if(pNewFormat)
        {
            pNewFormat->SetKey(nKey);
            mpFormatList->InsertNew(pNewFormat);
        }

        m_pCtrlManager->Update();
        mbModified = true;
    }
    Show(true, 0);

    pScMod->SetRefDialog( nId, false );

    return 0;
}

namespace {

sal_uInt32 FindKey(ScConditionalFormatList* pFormatList)
{
    sal_uInt32 nKey = 0;
    for(ScConditionalFormatList::const_iterator itr = pFormatList->begin(), itrEnd = pFormatList->end();
            itr != itrEnd; ++itr)
    {
        if(itr->GetKey() > nKey)
            nKey = itr->GetKey();
    }

    return nKey + 1;
}

}

IMPL_LINK_NOARG(ScCondFormatManagerDlg, AddBtnHdl)
{
    sal_uInt16 nId = 1;
    ScModule* pScMod = SC_MOD();
    pScMod->SetRefDialog( nId, true );
    boost::scoped_ptr<ScCondFormatDlg> pDlg(new ScCondFormatDlg(this, mpDoc, NULL, ScRangeList(),
                                               maPos, condformat::dialog::CONDITION));
    Show(false, 0);
    if(pDlg->Execute() == RET_OK)
    {
        ScConditionalFormat* pNewFormat = pDlg->GetConditionalFormat();
        if(pNewFormat)
        {
            mpFormatList->InsertNew(pNewFormat);
            pNewFormat->SetKey(FindKey(mpFormatList));
            m_pCtrlManager->Update();

            mbModified = true;
        }
    }
    Show(true, 0);
    pScMod->SetRefDialog( nId, false );

    return 0;
}

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


<commit_before>// SafeArryGUID.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <objbase.h>
#include <string>
#include<atlsafe.h>
#include<iostream>
using namespace std;

string GuidToString(const GUID &guid)
{
	char buf[64] = { 0 };
	sprintf_s(buf, sizeof(buf), "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
		guid.Data1, guid.Data2, guid.Data3,
		guid.Data4[0], guid.Data4[1],
		guid.Data4[2], guid.Data4[3],
		guid.Data4[4], guid.Data4[5],
		guid.Data4[6], guid.Data4[7]);
	return string(buf);
}

void Put1GuidInSafeArry()
{
	GUID guid;
	CoCreateGuid(&guid);

	auto guidStri = GuidToString(guid);

	cout << guidStri << endl;

	//TODO... put the guid into safearry..
	SAFEARRAY* p_safe_arry;
	SAFEARRAYBOUND safe_arry_bound[2] = { 0 };
	auto guidsize = sizeof(GUID);
	safe_arry_bound[0].cElements = guidsize;
	safe_arry_bound[0].lLbound = 0;
	safe_arry_bound[1].cElements = guidsize;
	safe_arry_bound[1].lLbound = 0;

	p_safe_arry = SafeArrayCreate(VT_ARRAY, 1, safe_arry_bound);
	auto pnData = reinterpret_cast<char*>(p_safe_arry->pvData);
	memcpy_s(pnData, guidsize, guidStri.c_str(), guidsize);
	//TODO...
	//do something..
	SafeArrayDestroy(p_safe_arry);
}

void Put2GuidInSafeArry()
{
	GUID guid, guid2;
	CoCreateGuid(&guid);
	CoCreateGuid(&guid2);

	//TODO... put the guid into safearry..
	SAFEARRAY* p_safe_arry;
	SAFEARRAYBOUND safe_arry_bound[2] = { 0 };
	safe_arry_bound[0].cElements = 2;
	safe_arry_bound[0].lLbound = 0;
	safe_arry_bound[1].cElements = 16;
	safe_arry_bound[1].lLbound = 0;

	p_safe_arry = SafeArrayCreate(VT_CLSID, 2, safe_arry_bound);
	auto pnData = reinterpret_cast<GUID*>(p_safe_arry->pvData);
	pnData[0] = guid;
	pnData[1] = guid2;
	//TODO...
	//do something..
	//TODO...

	SafeArrayDestroy(p_safe_arry);
}

void Put1GuidInSafeArryByStack()
{
	GUID guid;

	//TODO... put the guid into safearry..
	SAFEARRAY* pArray = nullptr;
	auto hr = SafeArrayAllocDescriptorEx(VT_CLSID, 1, &pArray);
	pArray->cbElements = sizeof(GUID);
	pArray->rgsabound[0].cElements = 1;
	pArray->rgsabound[0].lLbound = 16;
	pArray->pvData = &guid;
	pArray->fFeatures = FADF_AUTO;
	//_bstr_t bstr;
}

void CComSafeArrayGUID()
{
	//CComSafeArray<GUID> comsafeguid(10);
}

void LearnSafeArray()
{
	VARIANT var_Chunk;
	SAFEARRAY *psa;
	SAFEARRAYBOUND rgsabund[1];

	rgsabund[0].cElements = sizeof(GUID);
	rgsabund[0].lLbound = 0;

	//psa = SafeArrayCreate(VT_UI1,1,rgsabund);

	var_Chunk.vt = VT_RECORD | VT_ARRAY;
	//var_Chunk.parray =
}

int _tmain(int argc, _TCHAR* argv[])
{
	Put1GuidInSafeArry();
	Put2GuidInSafeArry();
	Put1GuidInSafeArryByStack();
	return 0;
}<commit_msg>update test<commit_after>// SafeArryGUID.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <objbase.h>
#include <string>
//#include<atlsafe.h>
//#include<atlcomcli.h>
#include<iostream>
using namespace std;

string GuidToString(const GUID &guid)
{
	char buf[64] = { 0 };
	sprintf_s(buf, sizeof(buf), "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
		guid.Data1, guid.Data2, guid.Data3,
		guid.Data4[0], guid.Data4[1],
		guid.Data4[2], guid.Data4[3],
		guid.Data4[4], guid.Data4[5],
		guid.Data4[6], guid.Data4[7]);
	return string(buf);
}

void Put1GuidInSafeArry()
{
	GUID guid;
	CoCreateGuid(&guid);

	auto guidStri = GuidToString(guid);

	cout << guidStri << endl;

	//TODO... put the guid into safearry..
	SAFEARRAY* p_safe_arry;
	SAFEARRAYBOUND safe_arry_bound[2] = { 0 };
	auto guidsize = sizeof(GUID);
	safe_arry_bound[0].cElements = guidsize;
	safe_arry_bound[0].lLbound = 0;
	safe_arry_bound[1].cElements = guidsize;
	safe_arry_bound[1].lLbound = 0;

	p_safe_arry = SafeArrayCreate(VT_ARRAY, 1, safe_arry_bound);
	auto pnData = reinterpret_cast<char*>(p_safe_arry->pvData);
	memcpy_s(pnData, guidsize, guidStri.c_str(), guidsize);
	//TODO...
	//do something..
	SafeArrayDestroy(p_safe_arry);
}

void Put2GuidInSafeArry()
{
	GUID guid, guid2;
	CoCreateGuid(&guid);
	CoCreateGuid(&guid2);

	//TODO... put the guid into safearry..
	SAFEARRAY* p_safe_arry;
	SAFEARRAYBOUND safe_arry_bound[2] = { 0 };
	safe_arry_bound[0].cElements = 2;
	safe_arry_bound[0].lLbound = 0;
	safe_arry_bound[1].cElements = 16;
	safe_arry_bound[1].lLbound = 0;

	p_safe_arry = SafeArrayCreate(VT_CLSID, 2, safe_arry_bound);
	auto pnData = reinterpret_cast<GUID*>(p_safe_arry->pvData);
	pnData[0] = guid;
	pnData[1] = guid2;
	//TODO...
	//do something..
	//TODO...

	SafeArrayDestroy(p_safe_arry);
}

void Put1GuidInSafeArryByStack()
{
	GUID guid;

	//TODO... put the guid into safearry..
	SAFEARRAY* pArray = nullptr;
	auto hr = SafeArrayAllocDescriptorEx(VT_CLSID, 1, &pArray);
	pArray->cbElements = sizeof(GUID);
	pArray->rgsabound[0].cElements = 1;
	pArray->rgsabound[0].lLbound = 16;
	pArray->pvData = &guid;
	pArray->fFeatures = FADF_AUTO;
	//_bstr_t bstr;
}

void CComSafeArrayGUID()
{
	//CComSafeArray<GUID> comsafeguid(10);
}

void LearnSafeArray()
{
	VARIANT var_Chunk;
	SAFEARRAY *psa;
	SAFEARRAYBOUND rgsabund[1];

	rgsabund[0].cElements = sizeof(GUID);
	rgsabund[0].lLbound = 0;

	//psa = SafeArrayCreate(VT_UI1,1,rgsabund);

	var_Chunk.vt = VT_RECORD | VT_ARRAY;
	//var_Chunk.parray =
}

void TestSafeArry()
{
	CComSafeArray<GUID> guid_Array;
	//GUID guid, guid2;
	//CoCreateGuid(&guid);
	//CoCreateGuid(&guid2);
	//guid_Array.Add(guid);
	//guid_Array.Add(guid2);

	//auto count = guid_Array.GetCount();
	//auto demention = guid_Array.GetDimensions();
	//auto upperbound = guid_Array.GetUpperBound();
	//auto p_safeArry = &guid_Array;
	//GUID guid3;
	//CoCreateGuid(&guid3);
	//p_safeArry->SetAt(1, guid3);
}

int _tmain(int argc, _TCHAR* argv[])
{
	TestSafeArry();
	Put1GuidInSafeArry();
	Put2GuidInSafeArry();
	Put1GuidInSafeArryByStack();
	return 0;
}<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "../../vendor/catch/catch.hpp"

#include "thread_utility.hpp"
#include "version_monitor.hpp"

TEST_CASE("initialize") {
  krbn::thread_utility::register_main_thread();
}

TEST_CASE("version_monitor") {
  system("rm -rf target");
  system("mkdir -p target/sub/");
  system("echo 1.0.0 > target/sub/version");

  {
    krbn::version_monitor version_monitor("target/sub/version");

    std::string last_changed_version;

    version_monitor.changed.connect([&](auto&& version) {
      last_changed_version = version;
    });

    version_monitor.start();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // Update version
    // ========================================

    last_changed_version.clear();

    system("echo 1.1.0 > target/sub/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.1.0");

    // ========================================
    // The callback is not called if the file contents is not changed.
    // ========================================

    last_changed_version.clear();

    system("touch target/sub/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // `manual_check` does not invoke callback if the version file is not actually changed.
    // ========================================

    last_changed_version.clear();

    version_monitor.manual_check();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // Self update is ignored by `kFSEventStreamCreateFlagIgnoreSelf`
    // ========================================

    last_changed_version.clear();

    {
      std::ofstream("target/sub/version") << "1.2.0";
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // `manual_check`
    // ========================================

    last_changed_version.clear();

    version_monitor.manual_check();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.2.0");

    // ========================================
    // Update version again
    // ========================================

    last_changed_version.clear();

    system("echo 1.3.0 > target/sub/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.3.0");
  }
}
<commit_msg>update tests<commit_after>#define CATCH_CONFIG_MAIN
#include "../../vendor/catch/catch.hpp"

#include "thread_utility.hpp"
#include "version_monitor.hpp"

TEST_CASE("initialize") {
  krbn::thread_utility::register_main_thread();
}

TEST_CASE("version_monitor") {
  system("rm -rf target");
  system("mkdir -p target");
  system("echo 1.0.0 > target/version");

  {
    krbn::version_monitor version_monitor("target/version");

    std::string last_changed_version;

    version_monitor.changed.connect([&](auto&& version) {
      last_changed_version = version;
    });

    version_monitor.start();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // Update version
    // ========================================

    last_changed_version.clear();

    system("echo 1.1.0 > target/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.1.0");

    // ========================================
    // The callback is not called if the file contents is not changed.
    // ========================================

    last_changed_version.clear();

    system("touch target/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // `manual_check` does not invoke callback if the version file is not actually changed.
    // ========================================

    last_changed_version.clear();

    version_monitor.manual_check();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // Self update is ignored by `kFSEventStreamCreateFlagIgnoreSelf`
    // ========================================

    last_changed_version.clear();

    {
      std::ofstream("target/version") << "1.2.0";
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version.empty());

    // ========================================
    // `manual_check`
    // ========================================

    last_changed_version.clear();

    version_monitor.manual_check();

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.2.0");

    // ========================================
    // Update version again
    // ========================================

    last_changed_version.clear();

    system("echo 1.3.0 > target/version");

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    REQUIRE(last_changed_version == "1.3.0");
  }
}
<|endoftext|>


<commit_before>#include "config/Base.hh"

#include "containers/PointCloud.hh"

#include "distances/Euclidean.hh"

#include "filtrations/Data.hh"

#include "geometry/BruteForce.hh"
#include "geometry/RipsSkeleton.hh"

#include "tests/Base.hh"

#include "persistentHomology/Calculation.hh"

#include "topology/Simplex.hh"
#include "topology/SimplicialComplex.hh"

#include <vector>

using namespace aleph::geometry;
using namespace aleph::topology;
using namespace aleph;

template <class T> void test()
{
  ALEPH_TEST_BEGIN( "Point cloud loading" );

  using PointCloud = PointCloud<T>;
  using Distance   = aleph::distances::Euclidean<T>;

  PointCloud pointCloud = load<T>( CMAKE_SOURCE_DIR + std::string( "/tests/input/Iris_colon_separated.txt" ) );

  ALEPH_ASSERT_THROW( pointCloud.size()      == 150 );
  ALEPH_ASSERT_THROW( pointCloud.dimension() ==   4);

  ALEPH_TEST_END();

  ALEPH_TEST_BEGIN( "Rips skeleton calculation" );

  using Wrapper      = BruteForce<PointCloud, Distance>;
  using RipsSkeleton = RipsSkeleton<Wrapper>;

  Wrapper wrapper( pointCloud );
  RipsSkeleton ripsSkeleton;

  auto K = ripsSkeleton( wrapper, 1.0 );

  using Simplex = typename decltype(K)::ValueType;

  ALEPH_ASSERT_THROW( K.empty() == false );
  ALEPH_ASSERT_THROW( std::count_if( K.begin(), K.end(), [] ( const Simplex& s ) { return s.dimension() == 1; } ) != 0 );

  ALEPH_TEST_END();

  ALEPH_TEST_BEGIN( "Zero-dimensional persistent homology calculation" );

  K.sort( filtrations::Data<Simplex>() );

  auto diagrams = calculatePersistenceDiagrams( K );

  ALEPH_ASSERT_THROW( diagrams.empty() == false );

  auto diagram1 = diagrams.front();

  ALEPH_ASSERT_THROW( diagram1.empty() == false );
  ALEPH_ASSERT_THROW( diagram1.size()  == pointCloud.size() );

  ALEPH_TEST_END();
}

int main()
{
  test<float> ();
  test<double>();
}
<commit_msg>Extended test for connected component calculations<commit_after>#include "config/Base.hh"

#include "containers/PointCloud.hh"

#include "distances/Euclidean.hh"

#include "filtrations/Data.hh"

#include "geometry/BruteForce.hh"
#include "geometry/RipsSkeleton.hh"

#include "tests/Base.hh"

#include "persistentHomology/Calculation.hh"
#include "persistentHomology/ConnectedComponents.hh"

#include "topology/Simplex.hh"
#include "topology/SimplicialComplex.hh"

#include <vector>

using namespace aleph::geometry;
using namespace aleph::topology;
using namespace aleph;

template <class T> void test()
{
  ALEPH_TEST_BEGIN( "Point cloud loading" );

  using PointCloud = PointCloud<T>;
  using Distance   = aleph::distances::Euclidean<T>;

  PointCloud pointCloud = load<T>( CMAKE_SOURCE_DIR + std::string( "/tests/input/Iris_colon_separated.txt" ) );

  ALEPH_ASSERT_THROW( pointCloud.size()      == 150 );
  ALEPH_ASSERT_THROW( pointCloud.dimension() ==   4);

  ALEPH_TEST_END();

  ALEPH_TEST_BEGIN( "Rips skeleton calculation" );

  using Wrapper      = BruteForce<PointCloud, Distance>;
  using RipsSkeleton = RipsSkeleton<Wrapper>;

  Wrapper wrapper( pointCloud );
  RipsSkeleton ripsSkeleton;

  auto K = ripsSkeleton( wrapper, 1.0 );

  using Simplex = typename decltype(K)::ValueType;

  ALEPH_ASSERT_THROW( K.empty() == false );
  ALEPH_ASSERT_THROW( std::count_if( K.begin(), K.end(), [] ( const Simplex& s ) { return s.dimension() == 1; } ) != 0 );

  ALEPH_TEST_END();

  ALEPH_TEST_BEGIN( "Zero-dimensional persistent homology calculation" );

  K.sort( filtrations::Data<Simplex>() );

  auto diagrams = calculatePersistenceDiagrams( K );
  auto diagram2 = calculateZeroDimensionalPersistenceDiagram( K );

  ALEPH_ASSERT_THROW( diagrams.empty() == false );

  auto diagram1 = diagrams.front();

  ALEPH_ASSERT_THROW( diagram1.empty() == false );
  ALEPH_ASSERT_THROW( diagram1.size()  == pointCloud.size() );
  ALEPH_ASSERT_THROW( diagram2.empty() == false );
  ALEPH_ASSERT_THROW( diagram1.size()  == diagram2.size() );

  ALEPH_TEST_END();
}

int main()
{
  test<float> ();
  test<double>();
}
<|endoftext|>


<commit_before>#pragma once

#include "iokit_utility.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <mach/mach_time.h>
#include <optional>
#include <pqrs/dispatcher.hpp>
#include <pqrs/osx/iokit_hid_device.hpp>
#include <pqrs/osx/iokit_hid_element.hpp>

namespace krbn {
class hid_keyboard_caps_lock_led_state_manager final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  hid_keyboard_caps_lock_led_state_manager(IOHIDDeviceRef device) : dispatcher_client(),
                                                                    device_(device),
                                                                    timer_(*this),
                                                                    started_(false) {
    if (device_) {
      pqrs::osx::iokit_hid_device hid_device(*device_);
      for (const auto& element : hid_device.make_elements()) {
        pqrs::osx::iokit_hid_element e(*element);

        if (e.get_usage_page() == pqrs::hid::usage_page::leds &&
            e.get_usage() == pqrs::hid::usage::led::caps_lock &&
            e.get_type() == pqrs::osx::iokit_hid_element_type::output) {
          logger::get_logger()->info(
              "caps lock is found on {0}",
              iokit_utility::make_device_name(*device_));

          element_ = e;
        }
      }
    }
  }

  ~hid_keyboard_caps_lock_led_state_manager(void) {
    detach_from_dispatcher([this] {
      timer_.stop();
    });
  }

  void set_state(std::optional<led_state> value) {
    std::lock_guard<std::mutex> lock(state_mutex_);

    // Skip if new state is same as the last state in order to avoid a possibility of infinite calling of set_state.
    if (state_ == value) {
      return;
    }

    state_ = value;

    enqueue_to_dispatcher([this] {
      update_caps_lock_led();
    });
  }

  void async_start(void) {
    enqueue_to_dispatcher([this] {
      started_ = true;

      timer_.start(
          [this] {
            update_caps_lock_led();
          },
          std::chrono::milliseconds(3000));
    });
  }

  void async_stop(void) {
    enqueue_to_dispatcher([this] {
      started_ = false;

      timer_.stop();
    });
  }

private:
  void update_caps_lock_led(void) const {
    if (!started_) {
      return;
    }

    // macOS 10.12 sometimes synchronize caps lock LED to internal keyboard caps lock state.
    // The behavior causes LED state mismatch because
    // the caps lock state of karabiner_grabber is independent from the hardware caps lock state.
    // Thus, we monitor the LED state and update it if needed.

    if (auto integer_value = make_integer_value()) {
      if (device_ && element_) {
        if (auto value = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault,
                                                          element_.get_raw_ptr(),
                                                          mach_absolute_time(),
                                                          *integer_value)) {
          IOHIDDeviceSetValue(*device_, element_.get_raw_ptr(), value);

          CFRelease(value);
        }
      }
    }
  }

  std::optional<CFIndex> make_integer_value(void) const {
    std::lock_guard<std::mutex> lock(state_mutex_);

    if (state_ && element_) {
      if (*state_ == led_state::on) {
        return element_.get_logical_max();
      } else {
        return element_.get_logical_min();
      }
    }

    return std::nullopt;
  }

  pqrs::cf::cf_ptr<IOHIDDeviceRef> device_;
  pqrs::osx::iokit_hid_element element_;
  std::optional<led_state> state_;
  mutable std::mutex state_mutex_;
  pqrs::dispatcher::extra::timer timer_;
  bool started_;
};
} // namespace krbn
<commit_msg>Improve caps lock led handling<commit_after>#pragma once

#include "iokit_utility.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <mach/mach_time.h>
#include <optional>
#include <pqrs/dispatcher.hpp>
#include <pqrs/osx/iokit_hid_device.hpp>
#include <pqrs/osx/iokit_hid_element.hpp>
#include <pqrs/osx/iokit_return.hpp>

namespace krbn {
class hid_keyboard_caps_lock_led_state_manager final : public pqrs::dispatcher::extra::dispatcher_client {
public:
  hid_keyboard_caps_lock_led_state_manager(IOHIDDeviceRef device) : dispatcher_client(),
                                                                    device_(device),
                                                                    timer_(*this),
                                                                    started_(false) {
    if (device_) {
      pqrs::osx::iokit_hid_device hid_device(*device_);
      for (const auto& element : hid_device.make_elements()) {
        pqrs::osx::iokit_hid_element e(*element);

        if (e.get_usage_page() == pqrs::hid::usage_page::leds &&
            e.get_usage() == pqrs::hid::usage::led::caps_lock &&
            e.get_type() == pqrs::osx::iokit_hid_element_type::output) {
          logger::get_logger()->info(
              "caps lock is found on {0}",
              iokit_utility::make_device_name(*device_));

          element_ = e;
        }
      }
    }
  }

  ~hid_keyboard_caps_lock_led_state_manager(void) {
    detach_from_dispatcher([this] {
      timer_.stop();
    });
  }

  void set_state(std::optional<led_state> value) {
    std::lock_guard<std::mutex> lock(state_mutex_);

    // Skip if new state is same as the last state in order to avoid a possibility of infinite calling of set_state.
    if (state_ == value) {
      return;
    }

    state_ = value;

    enqueue_to_dispatcher([this] {
      update_caps_lock_led();
    });
  }

  void async_start(void) {
    enqueue_to_dispatcher([this] {
      started_ = true;

      timer_.start(
          [this] {
            update_caps_lock_led();
          },
          std::chrono::milliseconds(3000));
    });
  }

  void async_stop(void) {
    enqueue_to_dispatcher([this] {
      started_ = false;

      timer_.stop();
    });
  }

private:
  void update_caps_lock_led(void) const {
    if (!started_) {
      return;
    }

    // macOS 10.12 sometimes synchronize caps lock LED to internal keyboard caps lock state.
    // The behavior causes LED state mismatch because
    // the caps lock state of karabiner_grabber is independent from the hardware caps lock state.
    // Thus, we monitor the LED state and update it if needed.

    if (auto integer_value = make_integer_value()) {
      if (device_ && element_) {
        if (auto value = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault,
                                                          element_.get_raw_ptr(),
                                                          mach_absolute_time(),
                                                          *integer_value)) {
          // We have to use asynchronous method in order to prevent deadlock.
          IOHIDDeviceSetValueWithCallback(
              *device_,
              element_.get_raw_ptr(),
              value,
              0.1,
              [](void* context, IOReturn result, void* sender, IOHIDValueRef value) {
                pqrs::osx::iokit_return r(result);
                if (!r) {
                  logger::get_logger()->warn("update_caps_lock_led is failed: {0}", r);
                }
              },
              nullptr);

          CFRelease(value);
        }
      }
    }
  }

  std::optional<CFIndex> make_integer_value(void) const {
    std::lock_guard<std::mutex> lock(state_mutex_);

    if (state_ && element_) {
      if (*state_ == led_state::on) {
        return element_.get_logical_max();
      } else {
        return element_.get_logical_min();
      }
    }

    return std::nullopt;
  }

  pqrs::cf::cf_ptr<IOHIDDeviceRef> device_;
  pqrs::osx::iokit_hid_element element_;
  std::optional<led_state> state_;
  mutable std::mutex state_mutex_;
  pqrs::dispatcher::extra::timer timer_;
  bool started_;
};
} // namespace krbn
<|endoftext|>


<commit_before>// RUN: %clangxx_asan -O %s -o %t && %run %t

#include <assert.h>
#include <stdio.h>
#include <sanitizer/asan_interface.h>

__attribute__((noinline))
void Throw() {
  int local;
  fprintf(stderr, "Throw:  %p\n", &local);
  throw 1;
}

__attribute__((noinline))
void ThrowAndCatch() {
  int local;
  try {
    Throw();
  } catch(...) {
    fprintf(stderr, "Catch:  %p\n", &local);
  }
}

void TestThrow() {
  char x[32];
  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
          __asan_address_is_poisoned(x + 32));
  assert(__asan_address_is_poisoned(x + 32));
  ThrowAndCatch();
  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
          __asan_address_is_poisoned(x + 32));
  // FIXME: Invert this assertion once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 32));
}

void TestThrowInline() {
  char x[32];
  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
          __asan_address_is_poisoned(x + 32));
  assert(__asan_address_is_poisoned(x + 32));
  try {
    Throw();
  } catch(...) {
    fprintf(stderr, "Catch\n");
  }
  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
          __asan_address_is_poisoned(x + 32));
  // FIXME: Invert this assertion once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 32));
}

int main(int argc, char **argv) {
  TestThrowInline();
  TestThrow();
}
<commit_msg>[asan] Fix test case failure on SystemZ<commit_after>// RUN: %clangxx_asan -O %s -o %t && %run %t

#include <assert.h>
#include <stdio.h>
#include <sanitizer/asan_interface.h>

__attribute__((noinline))
void Throw() {
  int local;
  fprintf(stderr, "Throw:  %p\n", &local);
  throw 1;
}

__attribute__((noinline))
void ThrowAndCatch() {
  int local;
  try {
    Throw();
  } catch(...) {
    fprintf(stderr, "Catch:  %p\n", &local);
  }
}

__attribute__((noinline))
void TestThrow() {
  char x[32];
  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
          __asan_address_is_poisoned(x + 32));
  assert(__asan_address_is_poisoned(x + 32));
  ThrowAndCatch();
  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
          __asan_address_is_poisoned(x + 32));
  // FIXME: Invert this assertion once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 32));
}

__attribute__((noinline))
void TestThrowInline() {
  char x[32];
  fprintf(stderr, "Before: %p poisoned: %d\n", &x,
          __asan_address_is_poisoned(x + 32));
  assert(__asan_address_is_poisoned(x + 32));
  try {
    Throw();
  } catch(...) {
    fprintf(stderr, "Catch\n");
  }
  fprintf(stderr, "After:  %p poisoned: %d\n",  &x,
          __asan_address_is_poisoned(x + 32));
  // FIXME: Invert this assertion once we fix
  // https://code.google.com/p/address-sanitizer/issues/detail?id=258
  // This assertion works only w/o UAR.
  if (!__asan_get_current_fake_stack())
    assert(!__asan_address_is_poisoned(x + 32));
}

int main(int argc, char **argv) {
  TestThrowInline();
  TestThrow();
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Antioch - A Gas Dynamics Thermochemistry Library
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-
//
// $Id$
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

#include "antioch_config.h"

#include <valarray>

#ifdef ANTIOCH_HAVE_EIGEN
#include "Eigen/Dense"
#endif

#ifdef ANTIOCH_HAVE_METAPHYSICL
#include "metaphysicl/numberarray.h"
#endif

// Declare metaprogramming overloads before they're used
#include "antioch/eigen_utils_decl.h"
#include "antioch/metaphysicl_utils_decl.h"
#include "antioch/valarray_utils_decl.h"

// C++
#include <cmath>
#include <iostream>
#include <limits>

// Antioch
#include "antioch/blottner_viscosity.h"

#include "antioch/eigen_utils.h"
#include "antioch/metaphysicl_utils.h"
#include "antioch/valarray_utils.h"

template <typename Scalar, typename PairScalars>
int test_viscosity( const PairScalars mu, const PairScalars mu_exact, const Scalar tol )
{
  int return_flag = 0;

  const PairScalars rel_error = std::abs( (mu - mu_exact)/mu_exact);

  if( Antioch::max(rel_error) > tol )
    {
      std::cerr << "Error: Mismatch in viscosity" << std::endl
		<< "mu(T)    = (" << mu[0] << ',' << mu[1] << ')' << std::endl
		<< "mu_exact = (" << mu_exact[0] << ',' << mu_exact[1] << ')' << std::endl
		<< "rel_error = (" << rel_error[0] << ',' << rel_error[1] << ')' << std::endl
		<< "tol = " << tol << std::endl;
      return_flag = 1;
    }

  return return_flag;
}

template <typename PairScalars>
int vectester(const PairScalars& example)
{
  typedef typename Antioch::value_type<PairScalars>::type Scalar;

  const Scalar a = 3.14e-3L;
  const Scalar b = 2.71e-2L;
  const Scalar c = 42.0e-5L;

  Antioch::BlottnerViscosity<Scalar> mu(a,b,c);

  std::cout << mu << std::endl;

  PairScalars T = example;
  T[0] = 1521.2L;
  T[1] = 1621.2L;

  // bc gives
  PairScalars mu_exact = example;
  mu_exact[0] = 0.1444222341677025337305172031086891L;
  mu_exact[1] = 0.1450979382180072302532592937776388L;

  int return_flag = 0;

  // How are we getting such high error in the long double case?
  const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 2;

  return_flag = test_viscosity( mu(T), mu_exact, tol );

  const Scalar a2 = 1e-3L;
  const Scalar b2 = 2e-2L;
  const Scalar c2 = 3e-5L;

  mu.reset_coeffs( a2, b2, c2 );

  // octave gives
  PairScalars mu_exact2 = example;
  mu_exact2[0] = .1221724955488799960527696821225472L;
  mu_exact2[1] = .1224428450807678499433510473203746L;

  return_flag = test_viscosity( mu(T), mu_exact2, tol );

  return return_flag;
}

int main()
{
  int returnval = 0;

  returnval = returnval ||
    vectester (std::valarray<float>(2));
  returnval = returnval ||
    vectester (std::valarray<double>(2));
  returnval = returnval ||
    vectester (std::valarray<long double>(2));
#ifdef ANTIOCH_HAVE_EIGEN
  returnval = returnval ||
    vectester (Eigen::Array2f());
  returnval = returnval ||
    vectester (Eigen::Array2d());
  returnval = returnval ||
    vectester (Eigen::Array<long double, 2, 1>());
#endif
#ifdef ANTIOCH_HAVE_METAPHYSICL
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, float> (0));
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, double> (0));
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, long double> (0));
#endif

  return returnval;
}
<commit_msg>[Antioch]: Forgot to remove now out-of-date comment.<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Antioch - A Gas Dynamics Thermochemistry Library
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-
//
// $Id$
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

#include "antioch_config.h"

#include <valarray>

#ifdef ANTIOCH_HAVE_EIGEN
#include "Eigen/Dense"
#endif

#ifdef ANTIOCH_HAVE_METAPHYSICL
#include "metaphysicl/numberarray.h"
#endif

// Declare metaprogramming overloads before they're used
#include "antioch/eigen_utils_decl.h"
#include "antioch/metaphysicl_utils_decl.h"
#include "antioch/valarray_utils_decl.h"

// C++
#include <cmath>
#include <iostream>
#include <limits>

// Antioch
#include "antioch/blottner_viscosity.h"

#include "antioch/eigen_utils.h"
#include "antioch/metaphysicl_utils.h"
#include "antioch/valarray_utils.h"

template <typename Scalar, typename PairScalars>
int test_viscosity( const PairScalars mu, const PairScalars mu_exact, const Scalar tol )
{
  int return_flag = 0;

  const PairScalars rel_error = std::abs( (mu - mu_exact)/mu_exact);

  if( Antioch::max(rel_error) > tol )
    {
      std::cerr << "Error: Mismatch in viscosity" << std::endl
		<< "mu(T)    = (" << mu[0] << ',' << mu[1] << ')' << std::endl
		<< "mu_exact = (" << mu_exact[0] << ',' << mu_exact[1] << ')' << std::endl
		<< "rel_error = (" << rel_error[0] << ',' << rel_error[1] << ')' << std::endl
		<< "tol = " << tol << std::endl;
      return_flag = 1;
    }

  return return_flag;
}

template <typename PairScalars>
int vectester(const PairScalars& example)
{
  typedef typename Antioch::value_type<PairScalars>::type Scalar;

  const Scalar a = 3.14e-3L;
  const Scalar b = 2.71e-2L;
  const Scalar c = 42.0e-5L;

  Antioch::BlottnerViscosity<Scalar> mu(a,b,c);

  std::cout << mu << std::endl;

  PairScalars T = example;
  T[0] = 1521.2L;
  T[1] = 1621.2L;

  // bc gives
  PairScalars mu_exact = example;
  mu_exact[0] = 0.1444222341677025337305172031086891L;
  mu_exact[1] = 0.1450979382180072302532592937776388L;

  int return_flag = 0;

  const Scalar tol = std::numeric_limits<Scalar>::epsilon() * 2;

  return_flag = test_viscosity( mu(T), mu_exact, tol );

  const Scalar a2 = 1e-3L;
  const Scalar b2 = 2e-2L;
  const Scalar c2 = 3e-5L;

  mu.reset_coeffs( a2, b2, c2 );

  // octave gives
  PairScalars mu_exact2 = example;
  mu_exact2[0] = .1221724955488799960527696821225472L;
  mu_exact2[1] = .1224428450807678499433510473203746L;

  return_flag = test_viscosity( mu(T), mu_exact2, tol );

  return return_flag;
}

int main()
{
  int returnval = 0;

  returnval = returnval ||
    vectester (std::valarray<float>(2));
  returnval = returnval ||
    vectester (std::valarray<double>(2));
  returnval = returnval ||
    vectester (std::valarray<long double>(2));
#ifdef ANTIOCH_HAVE_EIGEN
  returnval = returnval ||
    vectester (Eigen::Array2f());
  returnval = returnval ||
    vectester (Eigen::Array2d());
  returnval = returnval ||
    vectester (Eigen::Array<long double, 2, 1>());
#endif
#ifdef ANTIOCH_HAVE_METAPHYSICL
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, float> (0));
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, double> (0));
  returnval = returnval ||
    vectester (MetaPhysicL::NumberArray<2, long double> (0));
#endif

  return returnval;
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include "Halide.h"
#include <time.h>

// Test the simplifier in Halide by testing for equivalence of randomly generated expressions.

using namespace std;
using namespace Halide;
using namespace Halide::Internal;

const int fuzz_var_count = 5;

Type fuzz_types[] = { UInt(1), UInt(8), UInt(16), UInt(32), Int(8), Int(16), Int(32) };
const int fuzz_type_count = sizeof(fuzz_types)/sizeof(fuzz_types[0]);

std::string fuzz_var(int i) {
    return std::string(1, 'a' + i);
}

Expr random_var() {
    return Variable::make(Int(0), fuzz_var(rand()%fuzz_var_count));
}

Type random_type(int width) {
    Type T = fuzz_types[rand()%fuzz_type_count];
    if (width > 1) {
        T = T.with_lanes(width);
    }
    return T;
}

Expr random_leaf(Type T, bool overflow_undef = false, bool imm_only = false) {
    if (T.is_int() && T.bits() == 32) {
        overflow_undef = true;
    }
    if (T.is_scalar()) {
        int var = rand()%fuzz_var_count + 1;
        if (!imm_only && var < fuzz_var_count) {
            return cast(T, random_var());
        } else {
            if (overflow_undef) {
                // For Int(32), we don't care about correctness during
                // overflow, so just use numbers that are unlikely to
                // overflow.
                return cast(T, rand()%256 - 128);
            } else {
                return cast(T, rand() - RAND_MAX/2);
            }
        }
    } else {
        if (rand() % 2 == 0) {
            return Ramp::make(random_leaf(T.element_of(), overflow_undef),
                              random_leaf(T.element_of(), overflow_undef),
                              T.lanes());
        } else {
            return Broadcast::make(random_leaf(T.element_of(), overflow_undef), T.lanes());
        }
    }
}

Expr random_expr(Type T, int depth, bool overflow_undef = false);

Expr random_condition(Type T, int depth, bool maybe_scalar) {
    typedef Expr (*make_bin_op_fn)(Expr, Expr);
    static make_bin_op_fn make_bin_op[] = {
        EQ::make,
        NE::make,
        LT::make,
        LE::make,
        GT::make,
        GE::make,
    };
    const int op_count = sizeof(make_bin_op)/sizeof(make_bin_op[0]);

    if (maybe_scalar && rand() % T.lanes() == 0) {
        T = T.element_of();
    }

    Expr a = random_expr(T, depth);
    Expr b = random_expr(T, depth);
    int op = rand()%op_count;
    return make_bin_op[op](a, b);
}

Expr random_expr(Type T, int depth, bool overflow_undef) {
    typedef Expr (*make_bin_op_fn)(Expr, Expr);
    static make_bin_op_fn make_bin_op[] = {
        Add::make,
        Sub::make,
        Mul::make,
        Min::make,
        Max::make,
        Div::make,
        Mod::make,
     };

    static make_bin_op_fn make_bool_bin_op[] = {
        And::make,
        Or::make,
    };

    if (T.is_int() && T.bits() == 32) {
        overflow_undef = true;
    }

    if (depth-- <= 0) {
        return random_leaf(T, overflow_undef);
    }

    const int bin_op_count = sizeof(make_bin_op) / sizeof(make_bin_op[0]);
    const int bool_bin_op_count = sizeof(make_bool_bin_op) / sizeof(make_bool_bin_op[0]);
    const int op_count = bin_op_count + bool_bin_op_count + 5;

    int op = rand() % op_count;
    switch(op) {
    case 0: return random_leaf(T);
    case 1: return Select::make(random_condition(T, depth, true),
                                random_expr(T, depth, overflow_undef),
                                random_expr(T, depth, overflow_undef));

    case 2:
        if (T.lanes() != 1) {
            return Broadcast::make(random_expr(T.element_of(), depth, overflow_undef),
                                   T.lanes());
        }
        break;
    case 3:
        if (T.lanes() != 1) {
            return Ramp::make(random_expr(T.element_of(), depth, overflow_undef),
                              random_expr(T.element_of(), depth, overflow_undef),
                              T.lanes());
        }
        break;

    case 4:
        if (T.is_bool()) {
            return Not::make(random_expr(T, depth));
        }
        break;

    case 5:
        // When generating boolean expressions, maybe throw in a condition on non-bool types.
        if (T.is_bool()) {
            return random_condition(T, depth, false);
        }
        break;

    case 6:
    {
        // Get a random type that isn't T or int32 (int32 can overflow and we don't care about that).
        Type subT;
        do {
            subT = random_type(T.lanes());
        } while (subT == T || (subT.is_int() && subT.bits() == 32));
        return Cast::make(T, random_expr(subT, depth, overflow_undef));
    }

    default:
        make_bin_op_fn maker;
        if (T.is_bool()) {
            maker = make_bool_bin_op[op%bool_bin_op_count];
        } else {
            maker = make_bin_op[op%bin_op_count];
        }
        Expr a = random_expr(T, depth, overflow_undef);
        Expr b = random_expr(T, depth, overflow_undef);
        return maker(a, b);
    }
    // If we got here, try again.
    return random_expr(T, depth, overflow_undef);
}

bool test_simplification(Expr a, Expr b, Type T, const map<string, Expr> &vars) {
    for (int j = 0; j < T.lanes(); j++) {
        Expr a_j = a;
        Expr b_j = b;
        if (T.lanes() != 1) {
            a_j = extract_lane(a, j);
            b_j = extract_lane(b, j);
        }

        Expr a_j_v = simplify(substitute(vars, a_j));
        Expr b_j_v = simplify(substitute(vars, b_j));
        // If the simplifier didn't produce constants, there must be
        // undefined behavior in this expression. Ignore it.
        if (!Internal::is_const(a_j_v) || !Internal::is_const(b_j_v)) {
            continue;
        }
        if (!equal(a_j_v, b_j_v)) {
            for(map<string, Expr>::const_iterator i = vars.begin(); i != vars.end(); i++) {
                std::cout << i->first << " = " << i->second << '\n';
            }

            std::cout << a << '\n';
            std::cout << b << '\n';
            std::cout << "In vector lane " << j << ":\n";
            std::cout << a_j << " -> " << a_j_v << '\n';
            std::cout << b_j << " -> " << b_j_v << '\n';
            return false;
        }
    }
    return true;
}

bool test_expression(Expr test, int samples) {
    Expr simplified = simplify(test);

    map<string, Expr> vars;
    for (int i = 0; i < fuzz_var_count; i++) {
        vars[fuzz_var(i)] = Expr();
    }

    for (int i = 0; i < samples; i++) {
        for (std::map<string, Expr>::iterator v = vars.begin(); v != vars.end(); v++) {
            v->second = random_leaf(test.type().element_of(), true);
        }

        if (!test_simplification(test, simplified, test.type(), vars)) {
            return false;
        }
    }
    return true;
}

Expr ramp(Expr b, Expr s, int w) { return Ramp::make(b, s, w); }
Expr x1(Expr x) { return Broadcast::make(x, 2); }
Expr x2(Expr x) { return Broadcast::make(x, 2); }
Expr x4(Expr x) { return Broadcast::make(x, 2); }
Expr uint1(Expr x) { return Cast::make(UInt(1), x); }
Expr uint8(Expr x) { return Cast::make(UInt(8), x); }
Expr uint16(Expr x) { return Cast::make(UInt(16), x); }
Expr uint32(Expr x) { return Cast::make(UInt(32), x); }
Expr int8(Expr x) { return Cast::make(Int(8), x); }
Expr int16(Expr x) { return Cast::make(Int(16), x); }
Expr int32(Expr x) { return Cast::make(Int(32), x); }
Expr uint1x2(Expr x) { return Cast::make(UInt(1).with_lanes(2), x); }
Expr uint8x2(Expr x) { return Cast::make(UInt(8).with_lanes(2), x); }
Expr uint16x2(Expr x) { return Cast::make(UInt(16).with_lanes(2), x); }
Expr uint32x2(Expr x) { return Cast::make(UInt(32).with_lanes(2), x); }
Expr int8x2(Expr x) { return Cast::make(Int(8).with_lanes(2), x); }
Expr int16x2(Expr x) { return Cast::make(Int(16).with_lanes(2), x); }
Expr int32x2(Expr x) { return Cast::make(Int(32).with_lanes(2), x); }

Expr a(Variable::make(Int(0), fuzz_var(0)));
Expr b(Variable::make(Int(0), fuzz_var(1)));
Expr c(Variable::make(Int(0), fuzz_var(2)));
Expr d(Variable::make(Int(0), fuzz_var(3)));
Expr e(Variable::make(Int(0), fuzz_var(4)));

int main(int argc, char **argv) {
    // Number of random expressions to test.
    const int count = 1000;
    // Depth of the randomly generated expression trees.
    const int depth = 5;
    // Number of samples to test the generated expressions for.
    const int samples = 3;

    // We want different fuzz tests every time, to increase coverage.
    // We also report the seed to enable reproducing failures.
    int fuzz_seed = argc > 1 ? atoi(argv[1]) : time(NULL);
    srand(fuzz_seed);
    std::cout << "Simplify fuzz test seed: " << fuzz_seed << '\n';

    int max_fuzz_vector_width = 4;

    for (int i = 0; i < fuzz_type_count; i++) {
        Type T = fuzz_types[i];
        for (int w = 1; w < max_fuzz_vector_width; w *= 2) {
            Type VT = T.with_lanes(w);
            for (int n = 0; n < count; n++) {
                // Generate a random expr...
                Expr test = random_expr(VT, depth);
                if (!test_expression(test, samples)) {
                    return -1;
                }
            }
        }
    }
    std::cout << "Success!" << std::endl;
    return 0;
}
<commit_msg>Use std::endl to ensure buffer flush.<commit_after>#include <stdio.h>
#include "Halide.h"
#include <time.h>

// Test the simplifier in Halide by testing for equivalence of randomly generated expressions.

using namespace std;
using namespace Halide;
using namespace Halide::Internal;

const int fuzz_var_count = 5;

Type fuzz_types[] = { UInt(1), UInt(8), UInt(16), UInt(32), Int(8), Int(16), Int(32) };
const int fuzz_type_count = sizeof(fuzz_types)/sizeof(fuzz_types[0]);

std::string fuzz_var(int i) {
    return std::string(1, 'a' + i);
}

Expr random_var() {
    return Variable::make(Int(0), fuzz_var(rand()%fuzz_var_count));
}

Type random_type(int width) {
    Type T = fuzz_types[rand()%fuzz_type_count];
    if (width > 1) {
        T = T.with_lanes(width);
    }
    return T;
}

Expr random_leaf(Type T, bool overflow_undef = false, bool imm_only = false) {
    if (T.is_int() && T.bits() == 32) {
        overflow_undef = true;
    }
    if (T.is_scalar()) {
        int var = rand()%fuzz_var_count + 1;
        if (!imm_only && var < fuzz_var_count) {
            return cast(T, random_var());
        } else {
            if (overflow_undef) {
                // For Int(32), we don't care about correctness during
                // overflow, so just use numbers that are unlikely to
                // overflow.
                return cast(T, rand()%256 - 128);
            } else {
                return cast(T, rand() - RAND_MAX/2);
            }
        }
    } else {
        if (rand() % 2 == 0) {
            return Ramp::make(random_leaf(T.element_of(), overflow_undef),
                              random_leaf(T.element_of(), overflow_undef),
                              T.lanes());
        } else {
            return Broadcast::make(random_leaf(T.element_of(), overflow_undef), T.lanes());
        }
    }
}

Expr random_expr(Type T, int depth, bool overflow_undef = false);

Expr random_condition(Type T, int depth, bool maybe_scalar) {
    typedef Expr (*make_bin_op_fn)(Expr, Expr);
    static make_bin_op_fn make_bin_op[] = {
        EQ::make,
        NE::make,
        LT::make,
        LE::make,
        GT::make,
        GE::make,
    };
    const int op_count = sizeof(make_bin_op)/sizeof(make_bin_op[0]);

    if (maybe_scalar && rand() % T.lanes() == 0) {
        T = T.element_of();
    }

    Expr a = random_expr(T, depth);
    Expr b = random_expr(T, depth);
    int op = rand()%op_count;
    return make_bin_op[op](a, b);
}

Expr random_expr(Type T, int depth, bool overflow_undef) {
    typedef Expr (*make_bin_op_fn)(Expr, Expr);
    static make_bin_op_fn make_bin_op[] = {
        Add::make,
        Sub::make,
        Mul::make,
        Min::make,
        Max::make,
        Div::make,
        Mod::make,
     };

    static make_bin_op_fn make_bool_bin_op[] = {
        And::make,
        Or::make,
    };

    if (T.is_int() && T.bits() == 32) {
        overflow_undef = true;
    }

    if (depth-- <= 0) {
        return random_leaf(T, overflow_undef);
    }

    const int bin_op_count = sizeof(make_bin_op) / sizeof(make_bin_op[0]);
    const int bool_bin_op_count = sizeof(make_bool_bin_op) / sizeof(make_bool_bin_op[0]);
    const int op_count = bin_op_count + bool_bin_op_count + 5;

    int op = rand() % op_count;
    switch(op) {
    case 0: return random_leaf(T);
    case 1: return Select::make(random_condition(T, depth, true),
                                random_expr(T, depth, overflow_undef),
                                random_expr(T, depth, overflow_undef));

    case 2:
        if (T.lanes() != 1) {
            return Broadcast::make(random_expr(T.element_of(), depth, overflow_undef),
                                   T.lanes());
        }
        break;
    case 3:
        if (T.lanes() != 1) {
            return Ramp::make(random_expr(T.element_of(), depth, overflow_undef),
                              random_expr(T.element_of(), depth, overflow_undef),
                              T.lanes());
        }
        break;

    case 4:
        if (T.is_bool()) {
            return Not::make(random_expr(T, depth));
        }
        break;

    case 5:
        // When generating boolean expressions, maybe throw in a condition on non-bool types.
        if (T.is_bool()) {
            return random_condition(T, depth, false);
        }
        break;

    case 6:
    {
        // Get a random type that isn't T or int32 (int32 can overflow and we don't care about that).
        Type subT;
        do {
            subT = random_type(T.lanes());
        } while (subT == T || (subT.is_int() && subT.bits() == 32));
        return Cast::make(T, random_expr(subT, depth, overflow_undef));
    }

    default:
        make_bin_op_fn maker;
        if (T.is_bool()) {
            maker = make_bool_bin_op[op%bool_bin_op_count];
        } else {
            maker = make_bin_op[op%bin_op_count];
        }
        Expr a = random_expr(T, depth, overflow_undef);
        Expr b = random_expr(T, depth, overflow_undef);
        return maker(a, b);
    }
    // If we got here, try again.
    return random_expr(T, depth, overflow_undef);
}

bool test_simplification(Expr a, Expr b, Type T, const map<string, Expr> &vars) {
    for (int j = 0; j < T.lanes(); j++) {
        Expr a_j = a;
        Expr b_j = b;
        if (T.lanes() != 1) {
            a_j = extract_lane(a, j);
            b_j = extract_lane(b, j);
        }

        Expr a_j_v = simplify(substitute(vars, a_j));
        Expr b_j_v = simplify(substitute(vars, b_j));
        // If the simplifier didn't produce constants, there must be
        // undefined behavior in this expression. Ignore it.
        if (!Internal::is_const(a_j_v) || !Internal::is_const(b_j_v)) {
            continue;
        }
        if (!equal(a_j_v, b_j_v)) {
            for(map<string, Expr>::const_iterator i = vars.begin(); i != vars.end(); i++) {
                std::cout << i->first << " = " << i->second << '\n';
            }

            std::cout << a << '\n';
            std::cout << b << '\n';
            std::cout << "In vector lane " << j << ":\n";
            std::cout << a_j << " -> " << a_j_v << '\n';
            std::cout << b_j << " -> " << b_j_v << '\n';
            return false;
        }
    }
    return true;
}

bool test_expression(Expr test, int samples) {
    Expr simplified = simplify(test);

    map<string, Expr> vars;
    for (int i = 0; i < fuzz_var_count; i++) {
        vars[fuzz_var(i)] = Expr();
    }

    for (int i = 0; i < samples; i++) {
        for (std::map<string, Expr>::iterator v = vars.begin(); v != vars.end(); v++) {
            v->second = random_leaf(test.type().element_of(), true);
        }

        if (!test_simplification(test, simplified, test.type(), vars)) {
            return false;
        }
    }
    return true;
}

Expr ramp(Expr b, Expr s, int w) { return Ramp::make(b, s, w); }
Expr x1(Expr x) { return Broadcast::make(x, 2); }
Expr x2(Expr x) { return Broadcast::make(x, 2); }
Expr x4(Expr x) { return Broadcast::make(x, 2); }
Expr uint1(Expr x) { return Cast::make(UInt(1), x); }
Expr uint8(Expr x) { return Cast::make(UInt(8), x); }
Expr uint16(Expr x) { return Cast::make(UInt(16), x); }
Expr uint32(Expr x) { return Cast::make(UInt(32), x); }
Expr int8(Expr x) { return Cast::make(Int(8), x); }
Expr int16(Expr x) { return Cast::make(Int(16), x); }
Expr int32(Expr x) { return Cast::make(Int(32), x); }
Expr uint1x2(Expr x) { return Cast::make(UInt(1).with_lanes(2), x); }
Expr uint8x2(Expr x) { return Cast::make(UInt(8).with_lanes(2), x); }
Expr uint16x2(Expr x) { return Cast::make(UInt(16).with_lanes(2), x); }
Expr uint32x2(Expr x) { return Cast::make(UInt(32).with_lanes(2), x); }
Expr int8x2(Expr x) { return Cast::make(Int(8).with_lanes(2), x); }
Expr int16x2(Expr x) { return Cast::make(Int(16).with_lanes(2), x); }
Expr int32x2(Expr x) { return Cast::make(Int(32).with_lanes(2), x); }

Expr a(Variable::make(Int(0), fuzz_var(0)));
Expr b(Variable::make(Int(0), fuzz_var(1)));
Expr c(Variable::make(Int(0), fuzz_var(2)));
Expr d(Variable::make(Int(0), fuzz_var(3)));
Expr e(Variable::make(Int(0), fuzz_var(4)));

int main(int argc, char **argv) {
    // Number of random expressions to test.
    const int count = 1000;
    // Depth of the randomly generated expression trees.
    const int depth = 5;
    // Number of samples to test the generated expressions for.
    const int samples = 3;

    // We want different fuzz tests every time, to increase coverage.
    // We also report the seed to enable reproducing failures.
    int fuzz_seed = argc > 1 ? atoi(argv[1]) : time(NULL);
    srand(fuzz_seed);
    std::cout << "Simplify fuzz test seed: " << fuzz_seed << std::endl;

    int max_fuzz_vector_width = 4;

    for (int i = 0; i < fuzz_type_count; i++) {
        Type T = fuzz_types[i];
        for (int w = 1; w < max_fuzz_vector_width; w *= 2) {
            Type VT = T.with_lanes(w);
            for (int n = 0; n < count; n++) {
                // Generate a random expr...
                Expr test = random_expr(VT, depth);
                if (!test_expression(test, samples)) {
                    return -1;
                }
            }
        }
    }
    std::cout << "Success!" << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>#include <windows.h>
#include "pluginsdk\_plugins.h"
#include "pluginsdk\_exports.h" // modified _exports.h to use _dbg_addrinfoget export
#include "pluginsdk\bridgemain.h"
#ifdef _WIN64
#pragma comment(lib, "pluginsdk\\x64dbg.lib")
#pragma comment(lib, "pluginsdk\\x64bridge.lib")
#else
#pragma comment(lib, "pluginsdk\\x32dbg.lib")
#pragma comment(lib, "pluginsdk\\x32bridge.lib")
#endif

#ifndef DLL_EXPORT
#define DLL_EXPORT extern "C" __declspec(dllexport)
#endif //DLL_EXPORT

#define plugin_name "XrefInfo"
#define plugin_version 1

int pluginHandle;
HWND hwndDlg;

int compareFunc(const void* a, const void* b)
{
    XREF_RECORD* A, *B;
    A = (XREF_RECORD*)a;
    B = (XREF_RECORD*)b;
    if(A->type > B->type)
        return 1;
    else if(A->type < B->type)
        return -1;
    else if(A->addr > B->addr)
        return 1;
    else if(A->addr < B->addr)
        return -1;
    else
        return 0;
}

void cbPlugin(CBTYPE cbType, LPVOID generic_param)
{
    PLUG_CB_SELCHANGED* param = (PLUG_CB_SELCHANGED*)generic_param;
    if(param->hWindow == GUI_DISASSEMBLY)
    {
        XREF_INFO info;
        if(DbgXrefGet(param->VA, &info) && info.refcount > 0)
        {
            std::string output;
            std::qsort(info.references, info.refcount, sizeof(info.references[0]), &compareFunc);
            int t = -1;
            for(int i = 0; i < info.refcount; i++)
            {
                if(t != info.references[i].type)
                {
                    if(t != -1)
                        output += ",";
                    switch(info.references[i].type)
                    {
                    case XREF_JMP:
                        output += "Jump from ";
                        break;
                    case XREF_CALL:
                        output += "Call from ";
                        break;
                    default:
                        output += "Reference from ";
                        break;
                    }
                    t = info.references[i].type;
                }
                ADDRINFO label;
                label.flags = flaglabel;
                _dbg_addrinfoget(info.references[i].addr, SEG_DEFAULT, &label);
                output += label.label;
                if(i != info.refcount - 1)
                    output += ",";
            }
            GuiAddInfoLine(output.c_str());
        }
    }
}

DLL_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
    initStruct->pluginVersion = plugin_version;
    initStruct->sdkVersion = PLUG_SDKVERSION;
    strcpy(initStruct->pluginName, plugin_name);
    pluginHandle = initStruct->pluginHandle;
    return true;
}

DLL_EXPORT bool plugstop()
{
    return true;
}

DLL_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
    hwndDlg = setupStruct->hwndDlg;
    _plugin_registercallback(pluginHandle, CB_SELCHANGED, &cbPlugin);
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
        DisableThreadLibraryCalls(hinstDLL);
    return TRUE;
}
<commit_msg>rebrand this plugin<commit_after>#include <windows.h>
#include "pluginsdk\_plugins.h"
#include "pluginsdk\_exports.h" // modified _exports.h to use _dbg_addrinfoget export
#include "pluginsdk\bridgemain.h"
#ifdef _WIN64
#pragma comment(lib, "pluginsdk\\x64dbg.lib")
#pragma comment(lib, "pluginsdk\\x64bridge.lib")
#else
#pragma comment(lib, "pluginsdk\\x32dbg.lib")
#pragma comment(lib, "pluginsdk\\x32bridge.lib")
#endif

#ifndef DLL_EXPORT
#define DLL_EXPORT extern "C" __declspec(dllexport)
#endif //DLL_EXPORT

#define plugin_name "ExtraInfo"
#define plugin_version 1

int pluginHandle;
HWND hwndDlg;

int compareFunc(const void* a, const void* b)
{
    XREF_RECORD* A, *B;
    A = (XREF_RECORD*)a;
    B = (XREF_RECORD*)b;
    if(A->type > B->type)
        return 1;
    else if(A->type < B->type)
        return -1;
    else if(A->addr > B->addr)
        return 1;
    else if(A->addr < B->addr)
        return -1;
    else
        return 0;
}

void cbPlugin(CBTYPE cbType, LPVOID generic_param)
{
    PLUG_CB_SELCHANGED* param = (PLUG_CB_SELCHANGED*)generic_param;
    if(param->hWindow == GUI_DISASSEMBLY)
    {
        XREF_INFO info;
        if(DbgXrefGet(param->VA, &info) && info.refcount > 0)
        {
            std::string output;
            std::qsort(info.references, info.refcount, sizeof(info.references[0]), &compareFunc);
            int t = -1;
            for(int i = 0; i < info.refcount; i++)
            {
                if(t != info.references[i].type)
                {
                    if(t != -1)
                        output += ",";
                    switch(info.references[i].type)
                    {
                    case XREF_JMP:
                        output += "Jump from ";
                        break;
                    case XREF_CALL:
                        output += "Call from ";
                        break;
                    default:
                        output += "Reference from ";
                        break;
                    }
                    t = info.references[i].type;
                }
                ADDRINFO label;
                label.flags = flaglabel;
                _dbg_addrinfoget(info.references[i].addr, SEG_DEFAULT, &label);
                output += label.label;
                if(i != info.refcount - 1)
                    output += ",";
            }
            GuiAddInfoLine(output.c_str());
        }
    }
}

DLL_EXPORT bool pluginit(PLUG_INITSTRUCT* initStruct)
{
    initStruct->pluginVersion = plugin_version;
    initStruct->sdkVersion = PLUG_SDKVERSION;
    strcpy(initStruct->pluginName, plugin_name);
    pluginHandle = initStruct->pluginHandle;
    return true;
}

DLL_EXPORT bool plugstop()
{
    return true;
}

DLL_EXPORT void plugsetup(PLUG_SETUPSTRUCT* setupStruct)
{
    hwndDlg = setupStruct->hwndDlg;
    _plugin_registercallback(pluginHandle, CB_SELCHANGED, &cbPlugin);
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if(fdwReason == DLL_PROCESS_ATTACH)
        DisableThreadLibraryCalls(hinstDLL);
    return TRUE;
}
<|endoftext|>