<commit_before>// -*- mode: C++; c-file-style: "gnu" -*-
// kmfilter.cpp
// Author: Stefan Taferner <taferner@kde.org>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kmfilter.h"
#include "kmfilteraction.h"
#include "kmglobal.h"

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>

#include <assert.h>

KMFilter::KMFilter( KConfig* aConfig, bool popFilter )
  : bPopFilter(popFilter)
{
 if (!bPopFilter)
    mActions.setAutoDelete( true );

  if ( aConfig )
    readConfig( aConfig );
  else if ( bPopFilter )
    mAction = Down;
  else {
    bApplyOnInbound = true;
    bApplyOnOutbound = false;
    bApplyOnExplicit = true;
    bStopProcessingHere = true;
    bConfigureShortcut = false;
  }
}

KMFilter::KMFilter( const KMFilter & aFilter )
{
  bPopFilter = aFilter.isPopFilter();

  if ( !bPopFilter )
    mActions.setAutoDelete( true );

  mPattern = aFilter.mPattern;

  if ( bPopFilter ){
    mAction = aFilter.mAction;
  } else {
    bApplyOnInbound = aFilter.applyOnInbound();
    bApplyOnOutbound = aFilter.applyOnOutbound();
    bApplyOnExplicit = aFilter.applyOnExplicit();
    bStopProcessingHere = aFilter.stopProcessingHere();
    bConfigureShortcut = aFilter.configureShortcut();
    mIcon = aFilter.icon();

    QPtrListIterator<KMFilterAction> it( aFilter.mActions );
    for ( it.toFirst() ; it.current() ; ++it ) {
      KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ (*it)->name() ];
      if ( desc ) {
	KMFilterAction *f = desc->create();
	if ( f ) {
	  f->argsFromString( (*it)->argsAsString() );
	  mActions.append( f );
	}
      }
    }
  }
}

// only for !bPopFilter
KMFilter::ReturnCode KMFilter::execActions( KMMessage* msg, bool& stopIt ) const
{
  ReturnCode status = NoResult;

  QPtrListIterator<KMFilterAction> it( mActions );
  for ( it.toFirst() ; it.current() ; ++it ) {

    kdDebug(5006) << "####### KMFilter::process: going to apply action "
	      << (*it)->label() << " \"" << (*it)->argsAsString()
	      << "\"" << endl;

    KMFilterAction::ReturnCode result = (*it)->process( msg );

    switch ( result ) {
    case KMFilterAction::CriticalError:
      // in case it's a critical error: return immediately!
      return CriticalError;
    case KMFilterAction::ErrorButGoOn:
    default:
      break;
    }
  }

  if ( status == NoResult ) // No filters matched, keep copy of message
    status = GoOn;

  stopIt = stopProcessingHere();

  return status;
}

bool KMFilter::requiresBody( KMMsgBase* msg )
{
  if (pattern() && pattern()->requiresBody())
    return true; // no pattern means always matches?
  QPtrListIterator<KMFilterAction> it( *actions() );
  for ( it.toFirst() ; it.current() ; ++it )
    if ((*it)->requiresBody( msg ))
      return true;
  return false;
}

/** No descriptions */
// only for bPopFilter
void KMFilter::setAction(const KMPopFilterAction aAction)
{
  mAction = aAction;
}

// only for bPopFilter
KMPopFilterAction KMFilter::action()
{
  return mAction;
}

// only for !bPopFilter
bool KMFilter::folderRemoved( KMFolder* aFolder, KMFolder* aNewFolder )
{
  bool rem = false;

  QPtrListIterator<KMFilterAction> it( mActions );
  for ( it.toFirst() ; it.current() ; ++it )
    if ( (*it)->folderRemoved( aFolder, aNewFolder ) )
      rem = true;

  return rem;
}

//-----------------------------------------------------------------------------
void KMFilter::readConfig(KConfig* config)
{
  // MKSearchPattern::readConfig ensures
  // that the pattern is purified.
  mPattern.readConfig(config);

  if (bPopFilter)
    // get the action description...
    mAction = (KMPopFilterAction) config->readNumEntry( "action" );
  else {
    QStringList sets = config->readListEntry("apply-on");
    if ( sets.isEmpty() && !config->hasKey("apply-on") ) {
      bApplyOnOutbound = false;
      bApplyOnInbound = true;
      bApplyOnExplicit = true;
    } else {
      bApplyOnInbound = bool(sets.contains("check-mail"));
      bApplyOnOutbound = bool(sets.contains("send-mail"));
      bApplyOnExplicit = bool(sets.contains("manual-filtering"));
    }

    bStopProcessingHere = config->readBoolEntry("StopProcessingHere", true);
    bConfigureShortcut = config->readBoolEntry("ConfigureShortcut", false);
    mIcon = config->readEntry( "Icon", "gear" );

    int i, numActions;
    QString actName, argsName;

    mActions.clear();

    numActions = config->readNumEntry("actions",0);
    if (numActions > FILTER_MAX_ACTIONS) {
      numActions = FILTER_MAX_ACTIONS ;
      KMessageBox::information( 0, i18n("<qt>Too many filter actions in filter rule %1.</qt>").arg( mPattern.name() ) );
    }

    for ( i=0 ; i < numActions ; i++ ) {
      actName.sprintf("action-name-%d", i);
      argsName.sprintf("action-args-%d", i);
      // get the action description...
      KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ config->readEntry( actName ) ];
      if ( desc ) {
        //...create an instance...
        KMFilterAction *fa = desc->create();
        if ( fa ) {
  	  //...load it with it's parameter...
          fa->argsFromString( config->readEntry( argsName ) );
	  //...check if it's emoty and...
	  if ( !fa->isEmpty() )
	    //...append it if it's not and...
	    mActions.append( fa );
	  else
	    //...delete is else.
	    delete fa;
        }
      } else
        KMessageBox::information( 0 /* app-global modal dialog box */,
				  i18n("<qt>Unknown filter action %1
in filter rule %2.
Ignoring it.</qt>")
				       .arg( config->readEntry( actName ) ).arg( mPattern.name() ) );
    }
  }
}

void KMFilter::writeConfig(KConfig* config) const
{
  mPattern.writeConfig(config);

  if (bPopFilter) {
    config->writeEntry( "action", mAction );
  } else {
    QStringList sets;
    if ( bApplyOnInbound )
      sets.append( "check-mail" );
    if ( bApplyOnOutbound )
      sets.append( "send-mail" );
    if ( bApplyOnExplicit )
      sets.append( "manual-filtering" );
    config->writeEntry( "apply-on", sets );

    config->writeEntry( "StopProcessingHere", bStopProcessingHere );
    config->writeEntry( "ConfigureShortcut", bConfigureShortcut );
    config->writeEntry( "Icon", mIcon );

    QString key;
    int i;

    QPtrListIterator<KMFilterAction> it( mActions );
    for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
      config->writeEntry( key.sprintf("action-name-%d", i),
    			  (*it)->name() );
      config->writeEntry( key.sprintf("action-args-%d", i),
			  (*it)->argsAsString() );
    }
    config->writeEntry("actions", i );
  }
}

void KMFilter::purify()
{
  mPattern.purify();

  if (!bPopFilter) {
    QPtrListIterator<KMFilterAction> it( mActions );
    it.toLast();
    while ( it.current() )
      if ( (*it)->isEmpty() )
        mActions.remove ( (*it) );
      else
        --it;
  }
}

bool KMFilter::isEmpty() const
{
  if (bPopFilter)
    return mPattern.isEmpty();
  else
    return mPattern.isEmpty() && mActions.isEmpty();
}

#ifndef NDEBUG
const QString KMFilter::asString() const
{
  QString result;

  result += mPattern.asString();

  if (bPopFilter){
    result += "    action: ";
    result += mAction;
    result += "\n";
  }
  else {
    QPtrListIterator<KMFilterAction> it( mActions );
    for ( it.toFirst() ; it.current() ; ++it ) {
      result += "    action: ";
      result += (*it)->label();
      result += " ";
      result += (*it)->argsAsString();
      result += "\n";
    }
    result += "This filter belongs to the following sets:";
    if ( bApplyOnInbound )
      result += " Inbound";
    if ( bApplyOnOutbound )
      result += " Outbound";
    if ( bApplyOnExplicit )
      result += " Explicit";
    result += "\n";
    if ( bStopProcessingHere )
      result += "If it matches, processing stops at this filter.\n";
  }
  return result;
}
#endif
<commit_msg>Commiting a patch by Ingo Klöcker: The attached patch fixes the critical bug #71866.<commit_after>// -*- mode: C++; c-file-style: "gnu" -*-
// kmfilter.cpp
// Author: Stefan Taferner <taferner@kde.org>

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "kmfilter.h"
#include "kmfilteraction.h"
#include "kmglobal.h"

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>
#include <kconfig.h>

#include <assert.h>

KMFilter::KMFilter( KConfig* aConfig, bool popFilter )
  : bPopFilter(popFilter)
{
 if (!bPopFilter)
    mActions.setAutoDelete( true );

  if ( aConfig )
    readConfig( aConfig );
  else if ( bPopFilter )
    mAction = Down;
  else {
    bApplyOnInbound = true;
    bApplyOnOutbound = false;
    bApplyOnExplicit = true;
    bStopProcessingHere = true;
    bConfigureShortcut = false;
  }
}

KMFilter::KMFilter( const KMFilter & aFilter )
{
  bPopFilter = aFilter.isPopFilter();

  if ( !bPopFilter )
    mActions.setAutoDelete( true );

  mPattern = aFilter.mPattern;

  if ( bPopFilter ){
    mAction = aFilter.mAction;
  } else {
    bApplyOnInbound = aFilter.applyOnInbound();
    bApplyOnOutbound = aFilter.applyOnOutbound();
    bApplyOnExplicit = aFilter.applyOnExplicit();
    bStopProcessingHere = aFilter.stopProcessingHere();
    bConfigureShortcut = aFilter.configureShortcut();
    mIcon = aFilter.icon();

    QPtrListIterator<KMFilterAction> it( aFilter.mActions );
    for ( it.toFirst() ; it.current() ; ++it ) {
      KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ (*it)->name() ];
      if ( desc ) {
	KMFilterAction *f = desc->create();
	if ( f ) {
	  f->argsFromString( (*it)->argsAsString() );
	  mActions.append( f );
	}
      }
    }
  }
}

// only for !bPopFilter
KMFilter::ReturnCode KMFilter::execActions( KMMessage* msg, bool& stopIt ) const
{
  ReturnCode status = NoResult;

  QPtrListIterator<KMFilterAction> it( mActions );
  for ( it.toFirst() ; it.current() ; ++it ) {

    kdDebug(5006) << "####### KMFilter::process: going to apply action "
	      << (*it)->label() << " \"" << (*it)->argsAsString()
	      << "\"" << endl;

    KMFilterAction::ReturnCode result = (*it)->process( msg );

    switch ( result ) {
    case KMFilterAction::CriticalError:
      // in case it's a critical error: return immediately!
      return CriticalError;
    case KMFilterAction::ErrorButGoOn:
    default:
      break;
    }
  }

  if ( status == NoResult ) // No filters matched, keep copy of message
    status = GoOn;

  stopIt = stopProcessingHere();

  return status;
}

bool KMFilter::requiresBody( KMMsgBase* msg )
{
  if (pattern() && pattern()->requiresBody())
    return true; // no pattern means always matches?
  QPtrListIterator<KMFilterAction> it( *actions() );
  for ( it.toFirst() ; it.current() ; ++it )
    if ((*it)->requiresBody( msg ))
      return true;
  return false;
}

/** No descriptions */
// only for bPopFilter
void KMFilter::setAction(const KMPopFilterAction aAction)
{
  mAction = aAction;
}

// only for bPopFilter
KMPopFilterAction KMFilter::action()
{
  return mAction;
}

// only for !bPopFilter
bool KMFilter::folderRemoved( KMFolder* aFolder, KMFolder* aNewFolder )
{
  bool rem = false;

  QPtrListIterator<KMFilterAction> it( mActions );
  for ( it.toFirst() ; it.current() ; ++it )
    if ( (*it)->folderRemoved( aFolder, aNewFolder ) )
      rem = true;

  return rem;
}

//-----------------------------------------------------------------------------
void KMFilter::readConfig(KConfig* config)
{
  // MKSearchPattern::readConfig ensures
  // that the pattern is purified.
  mPattern.readConfig(config);

  if (bPopFilter) {
    // get the action description...
    QString action = config->readEntry( "action" );
    if ( action == "down" )
      mAction = Down;
    else if ( action == "later" )
      mAction = Later;
    else if ( action == "delete" )
      mAction = Delete;
    else
      mAction = NoAction;
  }
  else {
    QStringList sets = config->readListEntry("apply-on");
    if ( sets.isEmpty() && !config->hasKey("apply-on") ) {
      bApplyOnOutbound = false;
      bApplyOnInbound = true;
      bApplyOnExplicit = true;
    } else {
      bApplyOnInbound = bool(sets.contains("check-mail"));
      bApplyOnOutbound = bool(sets.contains("send-mail"));
      bApplyOnExplicit = bool(sets.contains("manual-filtering"));
    }

    bStopProcessingHere = config->readBoolEntry("StopProcessingHere", true);
    bConfigureShortcut = config->readBoolEntry("ConfigureShortcut", false);
    mIcon = config->readEntry( "Icon", "gear" );

    int i, numActions;
    QString actName, argsName;

    mActions.clear();

    numActions = config->readNumEntry("actions",0);
    if (numActions > FILTER_MAX_ACTIONS) {
      numActions = FILTER_MAX_ACTIONS ;
      KMessageBox::information( 0, i18n("<qt>Too many filter actions in filter rule %1.</qt>").arg( mPattern.name() ) );
    }

    for ( i=0 ; i < numActions ; i++ ) {
      actName.sprintf("action-name-%d", i);
      argsName.sprintf("action-args-%d", i);
      // get the action description...
      KMFilterActionDesc *desc = (*kmkernel->filterActionDict())[ config->readEntry( actName ) ];
      if ( desc ) {
        //...create an instance...
        KMFilterAction *fa = desc->create();
        if ( fa ) {
  	  //...load it with it's parameter...
          fa->argsFromString( config->readEntry( argsName ) );
	  //...check if it's emoty and...
	  if ( !fa->isEmpty() )
	    //...append it if it's not and...
	    mActions.append( fa );
	  else
	    //...delete is else.
	    delete fa;
        }
      } else
        KMessageBox::information( 0 /* app-global modal dialog box */,
				  i18n("<qt>Unknown filter action %1
in filter rule %2.
Ignoring it.</qt>")
				       .arg( config->readEntry( actName ) ).arg( mPattern.name() ) );
    }
  }
}

void KMFilter::writeConfig(KConfig* config) const
{
  mPattern.writeConfig(config);

  if (bPopFilter) {
    switch ( mAction ) {
    case Down:
      config->writeEntry( "action", "down" );
      break;
    case Later:
      config->writeEntry( "action", "later" );
      break;
    case Delete:
      config->writeEntry( "action", "delete" );
      break;
    default:
      config->writeEntry( "action", "" );
    }
  } else {
    QStringList sets;
    if ( bApplyOnInbound )
      sets.append( "check-mail" );
    if ( bApplyOnOutbound )
      sets.append( "send-mail" );
    if ( bApplyOnExplicit )
      sets.append( "manual-filtering" );
    config->writeEntry( "apply-on", sets );

    config->writeEntry( "StopProcessingHere", bStopProcessingHere );
    config->writeEntry( "ConfigureShortcut", bConfigureShortcut );
    config->writeEntry( "Icon", mIcon );

    QString key;
    int i;

    QPtrListIterator<KMFilterAction> it( mActions );
    for ( i=0, it.toFirst() ; it.current() ; ++it, ++i ) {
      config->writeEntry( key.sprintf("action-name-%d", i),
    			  (*it)->name() );
      config->writeEntry( key.sprintf("action-args-%d", i),
			  (*it)->argsAsString() );
    }
    config->writeEntry("actions", i );
  }
}

void KMFilter::purify()
{
  mPattern.purify();

  if (!bPopFilter) {
    QPtrListIterator<KMFilterAction> it( mActions );
    it.toLast();
    while ( it.current() )
      if ( (*it)->isEmpty() )
        mActions.remove ( (*it) );
      else
        --it;
  }
}

bool KMFilter::isEmpty() const
{
  if (bPopFilter)
    return mPattern.isEmpty();
  else
    return mPattern.isEmpty() && mActions.isEmpty();
}

#ifndef NDEBUG
const QString KMFilter::asString() const
{
  QString result;

  result += mPattern.asString();

  if (bPopFilter){
    result += "    action: ";
    result += mAction;
    result += "\n";
  }
  else {
    QPtrListIterator<KMFilterAction> it( mActions );
    for ( it.toFirst() ; it.current() ; ++it ) {
      result += "    action: ";
      result += (*it)->label();
      result += " ";
      result += (*it)->argsAsString();
      result += "\n";
    }
    result += "This filter belongs to the following sets:";
    if ( bApplyOnInbound )
      result += " Inbound";
    if ( bApplyOnOutbound )
      result += " Outbound";
    if ( bApplyOnExplicit )
      result += " Explicit";
    result += "\n";
    if ( bStopProcessingHere )
      result += "If it matches, processing stops at this filter.\n";
  }
  return result;
}
#endif
<|endoftext|>


<commit_before>/*
 *             KNotes
 *
 * $Id$
 *
 *              Copyright (C) 1997 Bernd Johannes Wuebben
 *                      wuebben@math.cornell.edu
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "knotes.h"

#include <qtooltip.h>
#include <kwm.h>
#include <kapp.h>
#include <klocale.h>
#include <kglobal.h>
#include <kiconloader.h>

#include "knotes.h"
#include "docking.h"

//extern QStrList  KPostit::PostitFilesList; // names of all postit files
//extern QList<KPostit> 	  KPostit::PostitList;

DockWidget::DockWidget(const char *name): QWidget(0, name, 0) {

  docked = false;

  pos_x = pos_y = 0;

  picsmall_pixmap = KGlobal::iconLoader()->loadApplicationMiniIcon( "knotes.xpm" );

  //////////////////////////////////////////////////////////////////
  // popup menu for left mouse button

  popup_m = new QPopupMenu();

  createLeftPopUp();

  connect( popup_m, SIGNAL(activated( int )),SLOT(findKPostit(int)) );
  popup_m->adjustSize();

  ///////////////////////////////////////////////////////////////////
  // right_popup menu for left mouse button

  right_popup_m = new QPopupMenu();
  right_popup_m->insertItem (i18n("Help"),this,SLOT(help()));

  right_popup_m->insertItem(i18n("Change Defaults"),
			    this, SLOT(configureKNotes()));

  right_popup_m->insertSeparator();

  right_popup_m->insertItem (i18n("Exit Knotes"),
			     this, SLOT(exitKNotes()));

  //  connect( right_popup_m, SIGNAL(activated( int )),SLOT(rightAction(int)) );
  right_popup_m->adjustSize();

}

DockWidget::~DockWidget(){

}

void DockWidget::createLeftPopUp(){

  //  printf("In creatLeftPopUp\n");
  popup_m->clear();

  newID = popup_m->insertItem(i18n("New Knote"),
				 this, SLOT(newKNote()));

  popup_m->insertSeparator();

  for ( uint i = 0; i < KPostit::PostitFilesList.count(); i++){

    popup_m->insertItem (KPostit::PostitFilesList[i]);

  }
}

void DockWidget::newKNote(){

  KPostit* postit;

  if(KPostit::PostitFilesList.count() == 0 ){

    KPostit::PostitFilesList.append("knote 1");
    postit = new KPostit(NULL,NULL,0,KPostit::PostitFilesList.last());

    KPostit::PostitList.append(postit);
    postit->show();
    createLeftPopUp();

  }
  else{

    KPostit::PostitList.first()->newKPostit();
  }

}
void DockWidget::exitKNotes(){

  //  printf("in exitKNotes\n");

  if(KPostit::PostitList.count() > 0){

    //    printf("about to exit via PostitList\n");
    KPostit::PostitList.at(0)->quit();

  }
  else{
      QApplication::exit();
  }

}

void DockWidget::configureKNotes(){

  KPostit* postit;

  if(KPostit::PostitFilesList.count() == 0 ){

    KPostit::PostitFilesList.append("knote 1");
    postit = new KPostit(NULL,NULL,0,KPostit::PostitFilesList.last());

    KPostit::PostitList.append(postit);

  }

  KPostit::PostitList.at(0)->defaults();
  createLeftPopUp();

}

void DockWidget::help(){

  kapp->invokeHTMLHelp("","");

}

void DockWidget::dock() {

  if (!docked) {
    // prepare panel to accept this widget
    KWM::setDockWindow (this->winId());

    // that's all the space there is
    this->setFixedSize(24, 24);

    // finally dock the widget
    this->show();
    docked = true;
  }

}

void DockWidget::findKPostit(int i){

  // convert absolute id to relative index
  i = popup_m->indexOf(i);

  if(KPostit::PostitList.count() > 0 && i > 1){
    KPostit::PostitList.at(0)->findKPostit( i - 2 );
  }

}

void DockWidget::undock() {

  if (docked) {
    // new docking method, taken from ksirc (servercontroller.cpp)
    this->hide();
    this->recreate(0x0, 0, QPoint(0,0), FALSE);
    docked = false;
  }
}

const bool DockWidget::isDocked() {

  return docked;

}

void DockWidget::paintEvent (QPaintEvent *e) {

  (void) e;

  paintIcon();

}

void DockWidget::paintIcon () {

  bitBlt(this, 0, 0, &picsmall_pixmap);

}

void DockWidget::mousePressEvent(QMouseEvent *e) {

  if ( e->button() == (LeftButton || MidButton) ) {

    QPoint point = this->mapToGlobal (QPoint(0,0));

    point  = point - QPoint(30,60);
    popup_m->popup(point);
    popup_m->exec();
    return;
  }

  if ( e->button() == RightButton ) {

    QPoint point = this->mapToGlobal (QPoint(0,0));

    point  = point - QPoint(30,60);
    right_popup_m->popup(point);
    right_popup_m->exec();
  }

}

void DockWidget::toggle_window_state() {

  /*
  // restore/hide connect-window
  if(k != 0L)  {
    if (k->isVisible()){

    QPoint point = k->mapToGlobal (QPoint (0,0));
     pos_x = point.x();
     pos_y = point.y();
     k->hide();
    }
    else {
     k->setGeometry(
		 pos_x,
		 pos_y,
		 k->width(),
		 k->height());

      k->show();
    }
  }
  */
}

#include "docking.moc"

<commit_msg>adopt latest KIconLoader changes<commit_after>/*
 *             KNotes
 *
 * $Id$
 *
 *              Copyright (C) 1997 Bernd Johannes Wuebben
 *                      wuebben@math.cornell.edu
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "knotes.h"

#include <qtooltip.h>
#include <kwm.h>
#include <kapp.h>
#include <klocale.h>
#include <kglobal.h>
#include <kiconloader.h>

#include "knotes.h"
#include "docking.h"

//extern QStrList  KPostit::PostitFilesList; // names of all postit files
//extern QList<KPostit> 	  KPostit::PostitList;

DockWidget::DockWidget(const char *name): QWidget(0, name, 0) {

  docked = false;

  pos_x = pos_y = 0;

  picsmall_pixmap = KGlobal::iconLoader()->loadApplicationIcon( "knotes", KIconLoader::Small );

  //////////////////////////////////////////////////////////////////
  // popup menu for left mouse button

  popup_m = new QPopupMenu();

  createLeftPopUp();

  connect( popup_m, SIGNAL(activated( int )),SLOT(findKPostit(int)) );
  popup_m->adjustSize();

  ///////////////////////////////////////////////////////////////////
  // right_popup menu for left mouse button

  right_popup_m = new QPopupMenu();
  right_popup_m->insertItem (i18n("Help"),this,SLOT(help()));

  right_popup_m->insertItem(i18n("Change Defaults"),
			    this, SLOT(configureKNotes()));

  right_popup_m->insertSeparator();

  right_popup_m->insertItem (i18n("Exit Knotes"),
			     this, SLOT(exitKNotes()));

  //  connect( right_popup_m, SIGNAL(activated( int )),SLOT(rightAction(int)) );
  right_popup_m->adjustSize();

}

DockWidget::~DockWidget(){

}

void DockWidget::createLeftPopUp(){

  //  printf("In creatLeftPopUp\n");
  popup_m->clear();

  newID = popup_m->insertItem(i18n("New Knote"),
				 this, SLOT(newKNote()));

  popup_m->insertSeparator();

  for ( uint i = 0; i < KPostit::PostitFilesList.count(); i++){

    popup_m->insertItem (KPostit::PostitFilesList[i]);

  }
}

void DockWidget::newKNote(){

  KPostit* postit;

  if(KPostit::PostitFilesList.count() == 0 ){

    KPostit::PostitFilesList.append("knote 1");
    postit = new KPostit(NULL,NULL,0,KPostit::PostitFilesList.last());

    KPostit::PostitList.append(postit);
    postit->show();
    createLeftPopUp();

  }
  else{

    KPostit::PostitList.first()->newKPostit();
  }

}
void DockWidget::exitKNotes(){

  //  printf("in exitKNotes\n");

  if(KPostit::PostitList.count() > 0){

    //    printf("about to exit via PostitList\n");
    KPostit::PostitList.at(0)->quit();

  }
  else{
      QApplication::exit();
  }

}

void DockWidget::configureKNotes(){

  KPostit* postit;

  if(KPostit::PostitFilesList.count() == 0 ){

    KPostit::PostitFilesList.append("knote 1");
    postit = new KPostit(NULL,NULL,0,KPostit::PostitFilesList.last());

    KPostit::PostitList.append(postit);

  }

  KPostit::PostitList.at(0)->defaults();
  createLeftPopUp();

}

void DockWidget::help(){

  kapp->invokeHTMLHelp("","");

}

void DockWidget::dock() {

  if (!docked) {
    // prepare panel to accept this widget
    KWM::setDockWindow (this->winId());

    // that's all the space there is
    this->setFixedSize(24, 24);

    // finally dock the widget
    this->show();
    docked = true;
  }

}

void DockWidget::findKPostit(int i){

  // convert absolute id to relative index
  i = popup_m->indexOf(i);

  if(KPostit::PostitList.count() > 0 && i > 1){
    KPostit::PostitList.at(0)->findKPostit( i - 2 );
  }

}

void DockWidget::undock() {

  if (docked) {
    // new docking method, taken from ksirc (servercontroller.cpp)
    this->hide();
    this->recreate(0x0, 0, QPoint(0,0), FALSE);
    docked = false;
  }
}

const bool DockWidget::isDocked() {

  return docked;

}

void DockWidget::paintEvent (QPaintEvent *e) {

  (void) e;

  paintIcon();

}

void DockWidget::paintIcon () {

  bitBlt(this, 0, 0, &picsmall_pixmap);

}

void DockWidget::mousePressEvent(QMouseEvent *e) {

  if ( e->button() == (LeftButton || MidButton) ) {

    QPoint point = this->mapToGlobal (QPoint(0,0));

    point  = point - QPoint(30,60);
    popup_m->popup(point);
    popup_m->exec();
    return;
  }

  if ( e->button() == RightButton ) {

    QPoint point = this->mapToGlobal (QPoint(0,0));

    point  = point - QPoint(30,60);
    right_popup_m->popup(point);
    right_popup_m->exec();
  }

}

void DockWidget::toggle_window_state() {

  /*
  // restore/hide connect-window
  if(k != 0L)  {
    if (k->isVisible()){

    QPoint point = k->mapToGlobal (QPoint (0,0));
     pos_x = point.x();
     pos_y = point.y();
     k->hide();
    }
    else {
     k->setGeometry(
		 pos_x,
		 pos_y,
		 k->width(),
		 k->height());

      k->show();
    }
  }
  */
}

#include "docking.moc"

<|endoftext|>


<commit_before><commit_msg>Clear LexTableBuilder's state after detecting conflicts<commit_after><|endoftext|>


<commit_before><commit_msg>Attempting to serialize sprites<commit_after><|endoftext|>


<commit_before>//
//  ZXSpectrum.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 17/03/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#include "ZXSpectrum.hpp"

#include "../../MachineTypes.hpp"

#include "../../../Analyser/Static/ZXSpectrum/Target.hpp"

#include <array>

namespace {
	const unsigned int ClockRate = 3'500'000;
}

namespace Sinclair {
namespace ZXSpectrum {

using Model = Analyser::Static::ZXSpectrum::Target::Model;
template<Model model> class ConcreteMachine:
	public MachineTypes::ScanProducer,
	public MachineTypes::TimedMachine,
	public Machine {
	public:
		ConcreteMachine(const Analyser::Static::ZXSpectrum::Target &target, const ROMMachine::ROMFetcher &rom_fetcher)
		{
			set_clock_rate(ClockRate);

			// With only the +2a and +3 currently supported, the +3 ROM is always
			// the one required.
			const auto roms =
				rom_fetcher({ {"ZXSpectrum", "the +2a/+3 ROM", "plus3.rom", 64 * 1024, 0x96e3c17a} });
			if(!roms[0]) throw ROMMachine::Error::MissingROMs;
			memcpy(rom_.data(), roms[0]->data(), std::min(rom_.size(), roms[0]->size()));

			// TODO: insert media, set up memory map.
			(void)target;
		}

		// MARK: - TimedMachine

		void run_for(const Cycles cycles) override {
			// TODO.
			(void)cycles;
		}

		// MARK: - ScanProducer

		void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
			(void)scan_target;
		}

		Outputs::Display::ScanStatus get_scaled_scan_status() const final {
			// TODO.
			return Outputs::Display::ScanStatus();
		}

	private:
		std::array<uint8_t, 64*1024> rom_;
		std::array<uint8_t, 128*1024> ram_;
};

}
}

using namespace Sinclair::ZXSpectrum;

Machine *Machine::ZXSpectrum(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
	const auto zx_target = dynamic_cast<const Analyser::Static::ZXSpectrum::Target *>(target);

	switch(zx_target->model) {
		case Model::Plus2a:	return new ConcreteMachine<Model::Plus2a>(*zx_target, rom_fetcher);
		case Model::Plus3:	return new ConcreteMachine<Model::Plus3>(*zx_target, rom_fetcher);
	}

	return nullptr;
}

Machine::~Machine() {}
<commit_msg>Stumbles towards a memory map.<commit_after>//
//  ZXSpectrum.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 17/03/2021.
//  Copyright © 2021 Thomas Harte. All rights reserved.
//

#include "ZXSpectrum.hpp"

#include "../../MachineTypes.hpp"

#include "../../../Processors/Z80/Z80.hpp"

#include "../../../Analyser/Static/ZXSpectrum/Target.hpp"

#include <array>

namespace {
	const unsigned int ClockRate = 3'500'000;
}

namespace Sinclair {
namespace ZXSpectrum {

using Model = Analyser::Static::ZXSpectrum::Target::Model;
template<Model model> class ConcreteMachine:
	public Machine,
	public MachineTypes::ScanProducer,
	public MachineTypes::TimedMachine,
	public CPU::Z80::BusHandler {
	public:
		ConcreteMachine(const Analyser::Static::ZXSpectrum::Target &target, const ROMMachine::ROMFetcher &rom_fetcher) :
			z80_(*this)
		{
			set_clock_rate(ClockRate);

			// With only the +2a and +3 currently supported, the +3 ROM is always
			// the one required.
			const auto roms =
				rom_fetcher({ {"ZXSpectrum", "the +2a/+3 ROM", "plus3.rom", 64 * 1024, 0x96e3c17a} });
			if(!roms[0]) throw ROMMachine::Error::MissingROMs;
			memcpy(rom_.data(), roms[0]->data(), std::min(rom_.size(), roms[0]->size()));

			// Set up initial memory map.
			update_memory_map();

			// TODO: insert media.
			(void)target;
		}

		// MARK: - TimedMachine

		void run_for(const Cycles cycles) override {
			z80_.run_for(cycles);
		}

		// MARK: - ScanProducer

		void set_scan_target(Outputs::Display::ScanTarget *scan_target) final {
			(void)scan_target;
		}

		Outputs::Display::ScanStatus get_scaled_scan_status() const final {
			// TODO.
			return Outputs::Display::ScanStatus();
		}

		// MARK: - BusHandler

		forceinline HalfCycles perform_machine_cycle(const CPU::Z80::PartialMachineCycle &cycle) {
			(void)cycle;

			return HalfCycles(0);
		}

	private:
		CPU::Z80::Processor<ConcreteMachine, false, false> z80_;

		// MARK: - Memory.
		std::array<uint8_t, 64*1024> rom_;
		std::array<uint8_t, 128*1024> ram_;

		std::array<uint8_t, 16*1024> scratch_;
		const uint8_t *read_pointers_[4];
		uint8_t *write_pointers_[4];

		uint8_t port1ffd_ = 0;
		uint8_t port7ffd_ = 0;
		bool disable_paging_ = false;

		void update_memory_map() {
			if(disable_paging_) {
				// Set 48kb-esque memory map.
				set_memory(0, rom_.data(), nullptr);
				set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
				set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
				set_memory(3, &ram_[0 * 16384], &ram_[0 * 16384]);
				return;
			}

			if(port1ffd_ & 1) {
				// "Special paging mode", i.e. one of four fixed
				// RAM configurations, port 7ffd doesn't matter.

				switch(port1ffd_ & 0x6) {
					default:
					case 0x00:
						set_memory(0, &ram_[0 * 16384], &ram_[0 * 16384]);
						set_memory(1, &ram_[1 * 16384], &ram_[1 * 16384]);
						set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);
						set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
					break;

					case 0x02:
						set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
						set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
						set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
						set_memory(3, &ram_[7 * 16384], &ram_[7 * 16384]);
					break;

					case 0x04:
						set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
						set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
						set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
						set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
					break;

					case 0x06:
						set_memory(0, &ram_[4 * 16384], &ram_[4 * 16384]);
						set_memory(1, &ram_[7 * 16384], &ram_[7 * 16384]);
						set_memory(2, &ram_[6 * 16384], &ram_[6 * 16384]);
						set_memory(3, &ram_[3 * 16384], &ram_[3 * 16384]);
					break;
				}

				return;
			}

			// Apply standard 128kb-esque mapping (albeit with extra ROM to pick from).
			const auto rom = &rom_[ (((port1ffd_ >> 1) & 2) | ((port7ffd_ >> 4) & 1)) * 16384];
			set_memory(0, rom, nullptr);

			set_memory(1, &ram_[5 * 16384], &ram_[5 * 16384]);
			set_memory(2, &ram_[2 * 16384], &ram_[2 * 16384]);

			const auto high_ram = &ram_[(port7ffd_ & 7) * 16384];
			set_memory(3, high_ram, high_ram);
		}

		void set_memory(int bank, const uint8_t *read, uint8_t *write) {
			read_pointers_[bank] = read - bank*16384;
			write_pointers_[bank] = (write ? write : scratch_.data()) - bank*16384;
		}
};

}
}

using namespace Sinclair::ZXSpectrum;

Machine *Machine::ZXSpectrum(const Analyser::Static::Target *target, const ROMMachine::ROMFetcher &rom_fetcher) {
	const auto zx_target = dynamic_cast<const Analyser::Static::ZXSpectrum::Target *>(target);

	switch(zx_target->model) {
		case Model::Plus2a:	return new ConcreteMachine<Model::Plus2a>(*zx_target, rom_fetcher);
		case Model::Plus3:	return new ConcreteMachine<Model::Plus3>(*zx_target, rom_fetcher);
	}

	return nullptr;
}

Machine::~Machine() {}
<|endoftext|>


<commit_before>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "Curve.h"

#include <algorithm>

#include "Engine/CurvePrivate.h"
#include "Engine/Interpolation.h"

namespace {
    struct KeyFrameCloner {
        boost::shared_ptr<KeyFrame> operator()(const boost::shared_ptr<KeyFrame>& kf) const { return boost::shared_ptr<KeyFrame>(new KeyFrame(kf->getTime(),kf->getValue())); }
    };

    class KeyFrameTimePredicate
    {
    public:
        KeyFrameTimePredicate(double t) : _t(t) {};

        bool operator()(const boost::shared_ptr<KeyFrame>& f) { return (f->getTime() == _t); }
    private:
        double _t;
    };
}

/************************************KEYFRAME************************************/

KeyFrame::KeyFrame()
    : _imp(new KeyFramePrivate)
{}

KeyFrame::KeyFrame(double time, const Variant& initialValue)
    : _imp(new KeyFramePrivate(time,initialValue))
{
}

KeyFrame::KeyFrame(const KeyFrame& other)
    : _imp(new KeyFramePrivate(*(other._imp)))
{
}

void KeyFrame::operator=(const KeyFrame& o)
{
    _imp->time = o._imp->time;
    _imp->value = o._imp->value;
    _imp->leftTangent = o._imp->leftTangent;
    _imp->rightTangent = o._imp->rightTangent;
    _imp->interpolation = o._imp->interpolation;
}

KeyFrame::~KeyFrame(){}

bool KeyFrame::operator==(const KeyFrame& o) const {
    return _imp->value == o._imp->value &&
            _imp->time == o._imp->time;
}

void KeyFrame::setLeftTangent(const Variant& v){
    _imp->leftTangent = v;
}

void KeyFrame::setRightTangent(const Variant& v){
    _imp->rightTangent = v;
}

void KeyFrame::setValue(const Variant& v){
    _imp->value = v;
}

void KeyFrame::setTime(double time){
    _imp->time = time;
}

void KeyFrame::setInterpolation(Natron::KeyframeType interp) { _imp->interpolation = interp; }

Natron::KeyframeType KeyFrame::getInterpolation() const { return _imp->interpolation; }

const Variant& KeyFrame::getValue() const { return _imp->value; }

double KeyFrame::getTime() const { return _imp->time; }

const Variant& KeyFrame::getLeftTangent() const { return _imp->leftTangent; }

const Variant& KeyFrame::getRightTangent() const { return _imp->rightTangent; }

/************************************CURVEPATH************************************/

Curve::Curve()
    : _imp(new CurvePrivate)
{

}

Curve::Curve(Knob *owner)
    : _imp(new CurvePrivate)
{
    _imp->owner = owner;
}

Curve::~Curve(){ clearKeyFrames(); }

void Curve::clearKeyFrames(){
    _imp->keyFrames.clear();
}

void Curve::clone(const Curve& other){
    clearKeyFrames();
    const KeyFrameSet& otherKeys = other.getKeyFrames();
    std::transform(otherKeys.begin(), otherKeys.end(), std::inserter(_imp->keyFrames, _imp->keyFrames.begin()), KeyFrameCloner());
}

double Curve::getMinimumTimeCovered() const{
    assert(!_imp->keyFrames.empty());
    return (*_imp->keyFrames.begin())->getTime();
}

double Curve::getMaximumTimeCovered() const{
    assert(!_imp->keyFrames.empty());
    return (*_imp->keyFrames.rbegin())->getTime();
}

void Curve::addKeyFrame(boost::shared_ptr<KeyFrame> cp)
{
    std::pair<KeyFrameSet::iterator,bool> newKey = _imp->keyFrames.insert(cp);
    if (newKey.second) {
        refreshTangents(KEYFRAME_CHANGED, newKey.first);
    }else{
        (*newKey.first)->setValue(cp->getValue());
    }
}

void Curve::removeKeyFrame(boost::shared_ptr<KeyFrame> cp) {
    KeyFrameSet::iterator it = std::find(_imp->keyFrames.begin(),_imp->keyFrames.end(),cp);
    KeyFrameSet::iterator prev = it;
    boost::shared_ptr<KeyFrame> prevCp;
    boost::shared_ptr<KeyFrame> nextCp;
    if(it != _imp->keyFrames.begin()){
        --prev;
        prevCp = (*prev);
    }
    KeyFrameSet::iterator next = it;
    ++next;
    if(next != _imp->keyFrames.end()){
        nextCp = (*next);
    }
    _imp->keyFrames.erase(it);
    if(prevCp){
        refreshTangents(TANGENT_CHANGED,prevCp);
    }
    if(nextCp){
        refreshTangents(TANGENT_CHANGED,nextCp);
    }

}

void Curve::removeKeyFrame(double time) {
    KeyFrameSet::iterator it = std::find_if(_imp->keyFrames.begin(), _imp->keyFrames.end(), KeyFrameTimePredicate(time));
    if (it != _imp->keyFrames.end()) {
        removeKeyFrame(*it);
    }
}

Variant Curve::getValueAt(double t) const {
    assert(!_imp->keyFrames.empty());
    if (_imp->keyFrames.size() == 1) {
        //if there's only 1 keyframe, don't bother interpolating
        return (*_imp->keyFrames.begin())->getValue();
    }
    double tcur,tnext;
    double vcurDerivRight ,vnextDerivLeft ,vcur ,vnext ;
    Natron::KeyframeType interp ,interpNext;
    KeyFrameSet::const_iterator upper = _imp->keyFrames.end();
    for(KeyFrameSet::const_iterator it = _imp->keyFrames.begin();it!=_imp->keyFrames.end();++it){
        if((*it)->getTime() > t){
            upper = it;
            break;
        }else if((*it)->getTime() == t){
            //if the time is exactly the time of a keyframe, return its value
            return (*it)->getValue();
        }
    }

    //if all keys have a greater time (i.e: we search after the last keyframe)
    KeyFrameSet::const_iterator prev = upper;
    --prev;

    //if we found no key that has a greater time (i.e: we search before the 1st keyframe)
    if (upper == _imp->keyFrames.begin()) {
        tnext = (*upper)->getTime();
        vnext = (*upper)->getValue().value<double>();
        vnextDerivLeft = (*upper)->getLeftTangent().value<double>();
        interpNext = (*upper)->getInterpolation();
        tcur = tnext - 1.;
        vcur = vnext;
        vcurDerivRight = 0.;
        interp = Natron::KEYFRAME_NONE;

    } else if (upper == _imp->keyFrames.end()) {
        tcur = (*prev)->getTime();
        vcur = (*prev)->getValue().value<double>();
        vcurDerivRight = (*prev)->getRightTangent().value<double>();
        interp = (*prev)->getInterpolation();
        tnext = tcur + 1.;
        vnext = vcur;
        vnextDerivLeft = 0.;
        interpNext = Natron::KEYFRAME_NONE;
    } else {
        tcur = (*prev)->getTime();
        vcur = (*prev)->getValue().value<double>();
        vcurDerivRight = (*prev)->getRightTangent().value<double>();
        interp = (*prev)->getInterpolation();
        tnext = (*upper)->getTime();
        vnext = (*upper)->getValue().value<double>();
        vnextDerivLeft = (*upper)->getLeftTangent().value<double>();
        interpNext = (*upper)->getInterpolation();
    }

    double v = Natron::interpolate<double>(tcur,vcur,
                                           vcurDerivRight,
                                           vnextDerivLeft,
                                           tnext,vnext,
                                           t,
                                           interp,
                                           interpNext);

    const Variant& firstKeyValue = (*_imp->keyFrames.begin())->getValue();
    switch(firstKeyValue.type()){
    case QVariant::Int :
        return Variant((int)std::floor(v+0.5));
    case QVariant::Double :
        return Variant(v);
    case QVariant::Bool:
        return Variant((bool)std::floor(v+0.5));
    default:
        std::string exc("The type requested ( ");
        exc.append(firstKeyValue.typeName());
        exc.append(") is not interpolable, it cannot animate!");
        throw std::invalid_argument(exc);
    }

}

bool Curve::isAnimated() const { return _imp->keyFrames.size() > 1; }

int Curve::keyFramesCount() const { return (int)_imp->keyFrames.size(); }

const KeyFrameSet& Curve::getKeyFrames() const { return _imp->keyFrames; }

void Curve::setKeyFrameValue(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(value.toDouble() != k->getValue().toDouble()){
        k->setValue(value);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }

}

void Curve::setKeyFrameTime(double time,boost::shared_ptr<KeyFrame> k){
    if(time != k->getTime()){
        k->setTime(time);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }
}

void Curve::setKeyFrameValueAndTime(double time,const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(time != k->getTime() || value.toDouble() != k->getValue().toDouble()){
        k->setTime(time);
        k->setValue(value);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }

}

void Curve::setKeyFrameLeftTangent(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(value.toDouble() != k->getRightTangent().toDouble()){
        k->setLeftTangent(value);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }

}

void Curve::setKeyFrameRightTangent(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(k->getLeftTangent().toDouble()  != value.toDouble()){
        k->setRightTangent(value);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }
}

void Curve::setKeyFrameTangents(const Variant& left,const Variant& right,boost::shared_ptr<KeyFrame> k){
    if(k->getLeftTangent().toDouble()  != left.toDouble() || right.toDouble() != k->getRightTangent().toDouble()){
        k->setLeftTangent(left);
        k->setRightTangent(right);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }

}

void Curve::setKeyFrameInterpolation(Natron::KeyframeType interp,boost::shared_ptr<KeyFrame> k){
    if(k->getInterpolation() != interp){
        k->setInterpolation(interp);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }
}

void Curve::refreshTangents(Curve::CurveChangedReason reason, KeyFrameSet::iterator key){
    double tcur = (*key)->getTime();
    double vcur = (*key)->getValue().value<double>();

    double tprev, vprev, tnext, vnext, vprevDerivRight, vnextDerivLeft;
    Natron::KeyframeType prevType, nextType;
    if (key == _imp->keyFrames.begin()) {
        tprev = tcur;
        vprev = vcur;
        vprevDerivRight = 0.;
        prevType = Natron::KEYFRAME_NONE;
    } else {
        KeyFrameSet::const_iterator prev = key;
        --prev;
        tprev = (*prev)->getTime();
        vprev = (*prev)->getValue().value<double>();
        vprevDerivRight = (*prev)->getRightTangent().value<double>();
        prevType = (*prev)->getInterpolation();

        //if prev is the first keyframe, and not edited by the user then interpolate linearly
        if(prev == _imp->keyFrames.begin() && prevType != Natron::KEYFRAME_FREE &&
           prevType != Natron::KEYFRAME_BROKEN){
            prevType = Natron::KEYFRAME_LINEAR;
        }
    }

    KeyFrameSet::const_iterator next = key;
    ++next;
    if (next == _imp->keyFrames.end()) {
        tnext = tcur;
        vnext = vcur;
        vnextDerivLeft = 0.;
        nextType = Natron::KEYFRAME_NONE;
    } else {
        tnext = (*next)->getTime();
        vnext = (*next)->getValue().value<double>();
        vnextDerivLeft = (*next)->getLeftTangent().value<double>();
        nextType = (*next)->getInterpolation();

        KeyFrameSet::const_iterator nextnext = next;
        ++nextnext;
        //if next is thelast keyframe, and not edited by the user then interpolate linearly
        if(nextnext == _imp->keyFrames.end() && nextType != Natron::KEYFRAME_FREE &&
           nextType != Natron::KEYFRAME_BROKEN){
            nextType = Natron::KEYFRAME_LINEAR;
        }
    }

    double vcurDerivLeft,vcurDerivRight;
    try{
        Natron::autoComputeTangents<double>(prevType,
                                            (*key)->getInterpolation(),
                                            nextType,
                                            tprev, vprev,
                                            tcur, vcur,
                                            tnext, vnext,
                                            vprevDerivRight,
                                            vnextDerivLeft,
                                            &vcurDerivLeft, &vcurDerivRight);
    }catch(const std::exception& e){
        std::cout << e.what() << std::endl;
        assert(false);
    }
    (*key)->setLeftTangent(Variant(vcurDerivLeft));
    (*key)->setRightTangent(Variant(vcurDerivRight));
    if(reason != TANGENT_CHANGED){
        evaluateCurveChanged(TANGENT_CHANGED,*key);
    }

}

void Curve::refreshTangents(CurveChangedReason reason, boost::shared_ptr<KeyFrame> k){
    KeyFrameSet::iterator it = std::find(_imp->keyFrames.begin(),_imp->keyFrames.end(),k);
    assert(it!=_imp->keyFrames.end());
    refreshTangents(reason,it);
}

void Curve::evaluateCurveChanged(CurveChangedReason reason,boost::shared_ptr<KeyFrame> k){
    KeyFrameSet::iterator found = _imp->keyFrames.end();
    for(KeyFrameSet::iterator it =  _imp->keyFrames.begin();it!=_imp->keyFrames.end();++it){
        if((*it) == k){
            found = it;
            break;
        }
    }
    assert(found!=_imp->keyFrames.end());

    if(k->getInterpolation()!= Natron::KEYFRAME_BROKEN && k->getInterpolation() != Natron::KEYFRAME_FREE
       && reason != TANGENT_CHANGED ){
        refreshTangents(TANGENT_CHANGED,found);
    }
    KeyFrameSet::iterator prev = found;
    if(found != _imp->keyFrames.begin()){
        --prev;
        if((*prev)->getInterpolation()!= Natron::KEYFRAME_BROKEN &&
           (*prev)->getInterpolation()!= Natron::KEYFRAME_FREE){
            refreshTangents(TANGENT_CHANGED,prev);
        }
    }
    KeyFrameSet::iterator next = found;
    ++next;
    if(next != _imp->keyFrames.end()){
        if((*next)->getInterpolation()!= Natron::KEYFRAME_BROKEN &&
           (*next)->getInterpolation()!= Natron::KEYFRAME_FREE){
            refreshTangents(TANGENT_CHANGED,next);
        }
    }

    _imp->owner->evaluateAnimationChange();
}
<commit_msg>clone(): copy all values from keyframe<commit_after>//  Natron
//
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
*Created by Alexandre GAUTHIER-FOICHAT on 6/1/2012.
*contact: immarespond at gmail dot com
*
*/

#include "Curve.h"

#include <algorithm>

#include "Engine/CurvePrivate.h"
#include "Engine/Interpolation.h"

namespace {
    struct KeyFrameCloner {
        boost::shared_ptr<KeyFrame> operator()(const boost::shared_ptr<KeyFrame>& kf) const { return boost::shared_ptr<KeyFrame>(new KeyFrame(*kf)); }
    };

    class KeyFrameTimePredicate
    {
    public:
        KeyFrameTimePredicate(double t) : _t(t) {};

        bool operator()(const boost::shared_ptr<KeyFrame>& f) { return (f->getTime() == _t); }
    private:
        double _t;
    };
}

/************************************KEYFRAME************************************/

KeyFrame::KeyFrame()
    : _imp(new KeyFramePrivate)
{}

KeyFrame::KeyFrame(double time, const Variant& initialValue)
    : _imp(new KeyFramePrivate(time,initialValue))
{
}

KeyFrame::KeyFrame(const KeyFrame& other)
    : _imp(new KeyFramePrivate(*(other._imp)))
{
}

void KeyFrame::operator=(const KeyFrame& o)
{
    _imp->time = o._imp->time;
    _imp->value = o._imp->value;
    _imp->leftTangent = o._imp->leftTangent;
    _imp->rightTangent = o._imp->rightTangent;
    _imp->interpolation = o._imp->interpolation;
}

KeyFrame::~KeyFrame(){}

bool KeyFrame::operator==(const KeyFrame& o) const {
    return _imp->value == o._imp->value &&
            _imp->time == o._imp->time;
}

void KeyFrame::setLeftTangent(const Variant& v){
    _imp->leftTangent = v;
}

void KeyFrame::setRightTangent(const Variant& v){
    _imp->rightTangent = v;
}

void KeyFrame::setValue(const Variant& v){
    _imp->value = v;
}

void KeyFrame::setTime(double time){
    _imp->time = time;
}

void KeyFrame::setInterpolation(Natron::KeyframeType interp) { _imp->interpolation = interp; }

Natron::KeyframeType KeyFrame::getInterpolation() const { return _imp->interpolation; }

const Variant& KeyFrame::getValue() const { return _imp->value; }

double KeyFrame::getTime() const { return _imp->time; }

const Variant& KeyFrame::getLeftTangent() const { return _imp->leftTangent; }

const Variant& KeyFrame::getRightTangent() const { return _imp->rightTangent; }

/************************************CURVEPATH************************************/

Curve::Curve()
    : _imp(new CurvePrivate)
{

}

Curve::Curve(Knob *owner)
    : _imp(new CurvePrivate)
{
    _imp->owner = owner;
}

Curve::~Curve(){ clearKeyFrames(); }

void Curve::clearKeyFrames(){
    _imp->keyFrames.clear();
}

void Curve::clone(const Curve& other){
    clearKeyFrames();
    const KeyFrameSet& otherKeys = other.getKeyFrames();
    std::transform(otherKeys.begin(), otherKeys.end(), std::inserter(_imp->keyFrames, _imp->keyFrames.begin()), KeyFrameCloner());
}

double Curve::getMinimumTimeCovered() const{
    assert(!_imp->keyFrames.empty());
    return (*_imp->keyFrames.begin())->getTime();
}

double Curve::getMaximumTimeCovered() const{
    assert(!_imp->keyFrames.empty());
    return (*_imp->keyFrames.rbegin())->getTime();
}

void Curve::addKeyFrame(boost::shared_ptr<KeyFrame> cp)
{
    std::pair<KeyFrameSet::iterator,bool> newKey = _imp->keyFrames.insert(cp);
    if (newKey.second) {
        refreshTangents(KEYFRAME_CHANGED, newKey.first);
    }else{
        (*newKey.first)->setValue(cp->getValue());
    }
}

void Curve::removeKeyFrame(boost::shared_ptr<KeyFrame> cp) {
    KeyFrameSet::iterator it = std::find(_imp->keyFrames.begin(),_imp->keyFrames.end(),cp);
    KeyFrameSet::iterator prev = it;
    boost::shared_ptr<KeyFrame> prevCp;
    boost::shared_ptr<KeyFrame> nextCp;
    if(it != _imp->keyFrames.begin()){
        --prev;
        prevCp = (*prev);
    }
    KeyFrameSet::iterator next = it;
    ++next;
    if(next != _imp->keyFrames.end()){
        nextCp = (*next);
    }
    _imp->keyFrames.erase(it);
    if(prevCp){
        refreshTangents(TANGENT_CHANGED,prevCp);
    }
    if(nextCp){
        refreshTangents(TANGENT_CHANGED,nextCp);
    }

}

void Curve::removeKeyFrame(double time) {
    KeyFrameSet::iterator it = std::find_if(_imp->keyFrames.begin(), _imp->keyFrames.end(), KeyFrameTimePredicate(time));
    if (it != _imp->keyFrames.end()) {
        removeKeyFrame(*it);
    }
}

Variant Curve::getValueAt(double t) const {
    assert(!_imp->keyFrames.empty());
    if (_imp->keyFrames.size() == 1) {
        //if there's only 1 keyframe, don't bother interpolating
        return (*_imp->keyFrames.begin())->getValue();
    }
    double tcur,tnext;
    double vcurDerivRight ,vnextDerivLeft ,vcur ,vnext ;
    Natron::KeyframeType interp ,interpNext;
    KeyFrameSet::const_iterator upper = _imp->keyFrames.end();
    for(KeyFrameSet::const_iterator it = _imp->keyFrames.begin();it!=_imp->keyFrames.end();++it){
        if((*it)->getTime() > t){
            upper = it;
            break;
        }else if((*it)->getTime() == t){
            //if the time is exactly the time of a keyframe, return its value
            return (*it)->getValue();
        }
    }

    //if all keys have a greater time (i.e: we search after the last keyframe)
    KeyFrameSet::const_iterator prev = upper;
    --prev;

    //if we found no key that has a greater time (i.e: we search before the 1st keyframe)
    if (upper == _imp->keyFrames.begin()) {
        tnext = (*upper)->getTime();
        vnext = (*upper)->getValue().value<double>();
        vnextDerivLeft = (*upper)->getLeftTangent().value<double>();
        interpNext = (*upper)->getInterpolation();
        tcur = tnext - 1.;
        vcur = vnext;
        vcurDerivRight = 0.;
        interp = Natron::KEYFRAME_NONE;

    } else if (upper == _imp->keyFrames.end()) {
        tcur = (*prev)->getTime();
        vcur = (*prev)->getValue().value<double>();
        vcurDerivRight = (*prev)->getRightTangent().value<double>();
        interp = (*prev)->getInterpolation();
        tnext = tcur + 1.;
        vnext = vcur;
        vnextDerivLeft = 0.;
        interpNext = Natron::KEYFRAME_NONE;
    } else {
        tcur = (*prev)->getTime();
        vcur = (*prev)->getValue().value<double>();
        vcurDerivRight = (*prev)->getRightTangent().value<double>();
        interp = (*prev)->getInterpolation();
        tnext = (*upper)->getTime();
        vnext = (*upper)->getValue().value<double>();
        vnextDerivLeft = (*upper)->getLeftTangent().value<double>();
        interpNext = (*upper)->getInterpolation();
    }

    double v = Natron::interpolate<double>(tcur,vcur,
                                           vcurDerivRight,
                                           vnextDerivLeft,
                                           tnext,vnext,
                                           t,
                                           interp,
                                           interpNext);

    const Variant& firstKeyValue = (*_imp->keyFrames.begin())->getValue();
    switch(firstKeyValue.type()){
    case QVariant::Int :
        return Variant((int)std::floor(v+0.5));
    case QVariant::Double :
        return Variant(v);
    case QVariant::Bool:
        return Variant((bool)std::floor(v+0.5));
    default:
        std::string exc("The type requested ( ");
        exc.append(firstKeyValue.typeName());
        exc.append(") is not interpolable, it cannot animate!");
        throw std::invalid_argument(exc);
    }

}

bool Curve::isAnimated() const { return _imp->keyFrames.size() > 1; }

int Curve::keyFramesCount() const { return (int)_imp->keyFrames.size(); }

const KeyFrameSet& Curve::getKeyFrames() const { return _imp->keyFrames; }

void Curve::setKeyFrameValue(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(value.toDouble() != k->getValue().toDouble()){
        k->setValue(value);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }

}

void Curve::setKeyFrameTime(double time,boost::shared_ptr<KeyFrame> k){
    if(time != k->getTime()){
        k->setTime(time);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }
}

void Curve::setKeyFrameValueAndTime(double time,const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(time != k->getTime() || value.toDouble() != k->getValue().toDouble()){
        k->setTime(time);
        k->setValue(value);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }

}

void Curve::setKeyFrameLeftTangent(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(value.toDouble() != k->getRightTangent().toDouble()){
        k->setLeftTangent(value);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }

}

void Curve::setKeyFrameRightTangent(const Variant& value,boost::shared_ptr<KeyFrame> k){
    if(k->getLeftTangent().toDouble()  != value.toDouble()){
        k->setRightTangent(value);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }
}

void Curve::setKeyFrameTangents(const Variant& left,const Variant& right,boost::shared_ptr<KeyFrame> k){
    if(k->getLeftTangent().toDouble()  != left.toDouble() || right.toDouble() != k->getRightTangent().toDouble()){
        k->setLeftTangent(left);
        k->setRightTangent(right);
        evaluateCurveChanged(TANGENT_CHANGED,k);
    }

}

void Curve::setKeyFrameInterpolation(Natron::KeyframeType interp,boost::shared_ptr<KeyFrame> k){
    if(k->getInterpolation() != interp){
        k->setInterpolation(interp);
        evaluateCurveChanged(KEYFRAME_CHANGED,k);
    }
}

void Curve::refreshTangents(Curve::CurveChangedReason reason, KeyFrameSet::iterator key){
    double tcur = (*key)->getTime();
    double vcur = (*key)->getValue().value<double>();

    double tprev, vprev, tnext, vnext, vprevDerivRight, vnextDerivLeft;
    Natron::KeyframeType prevType, nextType;
    if (key == _imp->keyFrames.begin()) {
        tprev = tcur;
        vprev = vcur;
        vprevDerivRight = 0.;
        prevType = Natron::KEYFRAME_NONE;
    } else {
        KeyFrameSet::const_iterator prev = key;
        --prev;
        tprev = (*prev)->getTime();
        vprev = (*prev)->getValue().value<double>();
        vprevDerivRight = (*prev)->getRightTangent().value<double>();
        prevType = (*prev)->getInterpolation();

        //if prev is the first keyframe, and not edited by the user then interpolate linearly
        if(prev == _imp->keyFrames.begin() && prevType != Natron::KEYFRAME_FREE &&
           prevType != Natron::KEYFRAME_BROKEN){
            prevType = Natron::KEYFRAME_LINEAR;
        }
    }

    KeyFrameSet::const_iterator next = key;
    ++next;
    if (next == _imp->keyFrames.end()) {
        tnext = tcur;
        vnext = vcur;
        vnextDerivLeft = 0.;
        nextType = Natron::KEYFRAME_NONE;
    } else {
        tnext = (*next)->getTime();
        vnext = (*next)->getValue().value<double>();
        vnextDerivLeft = (*next)->getLeftTangent().value<double>();
        nextType = (*next)->getInterpolation();

        KeyFrameSet::const_iterator nextnext = next;
        ++nextnext;
        //if next is thelast keyframe, and not edited by the user then interpolate linearly
        if(nextnext == _imp->keyFrames.end() && nextType != Natron::KEYFRAME_FREE &&
           nextType != Natron::KEYFRAME_BROKEN){
            nextType = Natron::KEYFRAME_LINEAR;
        }
    }

    double vcurDerivLeft,vcurDerivRight;
    try{
        Natron::autoComputeTangents<double>(prevType,
                                            (*key)->getInterpolation(),
                                            nextType,
                                            tprev, vprev,
                                            tcur, vcur,
                                            tnext, vnext,
                                            vprevDerivRight,
                                            vnextDerivLeft,
                                            &vcurDerivLeft, &vcurDerivRight);
    }catch(const std::exception& e){
        std::cout << e.what() << std::endl;
        assert(false);
    }
    (*key)->setLeftTangent(Variant(vcurDerivLeft));
    (*key)->setRightTangent(Variant(vcurDerivRight));
    if(reason != TANGENT_CHANGED){
        evaluateCurveChanged(TANGENT_CHANGED,*key);
    }

}

void Curve::refreshTangents(CurveChangedReason reason, boost::shared_ptr<KeyFrame> k){
    KeyFrameSet::iterator it = std::find(_imp->keyFrames.begin(),_imp->keyFrames.end(),k);
    assert(it!=_imp->keyFrames.end());
    refreshTangents(reason,it);
}

void Curve::evaluateCurveChanged(CurveChangedReason reason,boost::shared_ptr<KeyFrame> k){
    KeyFrameSet::iterator found = _imp->keyFrames.end();
    for(KeyFrameSet::iterator it =  _imp->keyFrames.begin();it!=_imp->keyFrames.end();++it){
        if((*it) == k){
            found = it;
            break;
        }
    }
    assert(found!=_imp->keyFrames.end());

    if(k->getInterpolation()!= Natron::KEYFRAME_BROKEN && k->getInterpolation() != Natron::KEYFRAME_FREE
       && reason != TANGENT_CHANGED ){
        refreshTangents(TANGENT_CHANGED,found);
    }
    KeyFrameSet::iterator prev = found;
    if(found != _imp->keyFrames.begin()){
        --prev;
        if((*prev)->getInterpolation()!= Natron::KEYFRAME_BROKEN &&
           (*prev)->getInterpolation()!= Natron::KEYFRAME_FREE){
            refreshTangents(TANGENT_CHANGED,prev);
        }
    }
    KeyFrameSet::iterator next = found;
    ++next;
    if(next != _imp->keyFrames.end()){
        if((*next)->getInterpolation()!= Natron::KEYFRAME_BROKEN &&
           (*next)->getInterpolation()!= Natron::KEYFRAME_FREE){
            refreshTangents(TANGENT_CHANGED,next);
        }
    }

    _imp->owner->evaluateAnimationChange();
}
<|endoftext|>


<commit_before>//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a DeadStores, a flow-sensitive checker that looks for
//  stores to variables that are no longer live.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include <sstream>

using namespace clang;

static bool scan_dealloc(Stmt* S, Selector Dealloc) {

  if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
    if (ME->getSelector() == Dealloc)
      if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts())
        if (PreDefinedExpr* E = dyn_cast<PreDefinedExpr>(Receiver))
          if (E->getIdentType() == PreDefinedExpr::ObjCSuper)
            return true;

  // Recurse to children.

  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
    if (*I && scan_dealloc(*I, Dealloc))
      return true;

  return false;
}

void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
                             const LangOptions& LOpts, BugReporter& BR) {

  assert (LOpts.getGCMode() != LangOptions::GCOnly);

  ASTContext& Ctx = BR.getContext();
  ObjCInterfaceDecl* ID = D->getClassInterface();

  // Does the class contain any ivars that are pointers (or id<...>)?
  // If not, skip the check entirely.
  // NOTE: This is motivated by PR 2517:
  //        http://llvm.org/bugs/show_bug.cgi?id=2517

  bool containsPointerIvar = false;

  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
       I!=E; ++I) {

    QualType T = (*I)->getType();

    if (T->isPointerType() || T->isObjCQualifiedIdType()) {
      containsPointerIvar = true;
      break;
    }
  }

  if (!containsPointerIvar)
    return;

  // Determine if the class subclasses NSObject.
  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier() == NSObjectII)
      break;

  if (!ID)
    return;

  // Get the "dealloc" selector.
  IdentifierInfo* II = &Ctx.Idents.get("dealloc");
  Selector S = Ctx.Selectors.getSelector(0, &II);

  ObjCMethodDecl* MD = 0;

  // Scan the instance methods for "dealloc".
  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
       E = D->instmeth_end(); I!=E; ++I) {

    if ((*I)->getSelector() == S) {
      MD = *I;
      break;
    }
  }

  if (!MD) { // No dealloc found.

    // FIXME: This code should be reduced to three lines if possible (Refactor).
    SimpleBugType BT(LOpts.getGCMode() == LangOptions::NonGC
                     ? "missing -dealloc"
                     : "missing -dealloc (Hybrid MM, non-GC)");

    DiagCollector C(BT);

    std::ostringstream os;
    os << "Objective-C class '" << D->getName()
       << "' lacks a 'dealloc' instance method";

    Diagnostic& Diag = BR.getDiagnostic();
    Diag.Report(&C,
                Ctx.getFullLoc(D->getLocStart()),
                Diag.getCustomDiagID(Diagnostic::Warning, os.str().c_str()),
                NULL, 0, NULL, 0);

    for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
      BR.EmitWarning(*I);

    return;
  }

  // dealloc found.  Scan for missing [super dealloc].
  if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {

    // FIXME: This code should be reduced to three lines if possible (Refactor).
    SimpleBugType BT(LOpts.getGCMode() == LangOptions::NonGC
                     ? "missing [super dealloc]"
                     : "missing [super dealloc] (Hybrid MM, non-GC)");

    DiagCollector C(BT);

    std::ostringstream os;
    os << "The 'dealloc' instance method in Objective-C class '" << D->getName()
       << "' does not send a 'dealloc' message to its super class"
           " (missing [super dealloc])";

    Diagnostic& Diag = BR.getDiagnostic();
    Diag.Report(&C,
                Ctx.getFullLoc(MD->getLocStart()),
                Diag.getCustomDiagID(Diagnostic::Warning, os.str().c_str()),
                NULL, 0, NULL, 0);

    for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
      BR.EmitWarning(*I);
  }
}

<commit_msg>Fix comment.<commit_after>//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a CheckObjCDealloc, a checker that
//  analyzes an Objective-C class's implementation to determine if it
//  correctly implements -dealloc.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include <sstream>

using namespace clang;

static bool scan_dealloc(Stmt* S, Selector Dealloc) {

  if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
    if (ME->getSelector() == Dealloc)
      if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts())
        if (PreDefinedExpr* E = dyn_cast<PreDefinedExpr>(Receiver))
          if (E->getIdentType() == PreDefinedExpr::ObjCSuper)
            return true;

  // Recurse to children.

  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
    if (*I && scan_dealloc(*I, Dealloc))
      return true;

  return false;
}

void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
                             const LangOptions& LOpts, BugReporter& BR) {

  assert (LOpts.getGCMode() != LangOptions::GCOnly);

  ASTContext& Ctx = BR.getContext();
  ObjCInterfaceDecl* ID = D->getClassInterface();

  // Does the class contain any ivars that are pointers (or id<...>)?
  // If not, skip the check entirely.
  // NOTE: This is motivated by PR 2517:
  //        http://llvm.org/bugs/show_bug.cgi?id=2517

  bool containsPointerIvar = false;

  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
       I!=E; ++I) {

    QualType T = (*I)->getType();

    if (T->isPointerType() || T->isObjCQualifiedIdType()) {
      containsPointerIvar = true;
      break;
    }
  }

  if (!containsPointerIvar)
    return;

  // Determine if the class subclasses NSObject.
  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier() == NSObjectII)
      break;

  if (!ID)
    return;

  // Get the "dealloc" selector.
  IdentifierInfo* II = &Ctx.Idents.get("dealloc");
  Selector S = Ctx.Selectors.getSelector(0, &II);

  ObjCMethodDecl* MD = 0;

  // Scan the instance methods for "dealloc".
  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
       E = D->instmeth_end(); I!=E; ++I) {

    if ((*I)->getSelector() == S) {
      MD = *I;
      break;
    }
  }

  if (!MD) { // No dealloc found.

    // FIXME: This code should be reduced to three lines if possible (Refactor).
    SimpleBugType BT(LOpts.getGCMode() == LangOptions::NonGC
                     ? "missing -dealloc"
                     : "missing -dealloc (Hybrid MM, non-GC)");

    DiagCollector C(BT);

    std::ostringstream os;
    os << "Objective-C class '" << D->getName()
       << "' lacks a 'dealloc' instance method";

    Diagnostic& Diag = BR.getDiagnostic();
    Diag.Report(&C,
                Ctx.getFullLoc(D->getLocStart()),
                Diag.getCustomDiagID(Diagnostic::Warning, os.str().c_str()),
                NULL, 0, NULL, 0);

    for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
      BR.EmitWarning(*I);

    return;
  }

  // dealloc found.  Scan for missing [super dealloc].
  if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {

    // FIXME: This code should be reduced to three lines if possible (Refactor).
    SimpleBugType BT(LOpts.getGCMode() == LangOptions::NonGC
                     ? "missing [super dealloc]"
                     : "missing [super dealloc] (Hybrid MM, non-GC)");

    DiagCollector C(BT);

    std::ostringstream os;
    os << "The 'dealloc' instance method in Objective-C class '" << D->getName()
       << "' does not send a 'dealloc' message to its super class"
           " (missing [super dealloc])";

    Diagnostic& Diag = BR.getDiagnostic();
    Diag.Report(&C,
                Ctx.getFullLoc(MD->getLocStart()),
                Diag.getCustomDiagID(Diagnostic::Warning, os.str().c_str()),
                NULL, 0, NULL, 0);

    for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
      BR.EmitWarning(*I);
  }
}

<|endoftext|>


<commit_before>//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a CheckObjCDealloc, a checker that
//  analyzes an Objective-C class's implementation to determine if it
//  correctly implements -dealloc.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include <sstream>

using namespace clang;

static bool scan_dealloc(Stmt* S, Selector Dealloc) {

  if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
    if (ME->getSelector() == Dealloc)
      if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts())
        if (PreDefinedExpr* E = dyn_cast<PreDefinedExpr>(Receiver))
          if (E->getIdentType() == PreDefinedExpr::ObjCSuper)
            return true;

  // Recurse to children.

  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
    if (*I && scan_dealloc(*I, Dealloc))
      return true;

  return false;
}

static bool isSEL(QualType T, IdentifierInfo* SelII) {
  if (const TypedefType* Ty = T->getAsTypedefType())
    return Ty->getDecl()->getIdentifier() == SelII;

  return false;
}

void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
                             const LangOptions& LOpts, BugReporter& BR) {

  assert (LOpts.getGCMode() != LangOptions::GCOnly);

  ASTContext& Ctx = BR.getContext();
  ObjCInterfaceDecl* ID = D->getClassInterface();

  // Does the class contain any ivars that are pointers (or id<...>)?
  // If not, skip the check entirely.
  // NOTE: This is motivated by PR 2517:
  //        http://llvm.org/bugs/show_bug.cgi?id=2517

  bool containsPointerIvar = false;
  IdentifierInfo* SelII = &Ctx.Idents.get("SEL");

  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
       I!=E; ++I) {

    ObjCIvarDecl* ID = *I;
    QualType T = ID->getType();

    if ((T->isPointerType() || Ctx.isObjCObjectPointerType(T)) &&
         (ID->getAttr<IBOutletAttr>() == 0 && // Skip IBOutlets.
          !isSEL(T, SelII))) { // Skip SEL ivars.
      containsPointerIvar = true;
      break;
    }
  }

  if (!containsPointerIvar)
    return;

  // Determine if the class subclasses NSObject.
  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier() == NSObjectII)
      break;

  if (!ID)
    return;

  // Get the "dealloc" selector.
  IdentifierInfo* II = &Ctx.Idents.get("dealloc");
  Selector S = Ctx.Selectors.getSelector(0, &II);
  ObjCMethodDecl* MD = 0;

  // Scan the instance methods for "dealloc".
  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
       E = D->instmeth_end(); I!=E; ++I) {

    if ((*I)->getSelector() == S) {
      MD = *I;
      break;
    }
  }

  if (!MD) { // No dealloc found.

    const char* name = LOpts.getGCMode() == LangOptions::NonGC
                       ? "missing -dealloc"
                       : "missing -dealloc (Hybrid MM, non-GC)";

    std::ostringstream os;
    os << "Objective-C class '" << D->getName()
       << "' lacks a 'dealloc' instance method";

    BR.EmitBasicReport(name, os.str().c_str(), D->getLocStart());
    return;
  }

  // dealloc found.  Scan for missing [super dealloc].
  if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {

    const char* name = LOpts.getGCMode() == LangOptions::NonGC
                       ? "missing [super dealloc]"
                       : "missing [super dealloc] (Hybrid MM, non-GC)";

    std::ostringstream os;
    os << "The 'dealloc' instance method in Objective-C class '" << D->getName()
       << "' does not send a 'dealloc' message to its super class"
           " (missing [super dealloc])";

    BR.EmitBasicReport(name, os.str().c_str(), D->getLocStart());
    return;
  }
}

<commit_msg>Only warn about missing/incomplete -dealloc implementations when a class contains a non-SEL, non-IBOutlet ivar that references an ObjC object.<commit_after>//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- C++ -*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines a CheckObjCDealloc, a checker that
//  analyzes an Objective-C class's implementation to determine if it
//  correctly implements -dealloc.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include <sstream>

using namespace clang;

static bool scan_dealloc(Stmt* S, Selector Dealloc) {

  if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S))
    if (ME->getSelector() == Dealloc)
      if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts())
        if (PreDefinedExpr* E = dyn_cast<PreDefinedExpr>(Receiver))
          if (E->getIdentType() == PreDefinedExpr::ObjCSuper)
            return true;

  // Recurse to children.

  for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I)
    if (*I && scan_dealloc(*I, Dealloc))
      return true;

  return false;
}

static bool isSEL(QualType T, IdentifierInfo* SelII) {
  if (const TypedefType* Ty = T->getAsTypedefType())
    return Ty->getDecl()->getIdentifier() == SelII;

  return false;
}

void clang::CheckObjCDealloc(ObjCImplementationDecl* D,
                             const LangOptions& LOpts, BugReporter& BR) {

  assert (LOpts.getGCMode() != LangOptions::GCOnly);

  ASTContext& Ctx = BR.getContext();
  ObjCInterfaceDecl* ID = D->getClassInterface();

  // Does the class contain any ivars that are pointers (or id<...>)?
  // If not, skip the check entirely.
  // NOTE: This is motivated by PR 2517:
  //        http://llvm.org/bugs/show_bug.cgi?id=2517

  bool containsPointerIvar = false;
  IdentifierInfo* SelII = &Ctx.Idents.get("SEL");

  for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end();
       I!=E; ++I) {

    ObjCIvarDecl* ID = *I;
    QualType T = ID->getType();

    if (!Ctx.isObjCObjectPointerType(T) ||
        ID->getAttr<IBOutletAttr>() || // Skip IBOutlets.
        isSEL(T, SelII)) // Skip SEL ivars.
      continue;

    containsPointerIvar = true;
    break;
  }

  if (!containsPointerIvar)
    return;

  // Determine if the class subclasses NSObject.
  IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");

  for ( ; ID ; ID = ID->getSuperClass())
    if (ID->getIdentifier() == NSObjectII)
      break;

  if (!ID)
    return;

  // Get the "dealloc" selector.
  IdentifierInfo* II = &Ctx.Idents.get("dealloc");
  Selector S = Ctx.Selectors.getSelector(0, &II);
  ObjCMethodDecl* MD = 0;

  // Scan the instance methods for "dealloc".
  for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(),
       E = D->instmeth_end(); I!=E; ++I) {

    if ((*I)->getSelector() == S) {
      MD = *I;
      break;
    }
  }

  if (!MD) { // No dealloc found.

    const char* name = LOpts.getGCMode() == LangOptions::NonGC
                       ? "missing -dealloc"
                       : "missing -dealloc (Hybrid MM, non-GC)";

    std::ostringstream os;
    os << "Objective-C class '" << D->getName()
       << "' lacks a 'dealloc' instance method";

    BR.EmitBasicReport(name, os.str().c_str(), D->getLocStart());
    return;
  }

  // dealloc found.  Scan for missing [super dealloc].
  if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) {

    const char* name = LOpts.getGCMode() == LangOptions::NonGC
                       ? "missing [super dealloc]"
                       : "missing [super dealloc] (Hybrid MM, non-GC)";

    std::ostringstream os;
    os << "The 'dealloc' instance method in Objective-C class '" << D->getName()
       << "' does not send a 'dealloc' message to its super class"
           " (missing [super dealloc])";

    BR.EmitBasicReport(name, os.str().c_str(), D->getLocStart());
    return;
  }
}

<|endoftext|>


<commit_before>#include "amuse/AudioGroupSampleDirectory.hpp"
#include "amuse/Common.hpp"
#include <string.h>

namespace amuse
{

void AudioGroupSampleDirectory::Entry::swapBig()
{
    m_sfxId = SBig(m_sfxId);
    m_sampleOff = SBig(m_sampleOff);
    m_unk = SBig(m_unk);
    m_sampleRate = SBig(m_sampleRate);
    m_numSamples = SBig(m_numSamples);
    m_loopStartSample = SBig(m_loopStartSample);
    m_loopLengthSamples = SBig(m_loopLengthSamples);
    m_adpcmParmOffset = SBig(m_adpcmParmOffset);
}

void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
{
    dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
    dsp.m_hist2 = SBig(dsp.m_hist2);
    dsp.m_hist1 = SBig(dsp.m_hist1);
    for (int i=0 ; i<8 ; ++i)
    {
        dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
        dsp.m_coefs[i][1] = SBig(dsp.m_coefs[i][1]);
    }
}

void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
{
    int16_t* allCoefs = reinterpret_cast<int16_t*>(vadpcm.m_coefs[0][0]);
    for (int i=0 ; i<128 ; ++i)
        allCoefs[i] = SBig(allCoefs[i]);
}

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag)
{
    const unsigned char* cur = data;
    while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
    {
        const AudioGroupSampleDirectory::Entry* ent =
            reinterpret_cast<const AudioGroupSampleDirectory::Entry*>(cur);

        std::pair<Entry, ADPCMParms>& store = m_entries[SBig(ent->m_sfxId)];
        store.first = *ent;
        store.first.swapBig();

        if (store.first.m_adpcmParmOffset)
        {
            const AudioGroupSampleDirectory::ADPCMParms* adpcm =
                reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data +
                    store.first.m_adpcmParmOffset);
            store.second = *adpcm;
            store.second.swapBigDSP();
        }

        cur += 32;
    }
}

struct MusyX1SdirEntry
{
    uint16_t m_sfxId;
    uint32_t m_sampleOff;
    uint32_t m_pitchSampleRate;
    uint32_t m_numSamples;
    uint32_t m_loopStartSample;
    uint32_t m_loopLengthSamples;

    void swapBig()
    {
        m_sfxId = SBig(m_sfxId);
        m_sampleOff = SBig(m_sampleOff);
        m_pitchSampleRate = SBig(m_pitchSampleRate);
        m_numSamples = SBig(m_numSamples);
        m_loopStartSample = SBig(m_loopStartSample);
        m_loopLengthSamples = SBig(m_loopLengthSamples);
    }

    void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
    {
        ent.m_sfxId = m_sfxId;
        ent.m_sampleOff = m_sampleOff;
        ent.m_unk = 0;
        ent.m_pitch = m_pitchSampleRate >> 24;
        ent.m_sampleRate = m_pitchSampleRate & 0xffff;
        ent.m_numSamples = m_numSamples;
        ent.m_loopStartSample = m_loopStartSample;
        ent.m_loopLengthSamples = m_loopLengthSamples;
        ent.m_adpcmParmOffset = 0;
    }
};

struct MusyX1AbsSdirEntry
{
    uint16_t m_sfxId;
    uint32_t m_sampleOff;
    uint32_t m_unk;
    uint32_t m_pitchSampleRate;
    uint32_t m_numSamples;
    uint32_t m_loopStartSample;
    uint32_t m_loopLengthSamples;

    void swapBig()
    {
        m_sfxId = SBig(m_sfxId);
        m_sampleOff = SBig(m_sampleOff);
        m_unk = SBig(m_unk);
        m_pitchSampleRate = SBig(m_pitchSampleRate);
        m_numSamples = SBig(m_numSamples);
        m_loopStartSample = SBig(m_loopStartSample);
        m_loopLengthSamples = SBig(m_loopLengthSamples);
    }

    void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
    {
        ent.m_sfxId = m_sfxId;
        ent.m_sampleOff = m_sampleOff;
        ent.m_unk = m_unk;
        ent.m_pitch = m_pitchSampleRate >> 24;
        ent.m_sampleRate = m_pitchSampleRate & 0xffff;
        ent.m_numSamples = m_numSamples;
        ent.m_loopStartSample = m_loopStartSample;
        ent.m_loopLengthSamples = m_loopLengthSamples;
        ent.m_adpcmParmOffset = 0;
    }
};

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
                                                     const unsigned char* sampData,
                                                     bool absOffs, N64DataTag)
{
    const unsigned char* cur = data;

    if (absOffs)
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            MusyX1AbsSdirEntry ent = *reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
            ent.swapBig();

            std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
            ent.setIntoMusyX2(store.first);

            memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
            store.second.swapBigVADPCM();

            cur += 28;
        }
    }
    else
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            MusyX1SdirEntry ent = *reinterpret_cast<const MusyX1SdirEntry*>(cur);
            ent.swapBig();

            std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
            ent.setIntoMusyX2(store.first);

            memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
            store.second.swapBigVADPCM();

            cur += 24;
        }
    }
}

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
                                                     bool absOffs, PCDataTag)
{
    const unsigned char* cur = data;

    if (absOffs)
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            const MusyX1AbsSdirEntry* ent = reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);

            std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
            ent->setIntoMusyX2(store.first);

            cur += 28;
        }
    }
    else
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            const MusyX1SdirEntry* ent = reinterpret_cast<const MusyX1SdirEntry*>(cur);

            std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
            ent->setIntoMusyX2(store.first);

            cur += 24;
        }
    }
}

}
<commit_msg>ADPCM parameter copy fix<commit_after>#include "amuse/AudioGroupSampleDirectory.hpp"
#include "amuse/Common.hpp"
#include <string.h>

namespace amuse
{

void AudioGroupSampleDirectory::Entry::swapBig()
{
    m_sfxId = SBig(m_sfxId);
    m_sampleOff = SBig(m_sampleOff);
    m_unk = SBig(m_unk);
    m_sampleRate = SBig(m_sampleRate);
    m_numSamples = SBig(m_numSamples);
    m_loopStartSample = SBig(m_loopStartSample);
    m_loopLengthSamples = SBig(m_loopLengthSamples);
    m_adpcmParmOffset = SBig(m_adpcmParmOffset);
}

void AudioGroupSampleDirectory::ADPCMParms::swapBigDSP()
{
    dsp.m_bytesPerFrame = SBig(dsp.m_bytesPerFrame);
    dsp.m_hist2 = SBig(dsp.m_hist2);
    dsp.m_hist1 = SBig(dsp.m_hist1);
    for (int i=0 ; i<8 ; ++i)
    {
        dsp.m_coefs[i][0] = SBig(dsp.m_coefs[i][0]);
        dsp.m_coefs[i][1] = SBig(dsp.m_coefs[i][1]);
    }
}

void AudioGroupSampleDirectory::ADPCMParms::swapBigVADPCM()
{
    int16_t* allCoefs = reinterpret_cast<int16_t*>(vadpcm.m_coefs[0][0]);
    for (int i=0 ; i<128 ; ++i)
        allCoefs[i] = SBig(allCoefs[i]);
}

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data, GCNDataTag)
{
    const unsigned char* cur = data;
    while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
    {
        const AudioGroupSampleDirectory::Entry* ent =
            reinterpret_cast<const AudioGroupSampleDirectory::Entry*>(cur);

        std::pair<Entry, ADPCMParms>& store = m_entries[SBig(ent->m_sfxId)];
        store.first = *ent;
        store.first.swapBig();

        if (store.first.m_adpcmParmOffset)
        {
            const AudioGroupSampleDirectory::ADPCMParms* adpcm =
                reinterpret_cast<const AudioGroupSampleDirectory::ADPCMParms*>(data +
                    store.first.m_adpcmParmOffset);
            store.second.dsp = adpcm->dsp;
            store.second.swapBigDSP();
        }

        cur += 32;
    }
}

struct MusyX1SdirEntry
{
    uint16_t m_sfxId;
    uint32_t m_sampleOff;
    uint32_t m_pitchSampleRate;
    uint32_t m_numSamples;
    uint32_t m_loopStartSample;
    uint32_t m_loopLengthSamples;

    void swapBig()
    {
        m_sfxId = SBig(m_sfxId);
        m_sampleOff = SBig(m_sampleOff);
        m_pitchSampleRate = SBig(m_pitchSampleRate);
        m_numSamples = SBig(m_numSamples);
        m_loopStartSample = SBig(m_loopStartSample);
        m_loopLengthSamples = SBig(m_loopLengthSamples);
    }

    void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
    {
        ent.m_sfxId = m_sfxId;
        ent.m_sampleOff = m_sampleOff;
        ent.m_unk = 0;
        ent.m_pitch = m_pitchSampleRate >> 24;
        ent.m_sampleRate = m_pitchSampleRate & 0xffff;
        ent.m_numSamples = m_numSamples;
        ent.m_loopStartSample = m_loopStartSample;
        ent.m_loopLengthSamples = m_loopLengthSamples;
        ent.m_adpcmParmOffset = 0;
    }
};

struct MusyX1AbsSdirEntry
{
    uint16_t m_sfxId;
    uint32_t m_sampleOff;
    uint32_t m_unk;
    uint32_t m_pitchSampleRate;
    uint32_t m_numSamples;
    uint32_t m_loopStartSample;
    uint32_t m_loopLengthSamples;

    void swapBig()
    {
        m_sfxId = SBig(m_sfxId);
        m_sampleOff = SBig(m_sampleOff);
        m_unk = SBig(m_unk);
        m_pitchSampleRate = SBig(m_pitchSampleRate);
        m_numSamples = SBig(m_numSamples);
        m_loopStartSample = SBig(m_loopStartSample);
        m_loopLengthSamples = SBig(m_loopLengthSamples);
    }

    void setIntoMusyX2(AudioGroupSampleDirectory::Entry& ent) const
    {
        ent.m_sfxId = m_sfxId;
        ent.m_sampleOff = m_sampleOff;
        ent.m_unk = m_unk;
        ent.m_pitch = m_pitchSampleRate >> 24;
        ent.m_sampleRate = m_pitchSampleRate & 0xffff;
        ent.m_numSamples = m_numSamples;
        ent.m_loopStartSample = m_loopStartSample;
        ent.m_loopLengthSamples = m_loopLengthSamples;
        ent.m_adpcmParmOffset = 0;
    }
};

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
                                                     const unsigned char* sampData,
                                                     bool absOffs, N64DataTag)
{
    const unsigned char* cur = data;

    if (absOffs)
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            MusyX1AbsSdirEntry ent = *reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);
            ent.swapBig();

            std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
            ent.setIntoMusyX2(store.first);

            memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
            store.second.swapBigVADPCM();

            cur += 28;
        }
    }
    else
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            MusyX1SdirEntry ent = *reinterpret_cast<const MusyX1SdirEntry*>(cur);
            ent.swapBig();

            std::pair<Entry, ADPCMParms>& store = m_entries[ent.m_sfxId];
            ent.setIntoMusyX2(store.first);

            memcpy(&store.second.vadpcm.m_coefs, sampData + ent.m_sampleOff, 256);
            store.second.swapBigVADPCM();

            cur += 24;
        }
    }
}

AudioGroupSampleDirectory::AudioGroupSampleDirectory(const unsigned char* data,
                                                     bool absOffs, PCDataTag)
{
    const unsigned char* cur = data;

    if (absOffs)
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            const MusyX1AbsSdirEntry* ent = reinterpret_cast<const MusyX1AbsSdirEntry*>(cur);

            std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
            ent->setIntoMusyX2(store.first);

            cur += 28;
        }
    }
    else
    {
        while (*reinterpret_cast<const uint32_t*>(cur) != 0xffffffff)
        {
            const MusyX1SdirEntry* ent = reinterpret_cast<const MusyX1SdirEntry*>(cur);

            std::pair<Entry, ADPCMParms>& store = m_entries[ent->m_sfxId];
            ent->setIntoMusyX2(store.first);

            cur += 24;
        }
    }
}

}
<|endoftext|>