<commit_before>/* This file is part of the KDE libraries
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
   Copyright (C) 2001 by Victor Röder <Victor_Roeder@GMX.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

/******** Partly based on the ArgHintWidget of Qt3 by Trolltech AS *********/
/* Trolltech doesn't mind, if we license that piece of code as LGPL, because there isn't much
 * left from the desigener code */

#include "katecodecompletion.h"
#include "katecodecompletion.moc"

#include "katecodecompletion_arghint.h"
#include "katedocument.h"
#include "kateview.h"
#include "katerenderer.h"
#include "kateconfig.h"

#include <kdebug.h>

#include <qwhatsthis.h>
#include <qvbox.h>
#include <qlistbox.h>
#include <qtimer.h>
#include <qtooltip.h>
#include <qapplication.h>
#include <qsizegrip.h>
#include <qfontmetrics.h>
/**
 * This class is used as the codecompletion listbox. It can be resized according to its contents,
 *  therfor the needed size is provided by sizeHint();
 *@short Listbox showing codecompletion
 *@author Jonas B. Jacobi <j.jacobi@gmx.de>
 */
class CCListBox : public QListBox{
public:
  /**
    @short Create a new CCListBox
    @param view The KateView, CCListBox is displayed in
   */
    CCListBox(KateView* view, QWidget* parent = 0, const char* name = 0, WFlags f = 0):QListBox(parent, name, f), m_view(view){
    };

    QSize sizeHint()  const {
        int count = this->count();
        int height = 20;
        int tmpwidth = 8;
        //FIXME the height is for some reasons at least 3 items heigh, even if there is only one item in the list
        if (count > 0)
            if(count < 11)
                height =  count * itemHeight(0);
            else  {
                height = 10 * itemHeight(0);
                tmpwidth += verticalScrollBar()->width();
            }

        int maxcount = 0, tmpcount = 0;
        const QFontMetrics* metrics = m_view->renderer()->currentFontMetrics();
        for (int i = 0; i < count; ++i)
            if ( (tmpcount = metrics->width(text(i)) ) > maxcount)
                    maxcount = tmpcount;

        if (maxcount > QApplication::desktop()->width()){
            tmpwidth = QApplication::desktop()->width() - 5;
            height += horizontalScrollBar()->height();
        } else
            tmpwidth += maxcount;
        return QSize(tmpwidth,height);

    };

private:
  KateView* m_view;

};

class CompletionItem : public QListBoxText
{
public:
  CompletionItem( QListBox* lb, KTextEditor::CompletionEntry entry )
    : QListBoxText( lb )
    , m_entry( entry )
  {
    if( entry.postfix == "()" ) { // should be configurable
      setText( entry.prefix + " " + entry.text + entry.postfix );
    } else {
      setText( entry.prefix + " " + entry.text + " " + entry.postfix);
    }
  }

  KTextEditor::CompletionEntry m_entry;
};

KateCodeCompletion::KateCodeCompletion( KateView* view )
  : QObject( view, "Kate Code Completion" )
  , m_view( view )
  , m_commentLabel( 0 )
{
  m_completionPopup = new QVBox( 0, 0, WType_Popup );
  m_completionPopup->setFrameStyle( QFrame::Box | QFrame::Plain );
  m_completionPopup->setLineWidth( 1 );

  m_completionListBox = new CCListBox( view,  m_completionPopup );
  m_completionListBox->setFrameStyle( QFrame::NoFrame );
  m_completionListBox->setCornerWidget( new QSizeGrip( m_completionListBox) );

  m_completionListBox->installEventFilter( this );

  m_completionPopup->resize(m_completionListBox->sizeHint() + QSize(2,2));
  m_completionPopup->installEventFilter( this );
  m_completionPopup->setFocusProxy( m_completionListBox );

  m_pArgHint = new KDevArgHint( m_view );
  connect( m_pArgHint, SIGNAL(argHintHidden()),
           this, SIGNAL(argHintHidden()) );

  connect( m_view, SIGNAL(cursorPositionChanged()),
           this, SLOT(slotCursorPosChanged()) );
}

bool KateCodeCompletion::codeCompletionVisible () {
  return m_completionPopup->isVisible();
}

void KateCodeCompletion::showCompletionBox(
    QValueList<KTextEditor::CompletionEntry> complList, int offset, bool casesensitive )
{
  emit aboutToShowCompletionBox();

  kdDebug(13035) << "showCompletionBox " << endl;

  m_caseSensitive = casesensitive;
  m_complList = complList;
  m_offset = offset;
  m_view->cursorPositionReal( &m_lineCursor, &m_colCursor );
  m_colCursor -= offset;

  updateBox( true );
}

bool KateCodeCompletion::eventFilter( QObject *o, QEvent *e )
{
  if ( o != m_completionPopup &&
       o != m_completionListBox &&
       o != m_completionListBox->viewport() )
    return false;

   if ( e->type() == QEvent::MouseButtonDblClick  ) {
    doComplete();
    return false;
   }

   if ( e->type() == QEvent::MouseButtonPress ) {
    QTimer::singleShot(0, this, SLOT(showComment()));
    return false;
   }

   if ( e->type() == QEvent::KeyPress ) {
    QKeyEvent *ke = (QKeyEvent*)e;
    if( /*(ke->key() == Key_Left)  || (ke->key() == Key_Right) ||*///what are <- and -> used for??
        (ke->key() == Key_Up)    || (ke->key() == Key_Down ) ||
        (ke->key() == Key_Home ) || (ke->key() == Key_End)   ||
        (ke->key() == Key_Prior) || (ke->key() == Key_Next )) {
      QTimer::singleShot(0,this,SLOT(showComment()));
      return false;
    }
    if( ke->key() == Key_Enter || ke->key() == Key_Return ) {
      doComplete();
      return false;
    }

    if( ke->key() == Key_Escape ) {
      abortCompletion();
      m_view->setFocus();
      return false;
    }

    // redirect the event to the editor
    if( ke->key() == Key_Backspace) {
      m_view->backspace();
    } else {
      QApplication::sendEvent( m_view->m_viewInternal, e );
    }
    if( m_colCursor > m_view->cursorColumnReal() ) {
      // the cursor is too far left
      kdDebug(13035) << "Aborting Codecompletion after sendEvent" << endl;
      kdDebug(13035) << m_view->cursorColumnReal() << endl;
      abortCompletion();
      m_view->setFocus();
      return true;
    }
    updateBox();
    return true;
  }

  if( e->type() == QEvent::FocusOut )
    abortCompletion();
  return false;
}

void KateCodeCompletion::doComplete()
{
  CompletionItem* item = static_cast<CompletionItem*>(
     m_completionListBox->item(m_completionListBox->currentItem()));

  if( item == 0 )
    return;

  QString text = item->m_entry.text;
  QString currentLine = m_view->currentTextLine();
  int len = m_view->cursorColumnReal() - m_colCursor;
  QString currentComplText = currentLine.mid(m_colCursor,len);
  QString add = text.mid(currentComplText.length());
  if( item->m_entry.postfix == "()" )
    add += "(";

  emit filterInsertString(&(item->m_entry),&add);
  m_view->insertText(add);

  complete( item->m_entry );
  m_view->setFocus();
}

void KateCodeCompletion::abortCompletion()
{
  m_completionPopup->hide();
  delete m_commentLabel;
  m_commentLabel = 0;
  emit completionAborted();
}

void KateCodeCompletion::complete( KTextEditor::CompletionEntry entry )
{
  m_completionPopup->hide();
  delete m_commentLabel;
  m_commentLabel = 0;
  emit completionDone( entry );
  emit completionDone();
}

void KateCodeCompletion::updateBox( bool newCoordinate )
{
  m_completionListBox->clear();

  QString currentLine = m_view->currentTextLine();
  int len = m_view->cursorColumnReal() - m_colCursor;
  QString currentComplText = currentLine.mid(m_colCursor,len);
/* No-one really badly wants those, or?
  kdDebug(13035) << "Column: " << m_colCursor << endl;
  kdDebug(13035) << "Line: " << currentLine << endl;
  kdDebug(13035) << "CurrentColumn: " << m_view->cursorColumnReal() << endl;
  kdDebug(13035) << "Len: " << len << endl;
  kdDebug(13035) << "Text: '" << currentComplText << "'" << endl;
  kdDebug(13035) << "Count: " << m_complList.count() << endl;
*/
  QValueList<KTextEditor::CompletionEntry>::Iterator it;
  if( m_caseSensitive ) {
    for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
      if( (*it).text.startsWith(currentComplText) ) {
        new CompletionItem(m_completionListBox,*it);
      }
    }
  } else {
    currentComplText = currentComplText.upper();
    for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
      if( (*it).text.upper().startsWith(currentComplText) ) {
        new CompletionItem(m_completionListBox,*it);
      }
    }
  }

  if( m_completionListBox->count() == 0 ||
      ( m_completionListBox->count() == 1 && // abort if we equaled the last item
        currentComplText == m_completionListBox->text(0).stripWhiteSpace() ) ) {
    abortCompletion();
    m_view->setFocus();
    return;
  }

    kdDebug(13035)<<"KateCodeCompletion::updateBox: Resizing widget"<<endl;
        m_completionPopup->resize(m_completionListBox->sizeHint() + QSize(2,2));
    QPoint p = m_view->mapToGlobal( m_view->cursorCoordinates() );
        int x = p.x();
        int y = p.y() ;
        if ( y + m_completionPopup->height() + m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height() > QApplication::desktop()->height() )
                y -= (m_completionPopup->height() );
        else
                y += m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height();

        if (x + m_completionPopup->width() > QApplication::desktop()->width())
                x = QApplication::desktop()->width() - m_completionPopup->width();

        m_completionPopup->move( QPoint(x,y) );

  m_completionListBox->setCurrentItem( 0 );
  m_completionListBox->setSelected( 0, true );
  m_completionListBox->setFocus();
  m_completionPopup->show();

  QTimer::singleShot(0,this,SLOT(showComment()));
}

void KateCodeCompletion::showArgHint ( QStringList functionList, const QString& strWrapping, const QString& strDelimiter )
{
  unsigned int line, col;
  m_view->cursorPositionReal( &line, &col );
  m_pArgHint->reset( line, col );
  m_pArgHint->setArgMarkInfos( strWrapping, strDelimiter );

  int nNum = 0;
  for( QStringList::Iterator it = functionList.begin(); it != functionList.end(); it++ )
  {
    kdDebug(13035) << "Insert function text: " << *it << endl;

    m_pArgHint->addFunction( nNum, ( *it ) );

    nNum++;
  }

  m_pArgHint->move(m_view->mapToGlobal(m_view->cursorCoordinates() + QPoint(0,m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height())) );
  m_pArgHint->show();
}

void KateCodeCompletion::slotCursorPosChanged()
{
  m_pArgHint->cursorPositionChanged ( m_view, m_view->cursorLine(), m_view->cursorColumnReal() );
}

void KateCodeCompletion::showComment()
{
  CompletionItem* item = static_cast<CompletionItem*>(m_completionListBox->item(m_completionListBox->currentItem()));

  if( !item )
    return;
  if( item->m_entry.comment.isEmpty() )
    return;

  delete m_commentLabel;
  m_commentLabel = new KateCodeCompletionCommentLabel( 0, item->m_entry.comment );
  m_commentLabel->setFont(QToolTip::font());
  m_commentLabel->setPalette(QToolTip::palette());

  QPoint rightPoint = m_completionPopup->mapToGlobal(QPoint(m_completionPopup->width(),0));
  QPoint leftPoint = m_completionPopup->mapToGlobal(QPoint(0,0));
  QRect screen = QApplication::desktop()->screenGeometry( m_commentLabel->x11Screen() );
  QPoint finalPoint;
  if (rightPoint.x()+m_commentLabel->width() > screen.x() + screen.width())
    finalPoint.setX(leftPoint.x()-m_commentLabel->width());
  else
    finalPoint.setX(rightPoint.x());

  m_completionListBox->ensureCurrentVisible();

  finalPoint.setY(
    m_completionListBox->viewport()->mapToGlobal(m_completionListBox->itemRect(
      m_completionListBox->item(m_completionListBox->currentItem())).topLeft()).y());

  m_commentLabel->move(finalPoint);
  m_commentLabel->show();
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>fix konqui crash<commit_after>/* This file is part of the KDE libraries
   Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org>
   Copyright (C) 2001 by Victor Röder <Victor_Roeder@GMX.de>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

/******** Partly based on the ArgHintWidget of Qt3 by Trolltech AS *********/
/* Trolltech doesn't mind, if we license that piece of code as LGPL, because there isn't much
 * left from the desigener code */

#include "katecodecompletion.h"
#include "katecodecompletion.moc"

#include "katecodecompletion_arghint.h"
#include "katedocument.h"
#include "kateview.h"
#include "katerenderer.h"
#include "kateconfig.h"

#include <kdebug.h>

#include <qwhatsthis.h>
#include <qvbox.h>
#include <qlistbox.h>
#include <qtimer.h>
#include <qtooltip.h>
#include <qapplication.h>
#include <qsizegrip.h>
#include <qfontmetrics.h>
/**
 * This class is used as the codecompletion listbox. It can be resized according to its contents,
 *  therfor the needed size is provided by sizeHint();
 *@short Listbox showing codecompletion
 *@author Jonas B. Jacobi <j.jacobi@gmx.de>
 */
class CCListBox : public QListBox{
public:
  /**
    @short Create a new CCListBox
    @param view The KateView, CCListBox is displayed in
   */
    CCListBox(KateView* view, QWidget* parent = 0, const char* name = 0, WFlags f = 0):QListBox(parent, name, f), m_view(view){
    };

    QSize sizeHint()  const {
        int count = this->count();
        int height = 20;
        int tmpwidth = 8;
        //FIXME the height is for some reasons at least 3 items heigh, even if there is only one item in the list
        if (count > 0)
            if(count < 11)
                height =  count * itemHeight(0);
            else  {
                height = 10 * itemHeight(0);
                tmpwidth += verticalScrollBar()->width();
            }

        int maxcount = 0, tmpcount = 0;
        for (int i = 0; i < count; ++i)
            if ( (tmpcount = fontMetrics().width(text(i)) ) > maxcount)
                    maxcount = tmpcount;

        if (maxcount > QApplication::desktop()->width()){
            tmpwidth = QApplication::desktop()->width() - 5;
            height += horizontalScrollBar()->height();
        } else
            tmpwidth += maxcount;
        return QSize(tmpwidth,height);

    };

private:
  KateView* m_view;

};

class CompletionItem : public QListBoxText
{
public:
  CompletionItem( QListBox* lb, KTextEditor::CompletionEntry entry )
    : QListBoxText( lb )
    , m_entry( entry )
  {
    if( entry.postfix == "()" ) { // should be configurable
      setText( entry.prefix + " " + entry.text + entry.postfix );
    } else {
      setText( entry.prefix + " " + entry.text + " " + entry.postfix);
    }
  }

  KTextEditor::CompletionEntry m_entry;
};

KateCodeCompletion::KateCodeCompletion( KateView* view )
  : QObject( view, "Kate Code Completion" )
  , m_view( view )
  , m_commentLabel( 0 )
{
  m_completionPopup = new QVBox( 0, 0, WType_Popup );
  m_completionPopup->setFrameStyle( QFrame::Box | QFrame::Plain );
  m_completionPopup->setLineWidth( 1 );

  m_completionListBox = new CCListBox( view,  m_completionPopup );
  m_completionListBox->setFrameStyle( QFrame::NoFrame );
  m_completionListBox->setCornerWidget( new QSizeGrip( m_completionListBox) );

  m_completionListBox->installEventFilter( this );

  m_completionPopup->resize(m_completionListBox->sizeHint() + QSize(2,2));
  m_completionPopup->installEventFilter( this );
  m_completionPopup->setFocusProxy( m_completionListBox );

  m_pArgHint = new KDevArgHint( m_view );
  connect( m_pArgHint, SIGNAL(argHintHidden()),
           this, SIGNAL(argHintHidden()) );

  connect( m_view, SIGNAL(cursorPositionChanged()),
           this, SLOT(slotCursorPosChanged()) );
}

bool KateCodeCompletion::codeCompletionVisible () {
  return m_completionPopup->isVisible();
}

void KateCodeCompletion::showCompletionBox(
    QValueList<KTextEditor::CompletionEntry> complList, int offset, bool casesensitive )
{
  emit aboutToShowCompletionBox();

  kdDebug(13035) << "showCompletionBox " << endl;

  m_caseSensitive = casesensitive;
  m_complList = complList;
  m_offset = offset;
  m_view->cursorPositionReal( &m_lineCursor, &m_colCursor );
  m_colCursor -= offset;

  updateBox( true );
}

bool KateCodeCompletion::eventFilter( QObject *o, QEvent *e )
{
  if ( o != m_completionPopup &&
       o != m_completionListBox &&
       o != m_completionListBox->viewport() )
    return false;

   if ( e->type() == QEvent::MouseButtonDblClick  ) {
    doComplete();
    return false;
   }

   if ( e->type() == QEvent::MouseButtonPress ) {
    QTimer::singleShot(0, this, SLOT(showComment()));
    return false;
   }

   if ( e->type() == QEvent::KeyPress ) {
    QKeyEvent *ke = (QKeyEvent*)e;
    if( /*(ke->key() == Key_Left)  || (ke->key() == Key_Right) ||*///what are <- and -> used for??
        (ke->key() == Key_Up)    || (ke->key() == Key_Down ) ||
        (ke->key() == Key_Home ) || (ke->key() == Key_End)   ||
        (ke->key() == Key_Prior) || (ke->key() == Key_Next )) {
      QTimer::singleShot(0,this,SLOT(showComment()));
      return false;
    }
    if( ke->key() == Key_Enter || ke->key() == Key_Return ) {
      doComplete();
      return false;
    }

    if( ke->key() == Key_Escape ) {
      abortCompletion();
      m_view->setFocus();
      return false;
    }

    // redirect the event to the editor
    if( ke->key() == Key_Backspace) {
      m_view->backspace();
    } else {
      QApplication::sendEvent( m_view->m_viewInternal, e );
    }
    if( m_colCursor > m_view->cursorColumnReal() ) {
      // the cursor is too far left
      kdDebug(13035) << "Aborting Codecompletion after sendEvent" << endl;
      kdDebug(13035) << m_view->cursorColumnReal() << endl;
      abortCompletion();
      m_view->setFocus();
      return true;
    }
    updateBox();
    return true;
  }

  if( e->type() == QEvent::FocusOut )
    abortCompletion();
  return false;
}

void KateCodeCompletion::doComplete()
{
  CompletionItem* item = static_cast<CompletionItem*>(
     m_completionListBox->item(m_completionListBox->currentItem()));

  if( item == 0 )
    return;

  QString text = item->m_entry.text;
  QString currentLine = m_view->currentTextLine();
  int len = m_view->cursorColumnReal() - m_colCursor;
  QString currentComplText = currentLine.mid(m_colCursor,len);
  QString add = text.mid(currentComplText.length());
  if( item->m_entry.postfix == "()" )
    add += "(";

  emit filterInsertString(&(item->m_entry),&add);
  m_view->insertText(add);

  complete( item->m_entry );
  m_view->setFocus();
}

void KateCodeCompletion::abortCompletion()
{
  m_completionPopup->hide();
  delete m_commentLabel;
  m_commentLabel = 0;
  emit completionAborted();
}

void KateCodeCompletion::complete( KTextEditor::CompletionEntry entry )
{
  m_completionPopup->hide();
  delete m_commentLabel;
  m_commentLabel = 0;
  emit completionDone( entry );
  emit completionDone();
}

void KateCodeCompletion::updateBox( bool newCoordinate )
{
  m_completionListBox->clear();

  QString currentLine = m_view->currentTextLine();
  int len = m_view->cursorColumnReal() - m_colCursor;
  QString currentComplText = currentLine.mid(m_colCursor,len);
/* No-one really badly wants those, or?
  kdDebug(13035) << "Column: " << m_colCursor << endl;
  kdDebug(13035) << "Line: " << currentLine << endl;
  kdDebug(13035) << "CurrentColumn: " << m_view->cursorColumnReal() << endl;
  kdDebug(13035) << "Len: " << len << endl;
  kdDebug(13035) << "Text: '" << currentComplText << "'" << endl;
  kdDebug(13035) << "Count: " << m_complList.count() << endl;
*/
  QValueList<KTextEditor::CompletionEntry>::Iterator it;
  if( m_caseSensitive ) {
    for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
      if( (*it).text.startsWith(currentComplText) ) {
        new CompletionItem(m_completionListBox,*it);
      }
    }
  } else {
    currentComplText = currentComplText.upper();
    for( it = m_complList.begin(); it != m_complList.end(); ++it ) {
      if( (*it).text.upper().startsWith(currentComplText) ) {
        new CompletionItem(m_completionListBox,*it);
      }
    }
  }

  if( m_completionListBox->count() == 0 ||
      ( m_completionListBox->count() == 1 && // abort if we equaled the last item
        currentComplText == m_completionListBox->text(0).stripWhiteSpace() ) ) {
    abortCompletion();
    m_view->setFocus();
    return;
  }

    kdDebug(13035)<<"KateCodeCompletion::updateBox: Resizing widget"<<endl;
        m_completionPopup->resize(m_completionListBox->sizeHint() + QSize(2,2));
    QPoint p = m_view->mapToGlobal( m_view->cursorCoordinates() );
        int x = p.x();
        int y = p.y() ;
        if ( y + m_completionPopup->height() + m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height() > QApplication::desktop()->height() )
                y -= (m_completionPopup->height() );
        else
                y += m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height();

        if (x + m_completionPopup->width() > QApplication::desktop()->width())
                x = QApplication::desktop()->width() - m_completionPopup->width();

        m_completionPopup->move( QPoint(x,y) );

  m_completionListBox->setCurrentItem( 0 );
  m_completionListBox->setSelected( 0, true );
  m_completionListBox->setFocus();
  m_completionPopup->show();

  QTimer::singleShot(0,this,SLOT(showComment()));
}

void KateCodeCompletion::showArgHint ( QStringList functionList, const QString& strWrapping, const QString& strDelimiter )
{
  unsigned int line, col;
  m_view->cursorPositionReal( &line, &col );
  m_pArgHint->reset( line, col );
  m_pArgHint->setArgMarkInfos( strWrapping, strDelimiter );

  int nNum = 0;
  for( QStringList::Iterator it = functionList.begin(); it != functionList.end(); it++ )
  {
    kdDebug(13035) << "Insert function text: " << *it << endl;

    m_pArgHint->addFunction( nNum, ( *it ) );

    nNum++;
  }

  m_pArgHint->move(m_view->mapToGlobal(m_view->cursorCoordinates() + QPoint(0,m_view->renderer()->config()->fontMetrics( KateRendererConfig::ViewFont )->height())) );
  m_pArgHint->show();
}

void KateCodeCompletion::slotCursorPosChanged()
{
  m_pArgHint->cursorPositionChanged ( m_view, m_view->cursorLine(), m_view->cursorColumnReal() );
}

void KateCodeCompletion::showComment()
{
  CompletionItem* item = static_cast<CompletionItem*>(m_completionListBox->item(m_completionListBox->currentItem()));

  if( !item )
    return;
  if( item->m_entry.comment.isEmpty() )
    return;

  delete m_commentLabel;
  m_commentLabel = new KateCodeCompletionCommentLabel( 0, item->m_entry.comment );
  m_commentLabel->setFont(QToolTip::font());
  m_commentLabel->setPalette(QToolTip::palette());

  QPoint rightPoint = m_completionPopup->mapToGlobal(QPoint(m_completionPopup->width(),0));
  QPoint leftPoint = m_completionPopup->mapToGlobal(QPoint(0,0));
  QRect screen = QApplication::desktop()->screenGeometry( m_commentLabel->x11Screen() );
  QPoint finalPoint;
  if (rightPoint.x()+m_commentLabel->width() > screen.x() + screen.width())
    finalPoint.setX(leftPoint.x()-m_commentLabel->width());
  else
    finalPoint.setX(rightPoint.x());

  m_completionListBox->ensureCurrentVisible();

  finalPoint.setY(
    m_completionListBox->viewport()->mapToGlobal(m_completionListBox->itemRect(
      m_completionListBox->item(m_completionListBox->currentItem())).topLeft()).y());

  m_commentLabel->move(finalPoint);
  m_commentLabel->show();
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>


<commit_before>#include <QVector3D>
#include "kernel.h"
#include "ilwisdata.h"
#include "geometries.h"
#include "coordinatesystem.h"
#include "geos/geom/Geometry.h"
#include "geos/geom/CoordinateSequence.h"
#include "geos/geom/LineString.h"
#include "geos/geom/LinearRing.h"
#include "geos/geom/Polygon.h"
#include "geometryhelper.h"
#include "drawers/drawerinterface.h"
#include "ilwistesselator.h"

void* stdAlloc(void* userData, unsigned int size)
{
    int* allocated = ( int*)userData;
    TESS_NOTUSED(userData);
    *allocated += (int)size;
    return malloc(size);
}

void stdFree(void* userData, void* ptr)
{
    TESS_NOTUSED(userData);
    free(ptr);
}

using namespace Ilwis;
using namespace Geodrawer;

IlwisTesselator::IlwisTesselator()
{
    int allocated = 0;

    memset(&_ma, 0, sizeof(_ma));
    _ma.memalloc = stdAlloc;
    _ma.memfree = stdFree;
    _ma.userData = (void*)&allocated;
    _ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices.

    _tessaltor = tessNewTess(&_ma);
}

IlwisTesselator::~IlwisTesselator()
{
    tessDeleteTess(_tessaltor);
}

void IlwisTesselator::tesselate(const ICoordinateSystem &csyRoot,
                                const ICoordinateSystem &csyGeom,
                                const geos::geom::Geometry *geometry,
                                Raw objectid, QVector<QVector3D> &points,
                                std::vector<VertexIndex> &indices)
{
    tessReinitialize(_tessaltor);
    std::vector<std::vector<float> > contours = getContours(geometry, csyRoot, csyGeom);
    tesselateInternal(contours,objectid, points, indices);
}

std::vector<std::vector<float> > IlwisTesselator::getContours(const geos::geom::Geometry *geometry,const ICoordinateSystem &csyRoot, const ICoordinateSystem &csyGeom)
{

    bool conversionNeeded = csyRoot != csyGeom;
    const geos::geom::Polygon *polygon = dynamic_cast<const geos::geom::Polygon *>(geometry);
    const geos::geom::LineString *outerRing = polygon->getExteriorRing();
    std::vector<std::vector<float>> contours(1);
    contours[0].resize(outerRing->getNumPoints() * 2);

    auto addCoord = [&](const geos::geom::Coordinate& crd, int index, int i) {
        if ( conversionNeeded){
            Coordinate crdTransformed = csyRoot->coord2coord(csyGeom,crd);
            contours[index][i] = crdTransformed.x;
            contours[index][i+1] = crdTransformed.y;
        } else{
           contours[index][i] = crd.x;
           contours[index][i+1] = crd.y;
        }
    };

    for(int i = 0 ; i < outerRing->getNumPoints(); ++i){
        const geos::geom::Coordinate& crd = outerRing->getCoordinateN(i);
        addCoord(crd, 0, i * 2);
    }
    if ( polygon->getNumInteriorRing() > 0){
        contours.resize(polygon->getNumInteriorRing() + 1);
        for(int i = 0; i < polygon->getNumInteriorRing(); ++i){
            const geos::geom::LineString *innerRing = polygon->getInteriorRingN(i);
            contours[i + 1].resize(innerRing->getNumPoints() * 2); // contours[0] is outer ring
            for(int j = 0 ; j < innerRing->getNumPoints(); ++j){
                const geos::geom::Coordinate& crd = innerRing->getCoordinateN(j);
                addCoord(crd, i+1, j * 2);
            }
        }
    }
    return contours;
}

void IlwisTesselator::tesselateInternal(const std::vector<std::vector<float> > &contours, Raw objectid, QVector<QVector3D> &points, std::vector<VertexIndex> &indices)
{

    quint32 maxVerts = 50;
    for(int i = 0; i < contours.size(); ++i){
        int nverts = contours[i].size() / 2; // 2D coords
        tessAddContour(_tessaltor,2,contours[i].data(), sizeof(float) * 2, nverts);
    }
    if (!tessTesselate(_tessaltor, TESS_WINDING_ODD, TESS_POLYGONS, maxVerts, 2, 0))
        return;

    const float* verts = tessGetVertices(_tessaltor);
    const int* elems = tessGetElements(_tessaltor);
    const int nelems = tessGetElementCount(_tessaltor);

    for (int i = 0; i < nelems; ++i)
    {
        const int* p = &elems[i*maxVerts];
        quint32 oldend = points.size();
        for (int j = 0; j < maxVerts && p[j] != TESS_UNDEF; ++j){
            QVector3D pos(verts[p[j]*2], verts[p[j]*2+1],0);
            points.push_back(pos);
        }
        indices.push_back(VertexIndex(oldend,points.size() - oldend, GL_TRIANGLE_FAN, objectid));
    }

}
<commit_msg>boundaries are also generated by the tesselator<commit_after>#include <QVector3D>
#include "kernel.h"
#include "ilwisdata.h"
#include "geometries.h"
#include "coordinatesystem.h"
#include "geos/geom/Geometry.h"
#include "geos/geom/CoordinateSequence.h"
#include "geos/geom/LineString.h"
#include "geos/geom/LinearRing.h"
#include "geos/geom/Polygon.h"
#include "geometryhelper.h"
#include "drawers/drawerinterface.h"
#include "ilwistesselator.h"

void* stdAlloc(void* userData, unsigned int size)
{
    int* allocated = ( int*)userData;
    TESS_NOTUSED(userData);
    *allocated += (int)size;
    return malloc(size);
}

void stdFree(void* userData, void* ptr)
{
    TESS_NOTUSED(userData);
    free(ptr);
}

using namespace Ilwis;
using namespace Geodrawer;

IlwisTesselator::IlwisTesselator()
{
    int allocated = 0;

    memset(&_ma, 0, sizeof(_ma));
    _ma.memalloc = stdAlloc;
    _ma.memfree = stdFree;
    _ma.userData = (void*)&allocated;
    _ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices.

    _tessaltor = tessNewTess(&_ma);
}

IlwisTesselator::~IlwisTesselator()
{
    tessDeleteTess(_tessaltor);
}

void IlwisTesselator::tesselate(const ICoordinateSystem &csyRoot,
                                const ICoordinateSystem &csyGeom,
                                const geos::geom::Geometry *geometry,
                                Raw objectid, QVector<QVector3D> &points,
                                std::vector<VertexIndex> &indices)
{
    tessReinitialize(_tessaltor);
    std::vector<std::vector<float> > contours = getContours(geometry, csyRoot, csyGeom);
    tesselateInternal(contours,objectid, points, indices);
}

std::vector<std::vector<float> > IlwisTesselator::getContours(const geos::geom::Geometry *geometry,const ICoordinateSystem &csyRoot, const ICoordinateSystem &csyGeom)
{

    bool conversionNeeded = csyRoot != csyGeom;
    const geos::geom::Polygon *polygon = dynamic_cast<const geos::geom::Polygon *>(geometry);
    const geos::geom::LineString *outerRing = polygon->getExteriorRing();
    std::vector<std::vector<float>> contours(1);
    contours[0].resize(outerRing->getNumPoints() * 2);

    auto addCoord = [&](const geos::geom::Coordinate& crd, int index, int i) {
        if ( conversionNeeded){
            Coordinate crdTransformed = csyRoot->coord2coord(csyGeom,crd);
            contours[index][i] = crdTransformed.x;
            contours[index][i+1] = crdTransformed.y;
        } else{
           contours[index][i] = crd.x;
           contours[index][i+1] = crd.y;
        }
    };

    for(int i = 0 ; i < outerRing->getNumPoints(); ++i){
        const geos::geom::Coordinate& crd = outerRing->getCoordinateN(i);
        addCoord(crd, 0, i * 2);
    }
    if ( polygon->getNumInteriorRing() > 0){
        contours.resize(polygon->getNumInteriorRing() + 1);
        for(int i = 0; i < polygon->getNumInteriorRing(); ++i){
            const geos::geom::LineString *innerRing = polygon->getInteriorRingN(i);
            contours[i + 1].resize(innerRing->getNumPoints() * 2); // contours[0] is outer ring
            for(int j = 0 ; j < innerRing->getNumPoints(); ++j){
                const geos::geom::Coordinate& crd = innerRing->getCoordinateN(j);
                addCoord(crd, i+1, j * 2);
            }
        }
    }
    return contours;
}

void IlwisTesselator::tesselateInternal(const std::vector<std::vector<float> > &contours, Raw objectid, QVector<QVector3D> &points, std::vector<VertexIndex> &indices)
{

    quint32 maxVerts = 50;
    for(int i = 0; i < contours.size(); ++i){
        int nverts = contours[i].size() / 2; // 2D coords
        tessAddContour(_tessaltor,2,contours[i].data(), sizeof(float) * 2, nverts);
    }
    if (!tessTesselate(_tessaltor, TESS_WINDING_ODD, TESS_POLYGONS, maxVerts, 2, 0))
        return;

    const float* verts = tessGetVertices(_tessaltor);
    const int* elems = tessGetElements(_tessaltor);
    const int nelems = tessGetElementCount(_tessaltor);

    for (int i = 0; i < nelems; ++i)
    {
        const int* p = &elems[i*maxVerts];
        quint32 oldend = points.size();
        for (int j = 0; j < maxVerts && p[j] != TESS_UNDEF; ++j){
            QVector3D pos(verts[p[j]*2], verts[p[j]*2+1],0);
            points.push_back(pos);
        }
        indices.push_back(VertexIndex(oldend,points.size() - oldend, GL_TRIANGLE_FAN, objectid));
    }
    for(int  i = 0; i < contours.size(); ++i){
        quint32 oldend = points.size();
        points.resize(oldend + contours[i].size()/2);
        for(int j = 0; j < contours[i].size(); j+=2){
            points[oldend + j/2] = QVector3D(QPointF(contours[i][j], contours[i][j+1]));
        }
        indices.push_back(VertexIndex(oldend,points.size() - oldend, GL_LINE_STRIP, objectid));
    }

}
<|endoftext|>


<commit_before>/*
 * SaveHandler.cpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#include "persistence/base/SaveHandler.hpp"

#include <string>
#include <sstream> // used for addReferences()

#include "boost/algorithm/string.hpp" // used for string splitting
#include "ecore/EObject.hpp"
#include "persistence/base/HandlerHelper.hpp"

using namespace persistence::base;

SaveHandler::SaveHandler()
{
	m_rootObject = nullptr;
	m_isXSIMode = true;
	m_savedObjects.reset(new Bag<ecore::EObject>());
}

SaveHandler::~SaveHandler()
{
}

/**/
std::string SaveHandler::getPrefix()
{
	return m_rootPrefix;
}

void SaveHandler::setRootObject(std::shared_ptr<ecore::EObject> object)
{
	if (m_rootObject == nullptr)
	{
		m_rootObject = object;
	}
}

void SaveHandler::addAttribute(const std::string &name, bool value)
{
	addAttribute(name, (value ? (std::string) "true" : (std::string) "false"));
}

void SaveHandler::addReference(const std::string &name, std::shared_ptr<ecore::EObject> object)
{
	if (object)
	{
		std::string ref = persistence::base::HandlerHelper::extractReference(object, m_rootObject, m_rootPrefix);

		addAttribute(name, ref);
	}
}

std::string SaveHandler::extractType(std::shared_ptr<ecore::EObject> obj) const
{
	return persistence::base::HandlerHelper::extractType(obj, m_rootPrefix);
}

void SaveHandler::addReference(const std::shared_ptr<ecore::EObject> object, const std::string &tagName, const bool typeRequired)
{
	if (object == nullptr)
	{
		return;
	}

	if (m_savedObjects->find(object) != -1)
	{
		return;
	}

	m_savedObjects->push_back(object);

	// 1. Create and add Node-Element to model-tree
	createAndAddElement(tagName);

	if (!m_isXSIMode)
	{
		auto iter = m_refToObject_map.find(object);
		if (iter != m_refToObject_map.end())
		{
			addAttribute("xmi:id", iter->second);
		}
		else
		{
			std::cout << "id not found for tag name '" << tagName << "'" << std::endl;
		}
	}

	if(typeRequired)
	{
		// 1.x Set Attribute "xsi:type" to the specific Class-Type
		if (m_isXSIMode)
		{
			addAttribute("xsi:type", extractType(object));
		}
		else
		{
			addAttribute("xmi:type", extractType(object));
		}
	}

	// 2. Recursive call of save()
	object->save(m_thisPtr);

	// 3. Tell saveHandler for stepping to previous level
	release();
}

void SaveHandler::setThisPtr(std::shared_ptr<SaveHandler> thisPtr)
{
	m_thisPtr = thisPtr;
}

void SaveHandler::setIsXSIMode(bool value)
{
	m_isXSIMode = value;
}

void SaveHandler::setTypesMap(std::map<std::string, std::shared_ptr<ecore::EObject>> typesMap)
{
	std::map<std::string, std::shared_ptr<ecore::EObject>>::iterator iter = typesMap.begin();
	std::map<std::string, std::shared_ptr<ecore::EObject>>::iterator end = typesMap.end();
	while (iter != end)
	{
		m_refToObject_map.insert(std::pair<std::shared_ptr<ecore::EObject>, std::string>(iter->second, iter->first));
		iter++;
	}
}
<commit_msg>[persistence] check typesList for reference string before calculating it<commit_after>/*
 * SaveHandler.cpp
 *
 *  Created on: 29.05.2017
 *      Author: Alexander
 */

#include "persistence/base/SaveHandler.hpp"

#include <string>
#include <sstream> // used for addReferences()

#include "boost/algorithm/string.hpp" // used for string splitting
#include "ecore/EObject.hpp"
#include "persistence/base/HandlerHelper.hpp"

using namespace persistence::base;

SaveHandler::SaveHandler()
{
	m_rootObject = nullptr;
	m_isXSIMode = true;
	m_savedObjects.reset(new Bag<ecore::EObject>());
}

SaveHandler::~SaveHandler()
{
}

/**/
std::string SaveHandler::getPrefix()
{
	return m_rootPrefix;
}

void SaveHandler::setRootObject(std::shared_ptr<ecore::EObject> object)
{
	if (m_rootObject == nullptr)
	{
		m_rootObject = object;
	}
}

void SaveHandler::addAttribute(const std::string &name, bool value)
{
	addAttribute(name, (value ? (std::string) "true" : (std::string) "false"));
}

void SaveHandler::addReference(const std::string &name, std::shared_ptr<ecore::EObject> object)
{
	if (object)
	{
		std::string ref = "";
		auto iter = m_refToObject_map.find(object);
		if (iter != m_refToObject_map.end())
		{
			ref = iter->second;
		}
		else
		{
			ref = persistence::base::HandlerHelper::extractReference(object, m_rootObject, m_rootPrefix);
		}

		addAttribute(name, ref);
	}
}

std::string SaveHandler::extractType(std::shared_ptr<ecore::EObject> obj) const
{
	return persistence::base::HandlerHelper::extractType(obj, m_rootPrefix);
}

void SaveHandler::addReference(const std::shared_ptr<ecore::EObject> object, const std::string &tagName, const bool typeRequired)
{
	if (object == nullptr)
	{
		return;
	}

	if (m_savedObjects->find(object) != -1)
	{
		return;
	}

	m_savedObjects->push_back(object);

	// 1. Create and add Node-Element to model-tree
	createAndAddElement(tagName);

	if (!m_isXSIMode)
	{
		auto iter = m_refToObject_map.find(object);
		if (iter != m_refToObject_map.end())
		{
			addAttribute("xmi:id", iter->second);
		}
		else
		{
			std::cout << "id not found for tag name '" << tagName << "'" << std::endl;
		}
	}

	if(typeRequired)
	{
		// 1.x Set Attribute "xsi:type" to the specific Class-Type
		if (m_isXSIMode)
		{
			addAttribute("xsi:type", extractType(object));
		}
		else
		{
			addAttribute("xmi:type", extractType(object));
		}
	}

	// 2. Recursive call of save()
	object->save(m_thisPtr);

	// 3. Tell saveHandler for stepping to previous level
	release();
}

void SaveHandler::setThisPtr(std::shared_ptr<SaveHandler> thisPtr)
{
	m_thisPtr = thisPtr;
}

void SaveHandler::setIsXSIMode(bool value)
{
	m_isXSIMode = value;
}

void SaveHandler::setTypesMap(std::map<std::string, std::shared_ptr<ecore::EObject>> typesMap)
{
	std::map<std::string, std::shared_ptr<ecore::EObject>>::iterator iter = typesMap.begin();
	std::map<std::string, std::shared_ptr<ecore::EObject>>::iterator end = typesMap.end();
	while (iter != end)
	{
		m_refToObject_map.insert(std::pair<std::shared_ptr<ecore::EObject>, std::string>(iter->second, iter->first));
		iter++;
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ProgressBarHelper.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: sab $ $Date: 2001-09-25 10:29:18 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

//___________________________________________________________________

#ifndef _XMLOFF_PROGRESSBARHELPER_HXX
#include "ProgressBarHelper.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

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

const sal_Int32 nDefaultProgressBarRange = 1000000;
const float fProgressStep = 0.5;

ProgressBarHelper::ProgressBarHelper(const ::com::sun::star::uno::Reference < ::com::sun::star::task::XStatusIndicator>& xTempStatusIndicator,
                                    const sal_Bool bTempStrict)
    : fOldPercent(0.0),
    nRange(nDefaultProgressBarRange),
    xStatusIndicator(xTempStatusIndicator),
    nReference(0),
    nValue(0),
    bStrict(bTempStrict)
{
}

ProgressBarHelper::~ProgressBarHelper()
{
}

sal_Int32 ProgressBarHelper::ChangeReference(sal_Int32 nNewReference)
{
    if((nNewReference > 0) && (nNewReference != nReference))
    {
        if (nReference)
        {
            double fPercent(nNewReference / nReference);
            double fValue(nValue * fPercent);
            nValue = sal_Int32(nValue);
            nReference = nNewReference;
        }
        else
        {
            nReference = nNewReference;
            nValue = 0;
        }
    }
    return nValue;
}

void ProgressBarHelper::SetValue(sal_Int32 nTempValue)
{
    if ((nTempValue >= nValue) && (!bStrict || (bStrict && (nTempValue <= nReference))))
    {
        // #91317# no progress bar with values > 100%
        nValue = (nTempValue > nReference) ? nReference : nTempValue;
        if (xStatusIndicator.is() && (nReference > 0))
        {
            double fValue(nValue);
            double fNewValue ((fValue * nRange) / nReference);
            double fPercent ((fNewValue * 100) / nRange);
            if (fPercent >= (fOldPercent + fProgressStep))
            {
                xStatusIndicator->setValue((sal_Int32)fNewValue);
                fOldPercent = fPercent;
            }
        }
    }
    else
        DBG_ERROR("tried to set a wrong value on the progressbar");
}

<commit_msg>#91949# prevent 'set wrong value on ProgressBar' assertion if no reference value is set<commit_after>/*************************************************************************
 *
 *  $RCSfile: ProgressBarHelper.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: dvo $ $Date: 2001-10-12 13:56:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

//___________________________________________________________________

#ifndef _XMLOFF_PROGRESSBARHELPER_HXX
#include "ProgressBarHelper.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

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

const sal_Int32 nDefaultProgressBarRange = 1000000;
const float fProgressStep = 0.5;

ProgressBarHelper::ProgressBarHelper(const ::com::sun::star::uno::Reference < ::com::sun::star::task::XStatusIndicator>& xTempStatusIndicator,
                                    const sal_Bool bTempStrict)
    : fOldPercent(0.0),
    nRange(nDefaultProgressBarRange),
    xStatusIndicator(xTempStatusIndicator),
    nReference(0),
    nValue(0),
    bStrict(bTempStrict)
{
}

ProgressBarHelper::~ProgressBarHelper()
{
}

sal_Int32 ProgressBarHelper::ChangeReference(sal_Int32 nNewReference)
{
    if((nNewReference > 0) && (nNewReference != nReference))
    {
        if (nReference)
        {
            double fPercent(nNewReference / nReference);
            double fValue(nValue * fPercent);
            nValue = sal_Int32(nValue);
            nReference = nNewReference;
        }
        else
        {
            nReference = nNewReference;
            nValue = 0;
        }
    }
    return nValue;
}

void ProgressBarHelper::SetValue(sal_Int32 nTempValue)
{
    if (xStatusIndicator.is() && (nReference > 0))
    {
        if ((nTempValue >= nValue) && (!bStrict || (bStrict && (nTempValue <= nReference))))
        {
            // #91317# no progress bar with values > 100%
            nValue = (nTempValue > nReference) ? nReference : nTempValue;

            double fValue(nValue);
            double fNewValue ((fValue * nRange) / nReference);
            double fPercent ((fNewValue * 100) / nRange);
            if (fPercent >= (fOldPercent + fProgressStep))
            {
                xStatusIndicator->setValue((sal_Int32)fNewValue);
                fOldPercent = fPercent;
            }
        }
        else
            DBG_ERROR("tried to set a wrong value on the progressbar");
    }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: PropertySetMerger.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: cl $ $Date: 2000-11-08 11:30:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSTATE_HPP_
#include <com/sun/star/beans/XPropertyState.hpp>
#endif

#ifndef _XMLOFF_PROPERTYSETMERGER_HXX_
#include "PropertySetMerger.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase3.hxx>
#endif

class SvXMLAttrContainerItem_Impl;

class PropertySetMergerImpl : public ::cppu::WeakAggImplHelper3< XPropertySet, XPropertyState, XPropertySetInfo >
{
private:
    Reference< XPropertySet > mxPropSet1;
    Reference< XPropertyState > mxPropSet1State;
    Reference< XPropertySetInfo > mxPropSet1Info;

    Reference< XPropertySet > mxPropSet2;
    Reference< XPropertyState > mxPropSet2State;
    Reference< XPropertySetInfo > mxPropSet2Info;

public:
    PropertySetMergerImpl( const Reference< XPropertySet > rPropSet1, const Reference< XPropertySet > rPropSet2 );
    virtual ~PropertySetMergerImpl();

    // XPropertySet
    virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(RuntimeException);
    virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException);
    virtual Any SAL_CALL getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);

    // XPropertyState
    virtual PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual Sequence< PropertyState > SAL_CALL getPropertyStates( const Sequence< OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);

    // XPropertySetInfo
    virtual Sequence< Property > SAL_CALL getProperties(  ) throw(RuntimeException);
    virtual Property SAL_CALL getPropertyByName( const OUString& aName ) throw(UnknownPropertyException, RuntimeException);
    virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) throw(RuntimeException);
};

// --------------------------------------------------------------------
// Interface implementation
// --------------------------------------------------------------------

PropertySetMergerImpl::PropertySetMergerImpl( Reference< XPropertySet > rPropSet1, Reference< XPropertySet > rPropSet2 )
: mxPropSet1( rPropSet1 ), mxPropSet2( rPropSet2 ),
  mxPropSet1State( rPropSet1, UNO_QUERY ), mxPropSet2State( rPropSet2, UNO_QUERY ),
  mxPropSet1Info( rPropSet1->getPropertySetInfo() ), mxPropSet2Info( rPropSet2->getPropertySetInfo() )
{
}

PropertySetMergerImpl::~PropertySetMergerImpl()
{
}

// XPropertySet
Reference< XPropertySetInfo > SAL_CALL PropertySetMergerImpl::getPropertySetInfo(  ) throw(RuntimeException)
{
    return this;
}

void SAL_CALL PropertySetMergerImpl::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( aPropertyName ) )
    {
        mxPropSet1->setPropertyValue( aPropertyName, aValue );
    }
    else
    {
        mxPropSet2->setPropertyValue( aPropertyName, aValue );
    }
}

Any SAL_CALL PropertySetMergerImpl::getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        return mxPropSet1->getPropertyValue( PropertyName );
    }
    else
    {
        return mxPropSet2->getPropertyValue( PropertyName );
    }
}

void SAL_CALL PropertySetMergerImpl::addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

// XPropertyState
PropertyState SAL_CALL PropertySetMergerImpl::getPropertyState( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        if( mxPropSet1State.is() )
        {
            return mxPropSet1State->getPropertyState( PropertyName );
        }
        else
        {
            return PropertyState_DIRECT_VALUE;
        }
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            return mxPropSet2State->getPropertyState( PropertyName );
        }
        else
        {
            return PropertyState_DIRECT_VALUE;
        }
    }
}

Sequence< PropertyState > SAL_CALL PropertySetMergerImpl::getPropertyStates( const Sequence< OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    const sal_Int32 nCount = aPropertyName.getLength();
    Sequence< PropertyState > aPropStates( nCount );
    PropertyState* pPropStates = aPropStates.getArray();
    const OUString* pPropNames = aPropertyName.getConstArray();

    sal_Int32 nIndex;
    for( nIndex = 0; nIndex < nCount; nIndex++ )
        *pPropStates++ = getPropertyState( *pPropNames++ );

    return aPropStates;
}

void SAL_CALL PropertySetMergerImpl::setPropertyToDefault( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1State.is() && mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        mxPropSet1State->setPropertyToDefault( PropertyName );
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            mxPropSet2State->setPropertyToDefault( PropertyName );
        }
    }
}

Any SAL_CALL PropertySetMergerImpl::getPropertyDefault( const OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1State.is() && mxPropSet1Info->hasPropertyByName( aPropertyName ) )
    {
        return mxPropSet1State->getPropertyDefault( aPropertyName );
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            return mxPropSet2State->getPropertyDefault( aPropertyName );
        }
        else
        {
            Any aAny;
            return aAny;
        }
    }
}

// XPropertySetInfo
Sequence< Property > SAL_CALL PropertySetMergerImpl::getProperties() throw(RuntimeException)
{
    Sequence< Property > aProps1( mxPropSet1Info->getProperties() );
    const Property* pProps1 = aProps1.getArray();
    const sal_Int32 nCount1 = aProps1.getLength();

    Sequence< Property > aProps2( mxPropSet1Info->getProperties() );
    const Property* pProps2 = aProps2.getArray();
    const sal_Int32 nCount2 = aProps2.getLength();

    Sequence< Property > aProperties( nCount1 + nCount2 );

    sal_Int32 nIndex;

    Property* pProperties;

    for( nIndex = 0; nIndex < nCount1; nIndex++ )
        *pProperties++ = *pProps1++;

    for( nIndex = 0; nIndex < nCount2; nIndex++ )
        *pProperties++ = *pProps2++;

    return aProperties;
}

Property SAL_CALL PropertySetMergerImpl::getPropertyByName( const OUString& aName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( aName ) )
        return mxPropSet1Info->getPropertyByName( aName );

    return mxPropSet2Info->getPropertyByName( aName );
}

sal_Bool SAL_CALL PropertySetMergerImpl::hasPropertyByName( const OUString& Name ) throw(RuntimeException)
{
    if(mxPropSet1Info->hasPropertyByName( Name ) )
        return sal_True;

    return mxPropSet2Info->hasPropertyByName( Name );
}

Reference< XPropertySet > PropertySetMerger_CreateInstance( Reference< XPropertySet > rPropSet1, Reference< XPropertySet > rPropSet2 ) throw()
{
    return new PropertySetMergerImpl( rPropSet1, rPropSet2 );
}
<commit_msg>INTEGRATION: CWS oasisbf1 (1.1.386); FILE MERGED 2004/10/14 10:09:13 mib 1.1.386.1: 'i31063#: unitialized variable in getProperties<commit_after>/*************************************************************************
 *
 *  $RCSfile: PropertySetMerger.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-09 12:14:04 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSTATE_HPP_
#include <com/sun/star/beans/XPropertyState.hpp>
#endif

#ifndef _XMLOFF_PROPERTYSETMERGER_HXX_
#include "PropertySetMerger.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase3.hxx>
#endif

class SvXMLAttrContainerItem_Impl;

class PropertySetMergerImpl : public ::cppu::WeakAggImplHelper3< XPropertySet, XPropertyState, XPropertySetInfo >
{
private:
    Reference< XPropertySet > mxPropSet1;
    Reference< XPropertyState > mxPropSet1State;
    Reference< XPropertySetInfo > mxPropSet1Info;

    Reference< XPropertySet > mxPropSet2;
    Reference< XPropertyState > mxPropSet2State;
    Reference< XPropertySetInfo > mxPropSet2Info;

public:
    PropertySetMergerImpl( const Reference< XPropertySet > rPropSet1, const Reference< XPropertySet > rPropSet2 );
    virtual ~PropertySetMergerImpl();

    // XPropertySet
    virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(RuntimeException);
    virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException);
    virtual Any SAL_CALL getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);
    virtual void SAL_CALL removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);

    // XPropertyState
    virtual PropertyState SAL_CALL getPropertyState( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual Sequence< PropertyState > SAL_CALL getPropertyStates( const Sequence< OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual void SAL_CALL setPropertyToDefault( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException);
    virtual Any SAL_CALL getPropertyDefault( const OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException);

    // XPropertySetInfo
    virtual Sequence< Property > SAL_CALL getProperties(  ) throw(RuntimeException);
    virtual Property SAL_CALL getPropertyByName( const OUString& aName ) throw(UnknownPropertyException, RuntimeException);
    virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) throw(RuntimeException);
};

// --------------------------------------------------------------------
// Interface implementation
// --------------------------------------------------------------------

PropertySetMergerImpl::PropertySetMergerImpl( Reference< XPropertySet > rPropSet1, Reference< XPropertySet > rPropSet2 )
: mxPropSet1( rPropSet1 ), mxPropSet2( rPropSet2 ),
  mxPropSet1State( rPropSet1, UNO_QUERY ), mxPropSet2State( rPropSet2, UNO_QUERY ),
  mxPropSet1Info( rPropSet1->getPropertySetInfo() ), mxPropSet2Info( rPropSet2->getPropertySetInfo() )
{
}

PropertySetMergerImpl::~PropertySetMergerImpl()
{
}

// XPropertySet
Reference< XPropertySetInfo > SAL_CALL PropertySetMergerImpl::getPropertySetInfo(  ) throw(RuntimeException)
{
    return this;
}

void SAL_CALL PropertySetMergerImpl::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( aPropertyName ) )
    {
        mxPropSet1->setPropertyValue( aPropertyName, aValue );
    }
    else
    {
        mxPropSet2->setPropertyValue( aPropertyName, aValue );
    }
}

Any SAL_CALL PropertySetMergerImpl::getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        return mxPropSet1->getPropertyValue( PropertyName );
    }
    else
    {
        return mxPropSet2->getPropertyValue( PropertyName );
    }
}

void SAL_CALL PropertySetMergerImpl::addPropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& xListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::removePropertyChangeListener( const OUString& aPropertyName, const Reference< XPropertyChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::addVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

void SAL_CALL PropertySetMergerImpl::removeVetoableChangeListener( const OUString& PropertyName, const Reference< XVetoableChangeListener >& aListener ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
}

// XPropertyState
PropertyState SAL_CALL PropertySetMergerImpl::getPropertyState( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        if( mxPropSet1State.is() )
        {
            return mxPropSet1State->getPropertyState( PropertyName );
        }
        else
        {
            return PropertyState_DIRECT_VALUE;
        }
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            return mxPropSet2State->getPropertyState( PropertyName );
        }
        else
        {
            return PropertyState_DIRECT_VALUE;
        }
    }
}

Sequence< PropertyState > SAL_CALL PropertySetMergerImpl::getPropertyStates( const Sequence< OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    const sal_Int32 nCount = aPropertyName.getLength();
    Sequence< PropertyState > aPropStates( nCount );
    PropertyState* pPropStates = aPropStates.getArray();
    const OUString* pPropNames = aPropertyName.getConstArray();

    sal_Int32 nIndex;
    for( nIndex = 0; nIndex < nCount; nIndex++ )
        *pPropStates++ = getPropertyState( *pPropNames++ );

    return aPropStates;
}

void SAL_CALL PropertySetMergerImpl::setPropertyToDefault( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1State.is() && mxPropSet1Info->hasPropertyByName( PropertyName ) )
    {
        mxPropSet1State->setPropertyToDefault( PropertyName );
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            mxPropSet2State->setPropertyToDefault( PropertyName );
        }
    }
}

Any SAL_CALL PropertySetMergerImpl::getPropertyDefault( const OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
{
    if( mxPropSet1State.is() && mxPropSet1Info->hasPropertyByName( aPropertyName ) )
    {
        return mxPropSet1State->getPropertyDefault( aPropertyName );
    }
    else
    {
        if( mxPropSet2State.is() )
        {
            return mxPropSet2State->getPropertyDefault( aPropertyName );
        }
        else
        {
            Any aAny;
            return aAny;
        }
    }
}

// XPropertySetInfo
Sequence< Property > SAL_CALL PropertySetMergerImpl::getProperties() throw(RuntimeException)
{
    Sequence< Property > aProps1( mxPropSet1Info->getProperties() );
    const Property* pProps1 = aProps1.getArray();
    const sal_Int32 nCount1 = aProps1.getLength();

    Sequence< Property > aProps2( mxPropSet1Info->getProperties() );
    const Property* pProps2 = aProps2.getArray();
    const sal_Int32 nCount2 = aProps2.getLength();

    Sequence< Property > aProperties( nCount1 + nCount2 );

    sal_Int32 nIndex;

    Property* pProperties = aProperties.getArray();

    for( nIndex = 0; nIndex < nCount1; nIndex++ )
        *pProperties++ = *pProps1++;

    for( nIndex = 0; nIndex < nCount2; nIndex++ )
        *pProperties++ = *pProps2++;

    return aProperties;
}

Property SAL_CALL PropertySetMergerImpl::getPropertyByName( const OUString& aName ) throw(UnknownPropertyException, RuntimeException)
{
    if( mxPropSet1Info->hasPropertyByName( aName ) )
        return mxPropSet1Info->getPropertyByName( aName );

    return mxPropSet2Info->getPropertyByName( aName );
}

sal_Bool SAL_CALL PropertySetMergerImpl::hasPropertyByName( const OUString& Name ) throw(RuntimeException)
{
    if(mxPropSet1Info->hasPropertyByName( Name ) )
        return sal_True;

    return mxPropSet2Info->hasPropertyByName( Name );
}

Reference< XPropertySet > PropertySetMerger_CreateInstance( Reference< XPropertySet > rPropSet1, Reference< XPropertySet > rPropSet2 ) throw()
{
    return new PropertySetMergerImpl( rPropSet1, rPropSet2 );
}
<|endoftext|>


<commit_before>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/fmt/format.hpp"
#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/range/v3/view/drop.hpp"
#include "vendor/range/v3/view/transform.hpp"
#include "vendor/range/v3/view/chunk.hpp"
#include "vendor/range/v3/to_container.hpp"
#include "vendor/range/v3/numeric/accumulate.hpp"
#include "vendor/docopt/docopt.hpp"
#include <thewizardplusplus/wizard_parser/lexer/lexeme.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/parser/rule_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/dummy_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/typing_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/match_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/concatenation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/lookahead_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/repetition_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/alternation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/ast_node.hpp>
#include <thewizardplusplus/wizard_parser/parser/parse.hpp>
#include <thewizardplusplus/wizard_parser/lexer/token.hpp>
#include <unordered_map>
#include <string>
#include <cstddef>
#include <functional>
#include <vector>
#include <stdexcept>
#include <cstdint>
#include <regex>
#include <iostream>
#include <cstdlib>
#include <iterator>
#include <sstream>
#include <limits>
#include <iomanip>
#include <exception>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

using constant_group = std::unordered_map<std::string, double>;

struct function final {
	const std::size_t arity;
	const std::function<double(const std::vector<double>&)> handler;
};

using function_group = std::unordered_map<std::string, function>;

struct positional_exception: std::runtime_error {
	const std::string description;
	const std::size_t offset;

	positional_exception(
		const std::string& description,
		const std::size_t& offset
	);
};

positional_exception::positional_exception(
	const std::string& description,
	const std::size_t& offset
):
	std::runtime_error{fmt::format("{:s} (offset: {:d})", description, offset)},
	description{description},
	offset{offset}
{}

BETTER_ENUM(entity_type, std::uint8_t,
	symbol,
	token,
	eoi,
	node,
	constant,
	function
)

template<entity_type::_integral type>
struct unexpected_entity_exception final: positional_exception {
	static_assert(entity_type::_is_valid(type));

	explicit unexpected_entity_exception(const std::size_t& offset);
};

template<entity_type::_integral type>
unexpected_entity_exception<type>::unexpected_entity_exception(
	const std::size_t& offset
):
	positional_exception{
		fmt::format(
			"unexpected {:s}",
			entity_type::_from_integral(type)._to_string()
		),
		offset
	}
{}

const auto usage =
R"(Usage:
  ./example [options] [--] [<expression>]

Options:
  -h, --help                           - show this message;
  -t TARGET, --target TARGET           - preliminary target of processing
                                       (allowed: tokens, cst);
  -p PRECISION, --precision PRECISION  - precision of a result;
  -s, --stdin                          - read an expression from stdin.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{"-"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{"/"}, "slash"},
	{std::regex{"%"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{","}, "comma"},
	{std::regex{R"(\d+(?:\.\d+)?(?:e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};
const auto exceptions = lexer::exception_group{"whitespace"};
// Boost 1.70.0, Math Toolkit 2.9.0
const auto constants = constant_group{
	{"pi", 3.141592653589793238462643383279502884},
	{"e", 2.718281828459045235360287471352662497}
};
const auto functions = function_group{
	{"+", {2, [] (const auto& arguments) {
		return arguments.front() + arguments.back();
	}}},
	{"-", {2, [] (const auto& arguments) {
		return arguments.front() - arguments.back();
	}}},
	{"*", {2, [] (const auto& arguments) {
		return arguments.front() * arguments.back();
	}}},
	{"/", {2, [] (const auto& arguments) {
		return arguments.front() / arguments.back();
	}}},
	{"%", {2, [] (const auto& arguments) {
		return static_cast<std::int64_t>(arguments.front())
			% static_cast<std::int64_t>(arguments.back());
	}}},
	{"floor", {1, [] (const auto& arguments) {
		return std::floor(arguments.front());
	}}},
	{"ceil", {1, [] (const auto& arguments) {
		return std::ceil(arguments.front());
	}}},
	{"trunc", {1, [] (const auto& arguments) {
		return std::trunc(arguments.front());
	}}},
	{"round", {1, [] (const auto& arguments) {
		return std::round(arguments.front());
	}}},
	{"sin", {1, [] (const auto& arguments) {
		return std::sin(arguments.front());
	}}},
	{"cos", {1, [] (const auto& arguments) {
		return std::cos(arguments.front());
	}}},
	{"tn", {1, [] (const auto& arguments) {
		return std::tan(arguments.front());
	}}},
	{"arcsin", {1, [] (const auto& arguments) {
		return std::asin(arguments.front());
	}}},
	{"arccos", {1, [] (const auto& arguments) {
		return std::acos(arguments.front());
	}}},
	{"arctn", {1, [] (const auto& arguments) {
		return std::atan(arguments.front());
	}}},
	{"angle", {2, [] (const auto& arguments) {
		return std::atan2(arguments.back(), arguments.front());
	}}},
	{"pow", {2, [] (const auto& arguments) {
		return std::pow(arguments.front(), arguments.back());
	}}},
	{"sqrt", {1, [] (const auto& arguments) {
		return std::sqrt(arguments.front());
	}}},
	{"exp", {1, [] (const auto& arguments) {
		return std::exp(arguments.front());
	}}},
	{"ln", {1, [] (const auto& arguments) {
		return std::log(arguments.front());
	}}},
	{"lg", {1, [] (const auto& arguments) {
		return std::log10(arguments.front());
	}}},
	{"abs", {1, [] (const auto& arguments) {
		return std::abs(arguments.front());
	}}},
};

template<typename streamable>
void stop(const int& code, std::ostream& stream, const streamable& message) {
	stream << message << '\n';
	std::exit(code);
}

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy >> *(&","_v >> expression_dummy))
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary >> *(("*"_v | "/"_v | "%"_v) >> unary);
	RULE(sum) = product >> *(("+"_v | "-"_v) >> product);
	expression_dummy->set_parser(sum);

	return sum;
}

const parser::ast_node_group& inspect_sequence(const parser::ast_node& ast) {
	return ast.children.front().children;
}

double evaluate_ast_node(
	const parser::ast_node& ast,
	const constant_group& constants,
	const function_group& functions
) {
	const auto evaluate_with_context = [&] (const auto& ast) {
		return evaluate_ast_node(ast, constants, functions);
	};

	if (ast.type == "number") {
		return std::stod(ast.value, nullptr);
	} else if (ast.type == "identifier") {
		try {
			return constants.at(ast.value);
		} catch (const std::out_of_range& exception) {
			throw unexpected_entity_exception<entity_type::constant>{
				parser::get_offset(ast)
			};
		}
	} else if (ast.type == "atom") {
		const auto type = (+parser::ast_node_type::sequence)._to_string();
		const auto first_child = ast.children.front().type == type
			? inspect_sequence(ast).front()
			: ast.children.front();
		return evaluate_with_context(first_child);
	} else if (ast.type == "unary") {
		const auto result = evaluate_with_context(inspect_sequence(ast).back());
		const auto sign = (inspect_sequence(ast).size()-1) % 2 ? -1 : 1;
		return sign * result;
	} else if (ast.type == "function_call") {
		try {
			const auto name = inspect_sequence(ast).front().value;
			const auto arguments = inspect_sequence(ast)
				| ranges::view::drop(1)
				| ranges::view::transform([&] (const auto& ast) {
					return evaluate_with_context(ast);
				});
			const auto function = functions.at(name);
			if (arguments.size() != function.arity) {
				throw positional_exception{
					fmt::format(
						"function requires {:d} {:s}",
						function.arity,
						function.arity == 1 ? "argument" : "arguments"
					),
					parser::get_offset(ast)
				};
			}

			return function.handler(arguments);
		} catch (const std::out_of_range& exception) {
			throw unexpected_entity_exception<entity_type::function>{
				parser::get_offset(ast)
			};
		}
	} else if (ast.type == "product" || ast.type == "sum") {
		const auto first_operand =
			evaluate_with_context(inspect_sequence(ast).front());
		const auto children_chunks = inspect_sequence(ast)
			| ranges::view::drop(1)
			| ranges::view::chunk(2)
			| ranges::view::transform([] (const auto& chunk) {
				return chunk | ranges::to_<parser::ast_node_group>();
			});
		return ranges::accumulate(
			children_chunks,
			first_operand,
			[&] (const auto& result, const auto& chunk) {
				const auto name = chunk.front().value;
				const auto second_operand = evaluate_with_context(chunk.back());
				return functions.at(name).handler({result, second_operand});
			}
		);
	} else {
		throw unexpected_entity_exception<entity_type::node>{parser::get_offset(ast)};
	}
}

int main(int argc, char* argv[]) try {
	const auto options = docopt::docopt(usage, {argv+1, argv+argc}, true);
	const auto expression = options.at("<expression>")
		? options.at("<expression>").asString()
		: "";
	const auto code = options.at("--stdin").asBool()
		? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
		: expression;
	auto [tokens, rest_offset] = lexer::tokenize(lexemes, exceptions, code);
	if (rest_offset != code.size()) {
		throw unexpected_entity_exception<entity_type::symbol>{rest_offset};
	}
	if (options.at("--target") == "tokens"s) {
		stop(EXIT_SUCCESS, std::cout, tokens);
	}

	const auto ast = parser::parse(make_parser(), tokens);
	if (!ast.rest_tokens.empty()) {
		throw unexpected_entity_exception<entity_type::token>{
			lexer::get_offset(ast.rest_tokens)
		};
	}
	if (!ast.node) {
		throw unexpected_entity_exception<entity_type::eoi>{code.size()};
	}
	if (options.at("--target") == "cst"s) {
		stop(EXIT_SUCCESS, std::cout, *ast.node);
	}

	auto buffer = std::ostringstream{};
	const auto precision = options.at("--precision")
		? options.at("--precision").asLong()
		: std::numeric_limits<double>::max_digits10;
	const auto result = evaluate_ast_node(*ast.node, constants, functions);
	buffer << std::setprecision(precision) << result;

	stop(EXIT_SUCCESS, std::cout, buffer.str());
} catch (const std::exception& exception) {
	stop(EXIT_FAILURE, std::cerr, fmt::format("error: {:s}", exception.what()));
}
<commit_msg>Add the `exceptions` module, add the `positional_exception` class: use it in the example<commit_after>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/fmt/format.hpp"
#include "vendor/range/v3/view/drop.hpp"
#include "vendor/range/v3/view/transform.hpp"
#include "vendor/range/v3/view/chunk.hpp"
#include "vendor/range/v3/to_container.hpp"
#include "vendor/range/v3/numeric/accumulate.hpp"
#include "vendor/docopt/docopt.hpp"
#include <thewizardplusplus/wizard_parser/exceptions/positional_exception.hpp>
#include <thewizardplusplus/wizard_parser/lexer/lexeme.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/parser/rule_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/dummy_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/typing_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/match_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/concatenation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/lookahead_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/repetition_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/alternation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/ast_node.hpp>
#include <thewizardplusplus/wizard_parser/parser/parse.hpp>
#include <thewizardplusplus/wizard_parser/lexer/token.hpp>
#include <unordered_map>
#include <string>
#include <cstddef>
#include <functional>
#include <vector>
#include <cstdint>
#include <regex>
#include <iostream>
#include <cstdlib>
#include <iterator>
#include <sstream>
#include <limits>
#include <iomanip>
#include <exception>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

using constant_group = std::unordered_map<std::string, double>;

struct function final {
	const std::size_t arity;
	const std::function<double(const std::vector<double>&)> handler;
};

using function_group = std::unordered_map<std::string, function>;

BETTER_ENUM(entity_type, std::uint8_t,
	symbol,
	token,
	eoi,
	node,
	constant,
	function
)

template<entity_type::_integral type>
struct unexpected_entity_exception final: exceptions::positional_exception {
	static_assert(entity_type::_is_valid(type));

	explicit unexpected_entity_exception(const std::size_t& offset);
};

template<entity_type::_integral type>
unexpected_entity_exception<type>::unexpected_entity_exception(
	const std::size_t& offset
):
	exceptions::positional_exception{
		fmt::format(
			"unexpected {:s}",
			entity_type::_from_integral(type)._to_string()
		),
		offset
	}
{}

const auto usage =
R"(Usage:
  ./example [options] [--] [<expression>]

Options:
  -h, --help                           - show this message;
  -t TARGET, --target TARGET           - preliminary target of processing
                                       (allowed: tokens, cst);
  -p PRECISION, --precision PRECISION  - precision of a result;
  -s, --stdin                          - read an expression from stdin.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{"-"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{"/"}, "slash"},
	{std::regex{"%"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{","}, "comma"},
	{std::regex{R"(\d+(?:\.\d+)?(?:e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};
const auto lexemes_exceptions = lexer::exception_group{"whitespace"};
// Boost 1.70.0, Math Toolkit 2.9.0
const auto constants = constant_group{
	{"pi", 3.141592653589793238462643383279502884},
	{"e", 2.718281828459045235360287471352662497}
};
const auto functions = function_group{
	{"+", {2, [] (const auto& arguments) {
		return arguments.front() + arguments.back();
	}}},
	{"-", {2, [] (const auto& arguments) {
		return arguments.front() - arguments.back();
	}}},
	{"*", {2, [] (const auto& arguments) {
		return arguments.front() * arguments.back();
	}}},
	{"/", {2, [] (const auto& arguments) {
		return arguments.front() / arguments.back();
	}}},
	{"%", {2, [] (const auto& arguments) {
		return static_cast<std::int64_t>(arguments.front())
			% static_cast<std::int64_t>(arguments.back());
	}}},
	{"floor", {1, [] (const auto& arguments) {
		return std::floor(arguments.front());
	}}},
	{"ceil", {1, [] (const auto& arguments) {
		return std::ceil(arguments.front());
	}}},
	{"trunc", {1, [] (const auto& arguments) {
		return std::trunc(arguments.front());
	}}},
	{"round", {1, [] (const auto& arguments) {
		return std::round(arguments.front());
	}}},
	{"sin", {1, [] (const auto& arguments) {
		return std::sin(arguments.front());
	}}},
	{"cos", {1, [] (const auto& arguments) {
		return std::cos(arguments.front());
	}}},
	{"tn", {1, [] (const auto& arguments) {
		return std::tan(arguments.front());
	}}},
	{"arcsin", {1, [] (const auto& arguments) {
		return std::asin(arguments.front());
	}}},
	{"arccos", {1, [] (const auto& arguments) {
		return std::acos(arguments.front());
	}}},
	{"arctn", {1, [] (const auto& arguments) {
		return std::atan(arguments.front());
	}}},
	{"angle", {2, [] (const auto& arguments) {
		return std::atan2(arguments.back(), arguments.front());
	}}},
	{"pow", {2, [] (const auto& arguments) {
		return std::pow(arguments.front(), arguments.back());
	}}},
	{"sqrt", {1, [] (const auto& arguments) {
		return std::sqrt(arguments.front());
	}}},
	{"exp", {1, [] (const auto& arguments) {
		return std::exp(arguments.front());
	}}},
	{"ln", {1, [] (const auto& arguments) {
		return std::log(arguments.front());
	}}},
	{"lg", {1, [] (const auto& arguments) {
		return std::log10(arguments.front());
	}}},
	{"abs", {1, [] (const auto& arguments) {
		return std::abs(arguments.front());
	}}},
};

template<typename streamable>
void stop(const int& code, std::ostream& stream, const streamable& message) {
	stream << message << '\n';
	std::exit(code);
}

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy >> *(&","_v >> expression_dummy))
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary >> *(("*"_v | "/"_v | "%"_v) >> unary);
	RULE(sum) = product >> *(("+"_v | "-"_v) >> product);
	expression_dummy->set_parser(sum);

	return sum;
}

const parser::ast_node_group& inspect_sequence(const parser::ast_node& ast) {
	return ast.children.front().children;
}

double evaluate_ast_node(
	const parser::ast_node& ast,
	const constant_group& constants,
	const function_group& functions
) {
	const auto evaluate_with_context = [&] (const auto& ast) {
		return evaluate_ast_node(ast, constants, functions);
	};

	if (ast.type == "number") {
		return std::stod(ast.value, nullptr);
	} else if (ast.type == "identifier") {
		try {
			return constants.at(ast.value);
		} catch (const std::out_of_range& exception) {
			throw unexpected_entity_exception<entity_type::constant>{
				parser::get_offset(ast)
			};
		}
	} else if (ast.type == "atom") {
		const auto type = (+parser::ast_node_type::sequence)._to_string();
		const auto first_child = ast.children.front().type == type
			? inspect_sequence(ast).front()
			: ast.children.front();
		return evaluate_with_context(first_child);
	} else if (ast.type == "unary") {
		const auto result = evaluate_with_context(inspect_sequence(ast).back());
		const auto sign = (inspect_sequence(ast).size()-1) % 2 ? -1 : 1;
		return sign * result;
	} else if (ast.type == "function_call") {
		try {
			const auto name = inspect_sequence(ast).front().value;
			const auto arguments = inspect_sequence(ast)
				| ranges::view::drop(1)
				| ranges::view::transform([&] (const auto& ast) {
					return evaluate_with_context(ast);
				});
			const auto function = functions.at(name);
			if (arguments.size() != function.arity) {
				throw exceptions::positional_exception{
					fmt::format(
						"function requires {:d} {:s}",
						function.arity,
						function.arity == 1 ? "argument" : "arguments"
					),
					parser::get_offset(ast)
				};
			}

			return function.handler(arguments);
		} catch (const std::out_of_range& exception) {
			throw unexpected_entity_exception<entity_type::function>{
				parser::get_offset(ast)
			};
		}
	} else if (ast.type == "product" || ast.type == "sum") {
		const auto first_operand =
			evaluate_with_context(inspect_sequence(ast).front());
		const auto children_chunks = inspect_sequence(ast)
			| ranges::view::drop(1)
			| ranges::view::chunk(2)
			| ranges::view::transform([] (const auto& chunk) {
				return chunk | ranges::to_<parser::ast_node_group>();
			});
		return ranges::accumulate(
			children_chunks,
			first_operand,
			[&] (const auto& result, const auto& chunk) {
				const auto name = chunk.front().value;
				const auto second_operand = evaluate_with_context(chunk.back());
				return functions.at(name).handler({result, second_operand});
			}
		);
	} else {
		throw unexpected_entity_exception<entity_type::node>{parser::get_offset(ast)};
	}
}

int main(int argc, char* argv[]) try {
	const auto options = docopt::docopt(usage, {argv+1, argv+argc}, true);
	const auto expression = options.at("<expression>")
		? options.at("<expression>").asString()
		: "";
	const auto code = options.at("--stdin").asBool()
		? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
		: expression;
	auto [tokens, rest_offset] = lexer::tokenize(
		lexemes,
		lexemes_exceptions,
		code
	);
	if (rest_offset != code.size()) {
		throw unexpected_entity_exception<entity_type::symbol>{rest_offset};
	}
	if (options.at("--target") == "tokens"s) {
		stop(EXIT_SUCCESS, std::cout, tokens);
	}

	const auto ast = parser::parse(make_parser(), tokens);
	if (!ast.rest_tokens.empty()) {
		throw unexpected_entity_exception<entity_type::token>{
			lexer::get_offset(ast.rest_tokens)
		};
	}
	if (!ast.node) {
		throw unexpected_entity_exception<entity_type::eoi>{code.size()};
	}
	if (options.at("--target") == "cst"s) {
		stop(EXIT_SUCCESS, std::cout, *ast.node);
	}

	auto buffer = std::ostringstream{};
	const auto precision = options.at("--precision")
		? options.at("--precision").asLong()
		: std::numeric_limits<double>::max_digits10;
	const auto result = evaluate_ast_node(*ast.node, constants, functions);
	buffer << std::setprecision(precision) << result;

	stop(EXIT_SUCCESS, std::cout, buffer.str());
} catch (const std::exception& exception) {
	stop(EXIT_FAILURE, std::cerr, fmt::format("error: {:s}", exception.what()));
}
<|endoftext|>


<commit_before>AliPhysicsSelectionTask* AddTaskPhysicsSelection(Bool_t mCAnalysisFlag = kFALSE, Bool_t deprecatedFlag = kTRUE, UInt_t computeBG = 0)
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskPhysicsSelection", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskPhysicsSelection", "This task requires an input event handler");
    return NULL;
  }

  AliVEventHandler *inputHandler=mgr->GetInputEventHandler();

  TString inputDataType = inputHandler->GetDataType(); // can be "ESD" or "AOD"

  // Configure analysis
  //===========================================================================
  AliPhysicsSelectionTask *task = new AliPhysicsSelectionTask("");

  // this makes physics selection to work using AliMultiInputEventHandler
  if (inputHandler && (inputHandler->IsA() == AliMultiInputEventHandler::Class())) {
    AliMultiInputEventHandler *multiInputHandler=(AliMultiInputEventHandler*)inputHandler;
    AliInputEventHandler *ih = multiInputHandler->GetFirstInputEventHandler();
    if (!ih) {
      ::Error("AddTaskPhysicsSelection","ESD or AOD input handler is mixxing");
      return NULL;
    }
    ih->SetEventSelection(multiInputHandler->GetEventSelection());
    inputDataType = ih->GetDataType(); // can be "ESD" or "AOD"
  }

  mgr->AddTask(task);

  AliPhysicsSelection* physSel = task->GetPhysicsSelection();
  if (mCAnalysisFlag)
    physSel->SetAnalyzeMC();
  if (computeBG)
    physSel->SetComputeBG(computeBG);

  if(!deprecatedFlag)
    AliFatal("The BG ID flag is deprecated. Please use the OADB to configure the cuts");

  AliAnalysisDataContainer *cinput0 = mgr->GetCommonInputContainer();
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("cstatsout",
                TList::Class(),
                AliAnalysisManager::kOutputContainer,
                "EventStat_temp.root");

  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task,1,coutput1);

  return task;
}
<commit_msg>spelling corrected<commit_after>AliPhysicsSelectionTask* AddTaskPhysicsSelection(Bool_t mCAnalysisFlag = kFALSE, Bool_t deprecatedFlag = kTRUE, UInt_t computeBG = 0)
{
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskPhysicsSelection", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskPhysicsSelection", "This task requires an input event handler");
    return NULL;
  }

  AliVEventHandler *inputHandler=mgr->GetInputEventHandler();

  TString inputDataType = inputHandler->GetDataType(); // can be "ESD" or "AOD"

  // Configure analysis
  //===========================================================================
  AliPhysicsSelectionTask *task = new AliPhysicsSelectionTask("");

  // this makes physics selection to work using AliMultiInputEventHandler
  if (inputHandler && (inputHandler->IsA() == AliMultiInputEventHandler::Class())) {
    AliMultiInputEventHandler *multiInputHandler=(AliMultiInputEventHandler*)inputHandler;
    AliInputEventHandler *ih = multiInputHandler->GetFirstInputEventHandler();
    if (!ih) {
      ::Error("AddTaskPhysicsSelection","ESD or AOD input handler is missing");
      return NULL;
    }
    ih->SetEventSelection(multiInputHandler->GetEventSelection());
    inputDataType = ih->GetDataType(); // can be "ESD" or "AOD"
  }

  mgr->AddTask(task);

  AliPhysicsSelection* physSel = task->GetPhysicsSelection();
  if (mCAnalysisFlag)
    physSel->SetAnalyzeMC();
  if (computeBG)
    physSel->SetComputeBG(computeBG);

  if(!deprecatedFlag)
    AliFatal("The BG ID flag is deprecated. Please use the OADB to configure the cuts");

  AliAnalysisDataContainer *cinput0 = mgr->GetCommonInputContainer();
  AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("cstatsout",
                TList::Class(),
                AliAnalysisManager::kOutputContainer,
                "EventStat_temp.root");

  mgr->ConnectInput(task, 0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput(task,1,coutput1);

  return task;
}
<|endoftext|>