<commit_before>/***************************************************************************
 *   Copyright (C) 2003 by                                                 *
 *   Unai Garro (ugarro@users.sourceforge.net)                             *
 *   Cyril Bosselut (bosselut@b1project.com)                               *
 *   Jason Kivlighn (confederacy2@excite.com)                              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "selectrecipedialog.h"

#include <qsignalmapper.h>
#include <klocale.h>

#include "DBBackend/recipedb.h"
#include "recipe.h"
#include "selectunitdialog.h"
#include "createelementdialog.h"

SelectRecipeDialog::SelectRecipeDialog(QWidget *parent, RecipeDB* db)
 : QWidget(parent)
{
//Store pointer to Recipe Database
database=db;

//Initialize internal data
recipeList=new ElementList;
categoryList=new ElementList;
//Design dialog

layout = new QGridLayout( this, 1, 1, 0, 0);

	// Border Spacers
	QSpacerItem* spacer_left = new QSpacerItem( 10,10, QSizePolicy::Fixed, QSizePolicy::Minimum );	layout->addMultiCell( spacer_left, 1,4,0,0 );
	QSpacerItem* spacer_top = new QSpacerItem( 10,10, QSizePolicy::Minimum, QSizePolicy::Fixed );
	layout->addMultiCell(spacer_top,0,0,1,4);

	searchBar=new QHBox(this);
	layout->addWidget(searchBar,1,1);

	searchLabel=new QLabel(searchBar); searchLabel->setText(i18n("Search:")); searchLabel->setFixedWidth(searchLabel->fontMetrics().width(i18n("Search:"))+5);
	searchBox=new KLineEdit(searchBar);

	QSpacerItem* searchSpacer=new QSpacerItem(10,10,QSizePolicy::Fixed,QSizePolicy::Minimum); layout->addItem(searchSpacer,1,2);
	categoryBox=new KComboBox(this);
	layout->addWidget(categoryBox,1,3);

	QSpacerItem* spacerFromSearchBar = new QSpacerItem(10,10,QSizePolicy::Minimum, QSizePolicy::Fixed);
    	layout->addItem(spacerFromSearchBar,2,1);

	il=new KIconLoader;
	recipeListView=new KListView(this);
	recipeListView->addColumn(i18n("Category"));
    	recipeListView->addColumn(i18n("Id"));
    	recipeListView->addColumn(i18n("Title"));
    	recipeListView->setGeometry( QRect( 10, 65, 190, 280 ) );
	recipeListView->setRootIsDecorated(true); // Show "+" open icons
	layout->addMultiCellWidget(recipeListView,3,3,1,3);

	buttonBar=new QHBox(this);
 	layout->addMultiCellWidget(buttonBar,4,4,1,3);

	openButton=new QPushButton(buttonBar);
	openButton->setText(i18n("Open Recipe"));
  openButton->setDisabled(true);
	QPixmap pm=il->loadIcon("ok", KIcon::NoGroup,16); openButton->setIconSet(pm);
	editButton=new QPushButton(buttonBar);
	editButton->setText(i18n("Edit Recipe"));
  editButton->setDisabled(true);
	pm=il->loadIcon("edit", KIcon::NoGroup,16); editButton->setIconSet(pm);
	removeButton=new QPushButton(buttonBar);
	removeButton->setText(i18n("Delete"));
  removeButton->setDisabled(true);
	removeButton->setMaximumWidth(100);
	pm=il->loadIcon("editshred", KIcon::NoGroup,16); removeButton->setIconSet(pm);

// Popup menu
    kpop = new KPopupMenu( recipeListView );
    kpop->insertItem( il->loadIcon("ok", KIcon::NoGroup,16),tr2i18n("&Open"), this, SLOT(open()), CTRL+Key_L );
    kpop->insertItem( il->loadIcon("edit", KIcon::NoGroup,16),tr2i18n("&Edit"), this, SLOT(edit()), CTRL+Key_E );
    kpop->insertItem( il->loadIcon("filesaveas", KIcon::NoGroup,16),tr2i18n("&Save as"), this, SLOT(exportRecipe()), CTRL+Key_S );
    kpop->insertItem( il->loadIcon("editshred", KIcon::NoGroup,16),tr2i18n("&Remove"), this, SLOT(remove()), CTRL+Key_R );
    kpop->polish();

// Load Recipe List
loadRecipeList();
loadCategoryCombo();

// Initialize some internal variables
isFilteringCategories=false;

// Signals & Slots

connect(openButton,SIGNAL(clicked()),this, SLOT(open()));
connect(this,SIGNAL(recipeSelected(bool)),openButton, SLOT(setEnabled(bool)));
connect(editButton,SIGNAL(clicked()),this, SLOT(edit()));
connect(this,SIGNAL(recipeSelected(bool)),editButton, SLOT(setEnabled(bool)));
connect(removeButton,SIGNAL(clicked()),this, SLOT(remove()));
connect(this,SIGNAL(recipeSelected(bool)),removeButton, SLOT(setEnabled(bool)));
connect(searchBox,SIGNAL(returnPressed(const QString&)),this,SLOT(filter(const QString&)));
connect(searchBox,SIGNAL(textChanged(const QString&)),this,SLOT(filter(const QString&)));
connect(recipeListView,SIGNAL(selectionChanged()),this, SLOT(haveSelectedItems()));
connect(recipeListView,SIGNAL(doubleClicked( QListViewItem*,const QPoint &, int )),this, SLOT(open()));
connect(recipeListView,SIGNAL(contextMenu (KListView *, QListViewItem *, const QPoint &)),this, SLOT(showPopup(KListView *, QListViewItem *, const QPoint &)));
connect(categoryBox,SIGNAL(activated(int)),this,SLOT(filterComboCategory(int)));
}

SelectRecipeDialog::~SelectRecipeDialog()
{
}

void SelectRecipeDialog::loadRecipeList(void)
{
recipeListView->clear();
recipeList->clear();
categoryList->clear();

// First show the categories

ElementList categoryList;

database->loadCategories(&categoryList);

for ( Element *category=categoryList.getFirst(); category; category=categoryList.getNext())
	{
	QListViewItem *it=new QListViewItem(recipeListView,category->name,"","");
	categoryItems.insert(category->id,it);
	}

// Now show the recipes

int *categoryID;
Element *recipe;
QPtrList <int> recipeCategoryList;

database->loadRecipeList(recipeList,0,&recipeCategoryList); // Read the whole list of recipes including category

for ( recipe=recipeList->getFirst(),categoryID=recipeCategoryList.first();(recipe && categoryID);recipe=recipeList->getNext(),categoryID=recipeCategoryList.next())
	{
	if (QListViewItem* categoryItem=categoryItems[*categoryID])
	{
	QListViewItem *it=new QListViewItem (categoryItem,"",QString::number(recipe->id),recipe->name,"");
	}
	else
	{
	QListViewItem *it=new QListViewItem (recipeListView,"...",QString::number(recipe->id),recipe->name);
	}
	}

filter(searchBox->text());

}

void SelectRecipeDialog::open(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),0);
}
void SelectRecipeDialog::edit(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),1);
}
void SelectRecipeDialog::remove(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),2);
}

void SelectRecipeDialog::reload()
{
loadRecipeList();
loadCategoryCombo();
}

void SelectRecipeDialog::filter(const QString& s)
{
for (QListViewItem *it=recipeListView->firstChild();it;it=it->nextSibling())
	{
	if (!it->firstChild()) // It's not a category
	{
		if (s==QString::null) it->setVisible(true); // Don't filter if the filter text is empty
		else if (it->text(2).contains(s,false)) it->setVisible(true);

		else it->setVisible(false);
	}
	else // It's a category. Check the children
	{
		for (QListViewItem *cit=it->firstChild();cit;cit=cit->nextSibling())
		{
		if (s==QString::null) cit->setVisible(true); // Don't filter if the filter text is empty

		else if (cit->text(2).contains(s,false)) {
								cit->setVisible(true);
								if (!isFilteringCategories) it->setOpen(true);
								}

		else cit->setVisible(false);

		}
	}

	}
}

void SelectRecipeDialog::filterCategories(int categoryID)
{
for (QListViewItem *it=recipeListView->firstChild();it;it=it->nextSibling())
	{
	if (categoryID==-1) it->setVisible(true); // We're not filtering categories
	else if (it!=categoryItems[categoryID]) it->setVisible(false);
	else it->setVisible(true);
	}

}

void SelectRecipeDialog::loadCategoryCombo(void)
{

ElementList categoryList;
database->loadCategories(&categoryList);
int row=0;
categoryBox->clear();
categoryComboRows.clear();
for (Element *category=categoryList.getFirst();category;category=categoryList.getNext())
	{
	categoryBox->insertItem(category->name);
	categoryComboRows.insert(row,&category->id); // store category id's in the combobox position to obtain the category id later
	row++;
	}

}

/*!
    \fn SelectRecipeDialog::exportRecipe()
 */
void SelectRecipeDialog::exportRecipe()
{
  if((recipeListView->selectedItem())->text(1) != NULL){
    KFileDialog* fd = new KFileDialog((recipeListView->selectedItem())->text(2), "*.kre|Gzip Krecipes file (*.kre)\n*.kre|Krecipes xml file (*.kreml)", 0, "Save recipe", true);
    QString fileName = fd->getSaveFileName((recipeListView->selectedItem())->text(2), "*.kre|Gzip Krecipes file (*.kre)\n*.kre|Krecipes xml file (*.kreml)", 0, "Save recipe");
    if(fileName != NULL){
      KreExporter* kre = new KreExporter(database, (recipeListView->selectedItem())->text(1).toInt(), fileName, fd->currentFilter());
      kre->exporter();
    }
  }
}

void SelectRecipeDialog::haveSelectedItems(){
  if( recipeListView->selectedItem() != 0 && !(recipeListView->selectedItem())->firstChild() ){
    emit recipeSelected(true);
  }
  else{
    emit recipeSelected(false);
  }
}

void SelectRecipeDialog::getCurrentRecipe( Recipe *recipe )
{
	if (recipeListView->selectedItem())
	{
		if((recipeListView->selectedItem())->text(1) != NULL)
			database->loadRecipe( recipe, (recipeListView->selectedItem())->text(1).toInt() );
	}
}

void SelectRecipeDialog::showPopup( KListView *l, QListViewItem *i, const QPoint &p ){
  if(!i->firstChild()){
    kpop->exec(p);
  }
}

void SelectRecipeDialog::filterComboCategory(int row)
{
//First get the category ID corresponding to this combo row
int categoryID=*categoryComboRows[row];

//Now filter
filterCategories(categoryID); // if categoryID==-1 doesn't filter

// Indicate that we are filtering by category so that
// the rest of the trees are not opened while filtering recipes

if (categoryID>=0)
{
// Open the corresponding category tree
categoryItems[categoryID]->setOpen(true);
isFilteringCategories=true;
}
else isFilteringCategories=false;

}
<commit_msg>Add "All Categories" filter in the combo to show all categories back in the search. Thanks mortehu for the lesson on QIntDict... :)<commit_after>/***************************************************************************
 *   Copyright (C) 2003 by                                                 *
 *   Unai Garro (ugarro@users.sourceforge.net)                             *
 *   Cyril Bosselut (bosselut@b1project.com)                               *
 *   Jason Kivlighn (confederacy2@excite.com)                              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "selectrecipedialog.h"

#include <qsignalmapper.h>
#include <klocale.h>

#include "DBBackend/recipedb.h"
#include "recipe.h"
#include "selectunitdialog.h"
#include "createelementdialog.h"

SelectRecipeDialog::SelectRecipeDialog(QWidget *parent, RecipeDB* db)
 : QWidget(parent)
{
//Store pointer to Recipe Database
database=db;

//Initialize internal data
recipeList=new ElementList;
categoryList=new ElementList;
//Design dialog

layout = new QGridLayout( this, 1, 1, 0, 0);

	// Border Spacers
	QSpacerItem* spacer_left = new QSpacerItem( 10,10, QSizePolicy::Fixed, QSizePolicy::Minimum );	layout->addMultiCell( spacer_left, 1,4,0,0 );
	QSpacerItem* spacer_top = new QSpacerItem( 10,10, QSizePolicy::Minimum, QSizePolicy::Fixed );
	layout->addMultiCell(spacer_top,0,0,1,4);

	searchBar=new QHBox(this);
	layout->addWidget(searchBar,1,1);

	searchLabel=new QLabel(searchBar); searchLabel->setText(i18n("Search:")); searchLabel->setFixedWidth(searchLabel->fontMetrics().width(i18n("Search:"))+5);
	searchBox=new KLineEdit(searchBar);

	QSpacerItem* searchSpacer=new QSpacerItem(10,10,QSizePolicy::Fixed,QSizePolicy::Minimum); layout->addItem(searchSpacer,1,2);
	categoryBox=new KComboBox(this);
	layout->addWidget(categoryBox,1,3);

	QSpacerItem* spacerFromSearchBar = new QSpacerItem(10,10,QSizePolicy::Minimum, QSizePolicy::Fixed);
    	layout->addItem(spacerFromSearchBar,2,1);

	il=new KIconLoader;
	recipeListView=new KListView(this);
	recipeListView->addColumn(i18n("Category"));
    	recipeListView->addColumn(i18n("Id"));
    	recipeListView->addColumn(i18n("Title"));
    	recipeListView->setGeometry( QRect( 10, 65, 190, 280 ) );
	recipeListView->setRootIsDecorated(true); // Show "+" open icons
	layout->addMultiCellWidget(recipeListView,3,3,1,3);

	buttonBar=new QHBox(this);
 	layout->addMultiCellWidget(buttonBar,4,4,1,3);

	openButton=new QPushButton(buttonBar);
	openButton->setText(i18n("Open Recipe"));
  openButton->setDisabled(true);
	QPixmap pm=il->loadIcon("ok", KIcon::NoGroup,16); openButton->setIconSet(pm);
	editButton=new QPushButton(buttonBar);
	editButton->setText(i18n("Edit Recipe"));
  editButton->setDisabled(true);
	pm=il->loadIcon("edit", KIcon::NoGroup,16); editButton->setIconSet(pm);
	removeButton=new QPushButton(buttonBar);
	removeButton->setText(i18n("Delete"));
  removeButton->setDisabled(true);
	removeButton->setMaximumWidth(100);
	pm=il->loadIcon("editshred", KIcon::NoGroup,16); removeButton->setIconSet(pm);

// Popup menu
    kpop = new KPopupMenu( recipeListView );
    kpop->insertItem( il->loadIcon("ok", KIcon::NoGroup,16),tr2i18n("&Open"), this, SLOT(open()), CTRL+Key_L );
    kpop->insertItem( il->loadIcon("edit", KIcon::NoGroup,16),tr2i18n("&Edit"), this, SLOT(edit()), CTRL+Key_E );
    kpop->insertItem( il->loadIcon("filesaveas", KIcon::NoGroup,16),tr2i18n("&Save as"), this, SLOT(exportRecipe()), CTRL+Key_S );
    kpop->insertItem( il->loadIcon("editshred", KIcon::NoGroup,16),tr2i18n("&Remove"), this, SLOT(remove()), CTRL+Key_R );
    kpop->polish();

// Load Recipe List
loadRecipeList();
loadCategoryCombo();

// Initialize some internal variables
isFilteringCategories=false;

// Signals & Slots

connect(openButton,SIGNAL(clicked()),this, SLOT(open()));
connect(this,SIGNAL(recipeSelected(bool)),openButton, SLOT(setEnabled(bool)));
connect(editButton,SIGNAL(clicked()),this, SLOT(edit()));
connect(this,SIGNAL(recipeSelected(bool)),editButton, SLOT(setEnabled(bool)));
connect(removeButton,SIGNAL(clicked()),this, SLOT(remove()));
connect(this,SIGNAL(recipeSelected(bool)),removeButton, SLOT(setEnabled(bool)));
connect(searchBox,SIGNAL(returnPressed(const QString&)),this,SLOT(filter(const QString&)));
connect(searchBox,SIGNAL(textChanged(const QString&)),this,SLOT(filter(const QString&)));
connect(recipeListView,SIGNAL(selectionChanged()),this, SLOT(haveSelectedItems()));
connect(recipeListView,SIGNAL(doubleClicked( QListViewItem*,const QPoint &, int )),this, SLOT(open()));
connect(recipeListView,SIGNAL(contextMenu (KListView *, QListViewItem *, const QPoint &)),this, SLOT(showPopup(KListView *, QListViewItem *, const QPoint &)));
connect(categoryBox,SIGNAL(activated(int)),this,SLOT(filterComboCategory(int)));
}

SelectRecipeDialog::~SelectRecipeDialog()
{
}

void SelectRecipeDialog::loadRecipeList(void)
{
recipeListView->clear();
recipeList->clear();
categoryList->clear();

// First show the categories

ElementList categoryList;

database->loadCategories(&categoryList);

for ( Element *category=categoryList.getFirst(); category; category=categoryList.getNext())
	{
	QListViewItem *it=new QListViewItem(recipeListView,category->name,"","");
	categoryItems.insert(category->id,it);
	}

// Now show the recipes

int *categoryID;
Element *recipe;
QPtrList <int> recipeCategoryList;

database->loadRecipeList(recipeList,0,&recipeCategoryList); // Read the whole list of recipes including category

for ( recipe=recipeList->getFirst(),categoryID=recipeCategoryList.first();(recipe && categoryID);recipe=recipeList->getNext(),categoryID=recipeCategoryList.next())
	{
	if (QListViewItem* categoryItem=categoryItems[*categoryID])
	{
	QListViewItem *it=new QListViewItem (categoryItem,"",QString::number(recipe->id),recipe->name,"");
	}
	else
	{
	QListViewItem *it=new QListViewItem (recipeListView,"...",QString::number(recipe->id),recipe->name);
	}
	}

filter(searchBox->text());

}

void SelectRecipeDialog::open(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),0);
}
void SelectRecipeDialog::edit(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),1);
}
void SelectRecipeDialog::remove(void)
{
QListViewItem *it;
it=recipeListView->selectedItem();
if ( it != 0 && !it->firstChild() ) emit recipeSelected(it->text(1).toInt(),2);
}

void SelectRecipeDialog::reload()
{
loadRecipeList();
loadCategoryCombo();
}

void SelectRecipeDialog::filter(const QString& s)
{
for (QListViewItem *it=recipeListView->firstChild();it;it=it->nextSibling())
	{
	if (!it->firstChild()) // It's not a category
	{
		if (s==QString::null) it->setVisible(true); // Don't filter if the filter text is empty
		else if (it->text(2).contains(s,false)) it->setVisible(true);

		else it->setVisible(false);
	}
	else // It's a category. Check the children
	{
		for (QListViewItem *cit=it->firstChild();cit;cit=cit->nextSibling())
		{
		if (s==QString::null) cit->setVisible(true); // Don't filter if the filter text is empty

		else if (cit->text(2).contains(s,false)) {
								cit->setVisible(true);
								if (!isFilteringCategories) it->setOpen(true);
								}

		else cit->setVisible(false);

		}
	}

	}
}

void SelectRecipeDialog::filterCategories(int categoryID)
{
std::cerr<<"I got category :"<<categoryID<<"\n";
for (QListViewItem *it=recipeListView->firstChild();it;it=it->nextSibling())
	{
	if (categoryID==-1) it->setVisible(true); // We're not filtering categories
	else if (it!=categoryItems[categoryID]) it->setVisible(false);
	else it->setVisible(true);
	}

}

void SelectRecipeDialog::loadCategoryCombo(void)
{

ElementList categoryList;
database->loadCategories(&categoryList);

categoryBox->clear();
categoryComboRows.clear();

// Insert default "All Categories" (row 0, which will be translated to -1 as category in the filtering process)
categoryBox->insertItem(i18n("All Categories"));

//Now load the categories
int row=1;
for (Element *category=categoryList.getFirst();category;category=categoryList.getNext())
	{
	categoryBox->insertItem(category->name);
	categoryComboRows.insert(row,&category->id); // store category id's in the combobox position to obtain the category id later
	row++;
	}

}

/*!
    \fn SelectRecipeDialog::exportRecipe()
 */
void SelectRecipeDialog::exportRecipe()
{
  if((recipeListView->selectedItem())->text(1) != NULL){
    KFileDialog* fd = new KFileDialog((recipeListView->selectedItem())->text(2), "*.kre|Gzip Krecipes file (*.kre)\n*.kre|Krecipes xml file (*.kreml)", 0, "Save recipe", true);
    QString fileName = fd->getSaveFileName((recipeListView->selectedItem())->text(2), "*.kre|Gzip Krecipes file (*.kre)\n*.kre|Krecipes xml file (*.kreml)", 0, "Save recipe");
    if(fileName != NULL){
      KreExporter* kre = new KreExporter(database, (recipeListView->selectedItem())->text(1).toInt(), fileName, fd->currentFilter());
      kre->exporter();
    }
  }
}

void SelectRecipeDialog::haveSelectedItems(){
  if( recipeListView->selectedItem() != 0 && !(recipeListView->selectedItem())->firstChild() ){
    emit recipeSelected(true);
  }
  else{
    emit recipeSelected(false);
  }
}

void SelectRecipeDialog::getCurrentRecipe( Recipe *recipe )
{
	if (recipeListView->selectedItem())
	{
		if((recipeListView->selectedItem())->text(1) != NULL)
			database->loadRecipe( recipe, (recipeListView->selectedItem())->text(1).toInt() );
	}
}

void SelectRecipeDialog::showPopup( KListView *l, QListViewItem *i, const QPoint &p ){
  if(!i->firstChild()){
    kpop->exec(p);
  }
}

void SelectRecipeDialog::filterComboCategory(int row)
{
std::cerr<<"I got row "<<row<<"\n";

//First get the category ID corresponding to this combo row
int categoryID;
if (row) categoryID=*(categoryComboRows[row]);
else categoryID=-1; // No category filtering

//Now filter

filterCategories(categoryID); // if categoryID==-1 doesn't filter

// Indicate that we are filtering by category so that
// the rest of the trees are not opened while filtering recipes
if (row>=1)
{
// Open the corresponding category tree
categoryItems[categoryID]->setOpen(true);
isFilteringCategories=true;
}
else isFilteringCategories=false;

}
<|endoftext|>


<commit_before><commit_msg>allegro screen format is not interesting anymore (because the format is fixed)<commit_after><|endoftext|>


<commit_before>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "heuristic_greedy.hh"
#include "alg_bdfs.hh"
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>

Heuristic_greedy::Heuristic_greedy(Log& l, std::string params) :
  Heuristic(l), m_search_depth(0), m_burst(false)
{
  m_search_depth = atoi(params.c_str());
  if (strchr(params.c_str(), 'b')) {
    m_burst = true;
  }
}

bool Heuristic_greedy::execute(int action)
{
  if (m_path.size() > 0) {
    int planned_action = m_path.back();
    if (planned_action != action) // invalidate planned path
      m_path.resize(0);
    else
      m_path.pop_back();
  }
  return Heuristic::execute(action);
}

float Heuristic_greedy::getCoverage() {
  if (my_coverage==NULL) {
    return 0.0;
  }
  return my_coverage->getCoverage();
}

int Heuristic_greedy::getAction()
{
  int* actions;
  int i = model->getActions(&actions);

  if (i==0) {
    return DEADLOCK;
  }

  float* f=new float[i];
  int pos=my_coverage->fitness(actions,i,f);
  float score = f[pos];
  delete [] f;

  if (score > 0.0) {
    log.debug("Greedy selected %i (out of %i)\n",
              pos,i);
    return actions[pos];
  }

  /* Fall back to random selection */
  pos=(((float)random())/RAND_MAX)*i;
  return actions[pos];
}

int Heuristic_greedy::getIAction()
{
  int* actions;
  int i = model->getIActions(&actions);
  int pos = -1;

  if (i==0) {
    // No input actions. See if there are output actions available.
    i=model->getActions(&actions);
    if (i==0) {
      return DEADLOCK;
    }
    return OUTPUT_ONLY;
  }

  if (m_search_depth < 1) {
    /* Do a very fast lookup */
    float* f=new float[i];
    pos=my_coverage->fitness(actions,i,f);
    float score = f[pos];
    delete [] f;

    if (score > 0.0) {
      log.debug("Greedy selected %i (out of %i)\n",
                pos,i);
      return actions[pos];
    }
  } else {
    /* In burst mode new path is not searched before previosly found
     * path is fully consumed */
    if (!m_burst || m_path.size() == 0) {
      /* Spend more time for better coverage */
      AlgPathToBestCoverage alg(m_search_depth);
      /* Use precalculated path (m_path) as a hint. */
      std::reverse(m_path.begin(), m_path.end());
      double score = alg.search(*model, *my_coverage, m_path);
      if (m_path.size() > 0) {
        std::reverse(m_path.begin(), m_path.end());
        log.debug("score: %f, path length: %d", score, m_path.size());
      }
    }
    if (m_path.size() > 0) {
      return m_path.back();
    }
  }

  /* Fall back to random selection. Input actions table might not be
   * valid anymore (execute might have happened), ask it again. */
  i = model->getIActions(&actions);
  pos=(((float)random())/RAND_MAX)*i;
  return actions[pos];
}

FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "greedy")

namespace {
  Heuristic* creator_func2(Log& log, std::string params = "")
  {
    return new Heuristic_greedy(log, params);
  }
  static HeuristicFactory::Register me2("lookahead", creator_func2);
}

namespace {
  Heuristic* creator_func3(Log& log, std::string params = "")
  {
    std::string p("");
    return new Heuristic_greedy(log, p);
  }
  static HeuristicFactory::Register me3("action_fitness", creator_func3);
}
<commit_msg>Print error msg and exit from heuristic greedy, when model and greedy view of the model is out of sync<commit_after>/*
 * fMBT, free Model Based Testing tool
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU Lesser General Public License,
 * version 2.1, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "heuristic_greedy.hh"
#include "alg_bdfs.hh"
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <algorithm>

Heuristic_greedy::Heuristic_greedy(Log& l, std::string params) :
  Heuristic(l), m_search_depth(0), m_burst(false)
{
  m_search_depth = atoi(params.c_str());
  if (strchr(params.c_str(), 'b')) {
    m_burst = true;
  }
}

bool Heuristic_greedy::execute(int action)
{
  if (m_path.size() > 0) {
    int planned_action = m_path.back();
    if (planned_action != action) // invalidate planned path
      m_path.resize(0);
    else
      m_path.pop_back();
  }
  return Heuristic::execute(action);
}

float Heuristic_greedy::getCoverage() {
  if (my_coverage==NULL) {
    return 0.0;
  }
  return my_coverage->getCoverage();
}

int Heuristic_greedy::getAction()
{
  int* actions;
  int i = model->getActions(&actions);

  if (i==0) {
    return DEADLOCK;
  }

  float* f=new float[i];
  int pos=my_coverage->fitness(actions,i,f);
  float score = f[pos];
  delete [] f;

  if (score > 0.0) {
    log.debug("Greedy selected %i (out of %i)\n",
              pos,i);
    return actions[pos];
  }

  /* Fall back to random selection */
  pos=(((float)random())/RAND_MAX)*i;
  return actions[pos];
}

int Heuristic_greedy::getIAction()
{
  int* actions;
  int i = model->getIActions(&actions);
  int pos = -1;

  log.debug("greedy getIACtion %i",i);

  for(int u=0;u<i;u++) {
    log.debug("iaction %i %i",u,actions[u]);
  }

  if (i==0) {
    // No input actions. See if there are output actions available.
    i=model->getActions(&actions);
    if (i==0) {
      return DEADLOCK;
    }
    return OUTPUT_ONLY;
  }

  if (m_search_depth < 1) {
    /* Do a very fast lookup */
    float* f=new float[i];
    pos=my_coverage->fitness(actions,i,f);
    float score = f[pos];
    delete [] f;

    if (score > 0.0) {
      log.debug("Greedy selected %i (out of %i)\n",
                pos,i);
      return actions[pos];
    }
  } else {
    /* In burst mode new path is not searched before previosly found
     * path is fully consumed */
    if (!m_burst || m_path.size() == 0) {
      /* Spend more time for better coverage */
      AlgPathToBestCoverage alg(m_search_depth);
      /* Use precalculated path (m_path) as a hint. */
      std::reverse(m_path.begin(), m_path.end());
      double score = alg.search(*model, *my_coverage, m_path);
      if (m_path.size() > 0) {
        std::reverse(m_path.begin(), m_path.end());
        log.debug("score: %f, path length: %d", score, m_path.size());
      }
    }
    if (m_path.size() > 0) {
      log.debug("path %i",m_path.back());
      i = model->getIActions(&actions);
      bool broken=true;
      int ret=m_path.back();
      for(int j=0;j<i;j++) {
	if (actions[j]=ret) {
	  broken=false;
	}
      }
      if (broken) {
	log.print("<ERROR msg=\"%s %i\"/>","trying to return action %i, which is not executable in the model");
	abort();
      }
      return m_path.back();
    }
  }

  /* Fall back to random selection. Input actions table might not be
   * valid anymore (execute might have happened), ask it again. */
  i = model->getIActions(&actions);
  pos=(((float)random())/RAND_MAX)*i;

  return actions[pos];
}

FACTORY_DEFAULT_CREATOR(Heuristic, Heuristic_greedy, "greedy")

namespace {
  Heuristic* creator_func2(Log& log, std::string params = "")
  {
    return new Heuristic_greedy(log, params);
  }
  static HeuristicFactory::Register me2("lookahead", creator_func2);
}

namespace {
  Heuristic* creator_func3(Log& log, std::string params = "")
  {
    std::string p("");
    return new Heuristic_greedy(log, p);
  }
  static HeuristicFactory::Register me3("action_fitness", creator_func3);
}
<|endoftext|>


<commit_before>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrSoftwarePathRenderer.h"
#include "GrPaint.h"
#include "SkPaint.h"
#include "GrRenderTarget.h"
#include "GrContext.h"
#include "SkDraw.h"
#include "SkRasterClip.h"

////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
                                         GrPathFill fill,
                                         const GrDrawTarget* target,
                                         bool antiAlias) const {
    if (!antiAlias || NULL == fContext) {
        // TODO: We could allow the SW path to also handle non-AA paths but
        // this would mean that GrDefaultPathRenderer would never be called
        // (since it appears after the SW renderer in the path renderer
        // chain). Some testing would need to be done r.e. performance
        // and consistency of the resulting images before removing
        // the "!antiAlias" clause from the above test
        return false;
    }

    return true;
}

namespace {

////////////////////////////////////////////////////////////////////////////////
SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
    switch (fill) {
        case kWinding_PathFill:
            return SkPath::kWinding_FillType;
        case kEvenOdd_PathFill:
            return SkPath::kEvenOdd_FillType;
        case kInverseWinding_PathFill:
            return SkPath::kInverseWinding_FillType;
        case kInverseEvenOdd_PathFill:
            return SkPath::kInverseEvenOdd_FillType;
        default:
            GrCrash("Unexpected fill.");
            return SkPath::kWinding_FillType;
    }
}

////////////////////////////////////////////////////////////////////////////////
// gets device coord bounds of path (not considering the fill) and clip. The
// path bounds will be a subset of the clip bounds. returns false if
// path bounds would be empty.
bool get_path_and_clip_bounds(const GrDrawTarget* target,
                              const SkPath& path,
                              const GrVec* translate,
                              GrIRect* pathBounds,
                              GrIRect* clipBounds) {
    // compute bounds as intersection of rt size, clip, and path
    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
    if (NULL == rt) {
        return false;
    }
    *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
    const GrClip& clip = target->getClip();
    if (clip.hasConservativeBounds()) {
        clip.getConservativeBounds().roundOut(clipBounds);
        if (!pathBounds->intersect(*clipBounds)) {
            return false;
        }
    } else {
        // pathBounds is currently the rt extent, set clip bounds to that rect.
        *clipBounds = *pathBounds;
    }
    GrRect pathSBounds = path.getBounds();
    if (!pathSBounds.isEmpty()) {
        if (NULL != translate) {
            pathSBounds.offset(*translate);
        }
        target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
                                                        pathSBounds);
        GrIRect pathIBounds;
        pathSBounds.roundOut(&pathIBounds);
        if (!pathBounds->intersect(pathIBounds)) {
            return false;
        }
    } else {
        return false;
    }
    return true;
}

////////////////////////////////////////////////////////////////////////////////
/**
 * sw rasterizes path to A8 mask using the context's matrix and uploads to a
 * scratch texture.
 */

bool sw_draw_path_to_mask_texture(const SkPath& clientPath,
                                  const GrIRect& pathDevBounds,
                                  GrPathFill fill,
                                  GrContext* context,
                                  const GrPoint* translate,
                                  GrAutoScratchTexture* tex,
                                  bool antiAlias) {
    SkPaint paint;
    SkPath tmpPath;
    const SkPath* pathToDraw = &clientPath;
    if (kHairLine_PathFill == fill) {
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(SK_Scalar1);
    } else {
        paint.setStyle(SkPaint::kFill_Style);
        SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
        if (skfill != pathToDraw->getFillType()) {
            tmpPath = *pathToDraw;
            tmpPath.setFillType(skfill);
            pathToDraw = &tmpPath;
        }
    }
    paint.setAntiAlias(antiAlias);
    paint.setColor(SK_ColorWHITE);

    GrMatrix matrix = context->getMatrix();
    if (NULL != translate) {
        matrix.postTranslate(translate->fX, translate->fY);
    }

    matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
                         -pathDevBounds.fTop * SK_Scalar1);
    GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
                                     pathDevBounds.height());

    SkBitmap bm;
    bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
    if (!bm.allocPixels()) {
        return false;
    }
    sk_bzero(bm.getPixels(), bm.getSafeSize());

    SkDraw  draw;
    sk_bzero(&draw, sizeof(draw));
    SkRasterClip rc(bounds);
    draw.fRC    = &rc;
    draw.fClip  = &rc.bwRgn();
    draw.fMatrix = &matrix;
    draw.fBitmap = &bm;
    draw.drawPath(*pathToDraw, paint);

    const GrTextureDesc desc = {
        kNone_GrTextureFlags,
        bounds.fRight,
        bounds.fBottom,
        kAlpha_8_GrPixelConfig,
        0 // samples
    };

    tex->set(context, desc);
    GrTexture* texture = tex->texture();

    if (NULL == texture) {
        return false;
    }
    SkAutoLockPixels alp(bm);
    texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                         bm.getPixels(), bm.rowBytes());
    return true;
}

////////////////////////////////////////////////////////////////////////////////
void draw_around_inv_path(GrDrawTarget* target,
                          GrDrawState::StageMask stageMask,
                          const GrIRect& clipBounds,
                          const GrIRect& pathBounds) {
    GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
    GrRect rect;
    if (clipBounds.fTop < pathBounds.fTop) {
        rect.iset(clipBounds.fLeft, clipBounds.fTop,
                    clipBounds.fRight, pathBounds.fTop);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fLeft < pathBounds.fLeft) {
        rect.iset(clipBounds.fLeft, pathBounds.fTop,
                    pathBounds.fLeft, pathBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fRight > pathBounds.fRight) {
        rect.iset(pathBounds.fRight, pathBounds.fTop,
                    clipBounds.fRight, pathBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fBottom > pathBounds.fBottom) {
        rect.iset(clipBounds.fLeft, pathBounds.fBottom,
                    clipBounds.fRight, clipBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
}

}

////////////////////////////////////////////////////////////////////////////////
// return true on success; false on failure
bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
                                        GrPathFill fill,
                                        const GrVec* translate,
                                        GrDrawTarget* target,
                                        GrDrawState::StageMask stageMask,
                                        bool antiAlias) {

    if (NULL == fContext) {
        return false;
    }

    GrAutoScratchTexture ast;
    GrIRect pathBounds, clipBounds;
    if (!get_path_and_clip_bounds(target, path, translate,
                                  &pathBounds, &clipBounds)) {
        return true;    // path is empty so there is nothing to do
    }
    if (sw_draw_path_to_mask_texture(path, pathBounds,
                                     fill, fContext,
                                     translate, &ast, antiAlias)) {
        GrTexture* texture = ast.texture();
        GrAssert(NULL != texture);
        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
        enum {
            // the SW path renderer shares this stage with glyph
            // rendering (kGlyphMaskStage in GrBatchedTextContext)
            kPathMaskStage = GrPaint::kTotalStages,
        };
        GrAssert(NULL == target->drawState()->getTexture(kPathMaskStage));
        target->drawState()->setTexture(kPathMaskStage, texture);
        target->drawState()->sampler(kPathMaskStage)->reset();
        GrScalar w = GrIntToScalar(pathBounds.width());
        GrScalar h = GrIntToScalar(pathBounds.height());
        GrRect maskRect = GrRect::MakeWH(w / texture->width(),
                                         h / texture->height());
        const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
        srcRects[kPathMaskStage] = &maskRect;
        stageMask |= 1 << kPathMaskStage;
        GrRect dstRect = GrRect::MakeLTRB(
                              SK_Scalar1* pathBounds.fLeft,
                              SK_Scalar1* pathBounds.fTop,
                              SK_Scalar1* pathBounds.fRight,
                              SK_Scalar1* pathBounds.fBottom);
        target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
        target->drawState()->setTexture(kPathMaskStage, NULL);
        if (GrIsFillInverted(fill)) {
            draw_around_inv_path(target, stageMask,
                                 clipBounds, pathBounds);
        }
        return true;
    }

    return false;
}

<commit_msg>Created SW clip mask creation helper class (in GrSoftwarePathRenderer)<commit_after>
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrSoftwarePathRenderer.h"
#include "GrPaint.h"
#include "SkPaint.h"
#include "GrRenderTarget.h"
#include "GrContext.h"
#include "SkDraw.h"
#include "SkRasterClip.h"

////////////////////////////////////////////////////////////////////////////////
bool GrSoftwarePathRenderer::canDrawPath(const SkPath& path,
                                         GrPathFill fill,
                                         const GrDrawTarget* target,
                                         bool antiAlias) const {
    if (!antiAlias || NULL == fContext) {
        // TODO: We could allow the SW path to also handle non-AA paths but
        // this would mean that GrDefaultPathRenderer would never be called
        // (since it appears after the SW renderer in the path renderer
        // chain). Some testing would need to be done r.e. performance
        // and consistency of the resulting images before removing
        // the "!antiAlias" clause from the above test
        return false;
    }

    return true;
}

namespace {

////////////////////////////////////////////////////////////////////////////////
SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
    switch (fill) {
        case kWinding_PathFill:
            return SkPath::kWinding_FillType;
        case kEvenOdd_PathFill:
            return SkPath::kEvenOdd_FillType;
        case kInverseWinding_PathFill:
            return SkPath::kInverseWinding_FillType;
        case kInverseEvenOdd_PathFill:
            return SkPath::kInverseEvenOdd_FillType;
        default:
            GrCrash("Unexpected fill.");
            return SkPath::kWinding_FillType;
    }
}

////////////////////////////////////////////////////////////////////////////////
// gets device coord bounds of path (not considering the fill) and clip. The
// path bounds will be a subset of the clip bounds. returns false if
// path bounds would be empty.
bool get_path_and_clip_bounds(const GrDrawTarget* target,
                              const SkPath& path,
                              const GrVec* translate,
                              GrIRect* pathBounds,
                              GrIRect* clipBounds) {
    // compute bounds as intersection of rt size, clip, and path
    const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
    if (NULL == rt) {
        return false;
    }
    *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
    const GrClip& clip = target->getClip();
    if (clip.hasConservativeBounds()) {
        clip.getConservativeBounds().roundOut(clipBounds);
        if (!pathBounds->intersect(*clipBounds)) {
            return false;
        }
    } else {
        // pathBounds is currently the rt extent, set clip bounds to that rect.
        *clipBounds = *pathBounds;
    }
    GrRect pathSBounds = path.getBounds();
    if (!pathSBounds.isEmpty()) {
        if (NULL != translate) {
            pathSBounds.offset(*translate);
        }
        target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
                                                        pathSBounds);
        GrIRect pathIBounds;
        pathSBounds.roundOut(&pathIBounds);
        if (!pathBounds->intersect(pathIBounds)) {
            return false;
        }
    } else {
        return false;
    }
    return true;
}

/**
 * The GrSWMaskHelper helps generate clip masks using the software rendering
 * path.
 */
class GrSWMaskHelper : public GrNoncopyable {
public:
    GrSWMaskHelper(GrContext* context)
    : fContext(context) {

    }

    /**
     * Draw a single element of the clip stack into the accumulation bitmap
     */
    void draw(const SkPath& clientPath, GrPathFill fill, bool antiAlias) {
        SkPaint paint;
        SkPath tmpPath;
        const SkPath* pathToDraw = &clientPath;
        if (kHairLine_PathFill == fill) {
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setStrokeWidth(SK_Scalar1);
        } else {
            paint.setStyle(SkPaint::kFill_Style);
            SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
            if (skfill != pathToDraw->getFillType()) {
                tmpPath = *pathToDraw;
                tmpPath.setFillType(skfill);
                pathToDraw = &tmpPath;
            }
        }
        paint.setAntiAlias(antiAlias);
        paint.setColor(SK_ColorWHITE);

        fDraw.drawPath(*pathToDraw, paint);
    }

    bool init(const GrIRect& pathDevBounds, const GrPoint* translate) {
        fMatrix = fContext->getMatrix();
        if (NULL != translate) {
            fMatrix.postTranslate(translate->fX, translate->fY);
        }

        fMatrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
                              -pathDevBounds.fTop * SK_Scalar1);
        GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
                                         pathDevBounds.height());

        fBM.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
        if (!fBM.allocPixels()) {
            return false;
        }
        sk_bzero(fBM.getPixels(), fBM.getSafeSize());

        sk_bzero(&fDraw, sizeof(fDraw));
        fRasterClip.setRect(bounds);
        fDraw.fRC    = &fRasterClip;
        fDraw.fClip  = &fRasterClip.bwRgn();
        fDraw.fMatrix = &fMatrix;
        fDraw.fBitmap = &fBM;
        return true;
    }

    /**
     * Move the result of the software mask generation back to the gpu
     */
    bool toTexture(GrAutoScratchTexture* tex) {
        const GrTextureDesc desc = {
            kNone_GrTextureFlags,
            fBM.width(),
            fBM.height(),
            kAlpha_8_GrPixelConfig,
            0 // samples
        };

        tex->set(fContext, desc);
        GrTexture* texture = tex->texture();

        if (NULL == texture) {
            return false;
        }
        SkAutoLockPixels alp(fBM);
        texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
                             fBM.getPixels(), fBM.rowBytes());
        return true;
    }

protected:
private:
    GrContext*      fContext;
    GrMatrix        fMatrix;
    SkBitmap        fBM;
    SkDraw          fDraw;
    SkRasterClip    fRasterClip;

    typedef GrPathRenderer INHERITED;
};

////////////////////////////////////////////////////////////////////////////////
/**
 * sw rasterizes path to A8 mask using the context's matrix and uploads to a
 * scratch texture.
 */
bool sw_draw_path_to_mask_texture(const SkPath& clientPath,
                                  const GrIRect& pathDevBounds,
                                  GrPathFill fill,
                                  GrContext* context,
                                  const GrPoint* translate,
                                  GrAutoScratchTexture* tex,
                                  bool antiAlias) {
    GrSWMaskHelper helper(context);

    if (!helper.init(pathDevBounds, translate)) {
        return false;
    }

    helper.draw(clientPath, fill, antiAlias);

    if (!helper.toTexture(tex)) {
        return false;
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////////
void draw_around_inv_path(GrDrawTarget* target,
                          GrDrawState::StageMask stageMask,
                          const GrIRect& clipBounds,
                          const GrIRect& pathBounds) {
    GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
    GrRect rect;
    if (clipBounds.fTop < pathBounds.fTop) {
        rect.iset(clipBounds.fLeft, clipBounds.fTop,
                    clipBounds.fRight, pathBounds.fTop);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fLeft < pathBounds.fLeft) {
        rect.iset(clipBounds.fLeft, pathBounds.fTop,
                    pathBounds.fLeft, pathBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fRight > pathBounds.fRight) {
        rect.iset(pathBounds.fRight, pathBounds.fTop,
                    clipBounds.fRight, pathBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
    if (clipBounds.fBottom > pathBounds.fBottom) {
        rect.iset(clipBounds.fLeft, pathBounds.fBottom,
                    clipBounds.fRight, clipBounds.fBottom);
        target->drawSimpleRect(rect, NULL, stageMask);
    }
}

}

////////////////////////////////////////////////////////////////////////////////
// return true on success; false on failure
bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
                                        GrPathFill fill,
                                        const GrVec* translate,
                                        GrDrawTarget* target,
                                        GrDrawState::StageMask stageMask,
                                        bool antiAlias) {

    if (NULL == fContext) {
        return false;
    }

    GrAutoScratchTexture ast;
    GrIRect pathBounds, clipBounds;
    if (!get_path_and_clip_bounds(target, path, translate,
                                  &pathBounds, &clipBounds)) {
        return true;    // path is empty so there is nothing to do
    }
    if (sw_draw_path_to_mask_texture(path, pathBounds,
                                     fill, fContext,
                                     translate, &ast, antiAlias)) {
        GrTexture* texture = ast.texture();
        GrAssert(NULL != texture);
        GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
        enum {
            // the SW path renderer shares this stage with glyph
            // rendering (kGlyphMaskStage in GrBatchedTextContext)
            kPathMaskStage = GrPaint::kTotalStages,
        };
        GrAssert(NULL == target->drawState()->getTexture(kPathMaskStage));
        target->drawState()->setTexture(kPathMaskStage, texture);
        target->drawState()->sampler(kPathMaskStage)->reset();
        GrScalar w = GrIntToScalar(pathBounds.width());
        GrScalar h = GrIntToScalar(pathBounds.height());
        GrRect maskRect = GrRect::MakeWH(w / texture->width(),
                                         h / texture->height());
        const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
        srcRects[kPathMaskStage] = &maskRect;
        stageMask |= 1 << kPathMaskStage;
        GrRect dstRect = GrRect::MakeLTRB(
                              SK_Scalar1* pathBounds.fLeft,
                              SK_Scalar1* pathBounds.fTop,
                              SK_Scalar1* pathBounds.fRight,
                              SK_Scalar1* pathBounds.fBottom);
        target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
        target->drawState()->setTexture(kPathMaskStage, NULL);
        if (GrIsFillInverted(fill)) {
            draw_around_inv_path(target, stageMask,
                                 clipBounds, pathBounds);
        }
        return true;
    }

    return false;
}

<|endoftext|>


<commit_before>/** @file gsBoundaryConditions.hpp

    @brief Implementation file for the gsBoundaryConditions class.

    This file is part of the G+Smo library.

    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/.

    Author(s): A. Mantzaflaris
*/

#include <gsIO/gsXml.h>
#include <gsCore/gsFunctionExpr.h>
#include <gsUtils/gsSortedVector.h>

namespace gismo
{

namespace internal
{

/// @brief I/O for boundary conditions from file
template<class T>
class gsXml< gsBoundaryConditions<T> >
{
private:
    gsXml() { }
    typedef gsBoundaryConditions<T> Object;
public:
    GSXML_COMMON_FUNCTIONS(Object);
    static std::string tag  () { return "boundaryConditions"; }
    static std::string type () { return ""; }

    GSXML_GET_POINTER(Object);

    static void get_into(gsXmlNode * node, Object & result)
    {
        GISMO_ASSERT(!strcmp(node->name(), tag().c_str()),
                "Something went wrong. Expected tag "<< tag());

        //gsXmlNode * tmp = node->first_node("patches");
        //GISMO_ASSERT(tmp, "No pathes tag");
//
//        std::istringstream str;
//        str.str( tmp->value() );
//        // Resolve ID numbers
//        std::map<int,int> ids;
//        if ( ! strcmp( tmp->first_attribute("type")->value(), "id_range") )
//        {
//            int first, last;
//            gsGetInt(str, first);
//            gsGetInt(str, last);
//            for ( int i = first; i<=last; ++i )
//                ids[i] = i - first;
//        }
//        else if ( ! strcmp( tmp->first_attribute("type")->value(),"id_index") )
//        {
//            int c = 0;
//            for (int pindex; gsGetInt(str, pindex);)
//                ids[pindex] = c++;
//        }
//        else
//        {
//            gsWarn<<"Incomplete tag \"patch\" in boundaryConditions.\n";
//        }
        std::istringstream str;
        std::map<int, int> ids;

        // Read function inventory
        int count = countByTag("Function", node);
        std::vector<typename gsFunctionExpr<T>::Ptr> func(count); // todo: gsFunction::Ptr
        for (gsXmlNode * child = node->first_node("Function"); child; child =
                child->next_sibling("Function"))
        {
            const int i = atoi(child->first_attribute("index")->value());
            func[i] = memory::make_shared(new gsFunctionExpr<T>);
            getFunctionFromXml(child, *func[i]);
        }

        // Read boundary conditions
        std::vector<patchSide> boundaries;
        for (gsXmlNode * child = node->first_node("bc"); child;
                child = child->next_sibling("bc"))
        {
            const int uIndex = atoi(child->first_attribute("unknown")->value());
            const int fIndex = atoi(
                    child->first_attribute("function")->value());

            const gsXmlAttribute * comp = child->first_attribute("component");
            int cIndex = -1;
            if (NULL != comp)
                cIndex = atoi( child->first_attribute("component")->value() );

            getBoundaries(child, ids, boundaries);

            const gsXmlAttribute * bcat = child->first_attribute("type");
            GISMO_ASSERT(NULL != bcat, "No type provided");
            const char * bctype = bcat->value();
            for (std::vector<patchSide>::const_iterator it = boundaries.begin();
                    it != boundaries.end(); ++it)
                result.add(it->patch, it->side(), bctype, func[fIndex], uIndex,cIndex,
                        false);        //parametric
        }

        T val(0);
        for (gsXmlNode * child = node->first_node("cv"); child;
                child = child->next_sibling("cv"))
        {
            str.clear();
            str.str(child->value());
            GISMO_ENSURE(gsGetReal(str, val), "No value");
            const int uIndex = atoi(child->first_attribute("unknown")->value());
            const int cIndex = atoi(child->first_attribute("corner")->value());
            int pIndex = atoi(child->first_attribute("patch")->value());
            pIndex = ids[pIndex];

            result.addCornerValue(cIndex, val, pIndex, uIndex);
        }
    }

    static gsXmlNode * put(const Object & obj, gsXmlTree & data)
    {
        // Check if the last node is a multipatch
        //gsXmlNode * mp = data.getRoot()->last_node("MultiPatch");

        gsXmlNode * BCs = internal::makeNode("boundaryConditions", data);
        //data.appendToRoot(BCs);
        gsXmlAttribute * multi = internal::makeAttribute("multipatch", "0",
                data);

        BCs->append_attribute(multi);

        // inventory of functions
        typedef typename gsBoundaryConditions<T>::const_bciterator bctype_it;
        typedef typename Object::const_iterator bc_it;

        std::vector<typename gsFunction<T>::Ptr> fun;
        //gsSortedVector<typename gsFunction<T>::Ptr> fun;
        typedef typename std::vector<const boundary_condition<T>*> bctype_vec;
        typedef typename std::map<int, bctype_vec> bctype_map;
        std::map<std::string, bctype_map> fi;

        for (bctype_it it = obj.beginAll(); it != obj.endAll(); ++it)
        {
            std::string label = it->first;
            bctype_map map;
            for (bc_it bc = it->second.begin(); bc != it->second.end(); ++bc)
            {
                typename gsFunction<T>::Ptr ptr = bc->function();
                bool contains = std::find(fun.begin(), fun.end(), ptr)
                        != fun.end();
                if (!contains)
                {
                    fun.push_back(ptr);
                }
                int index = std::find(fun.begin(), fun.end(), ptr)
                        - fun.begin();
//                fun.push_sorted_unique(ptr);
//                int index = fun.getIndex(ptr);
                std::vector<const boundary_condition<T>*> vec = map[index];
                const boundary_condition<T>* b = &(*bc);
                vec.push_back(b);
                map[index] = vec;
            }
            std::pair<std::string, bctype_map> pair(label, map);
            fi.insert(pair);
        }

        int count = 0;
        typedef typename std::vector<typename gsFunction<T>::Ptr>::const_iterator fun_it;
        for (fun_it fit = fun.begin(); fit != fun.end(); ++fit)
        {
            gsXmlNode * ff = putFunctionFromXml(*fit, data, count);
            BCs->append_node(ff);
            ++count;
        }

        // for all bcs, append bc, cv
        typedef typename std::map<std::string, bctype_map>::const_iterator bctype_map_it;
        typedef typename std::map<int, bctype_vec>::const_iterator bctype_iv_it;
        typedef typename bctype_vec::const_iterator bctype_vec_it;

        count = 0;
        for (bctype_map_it it = fi.begin(); it != fi.end(); ++it)
        {
            std::string label = it->first;
            //gsDebug << "Label='" << label << "'\n";
            bctype_map map = it->second;

            for (bctype_iv_it bcV = map.begin(); bcV != map.end(); ++bcV)
            {
                int index = bcV->first;
                bctype_vec vec = bcV->second;
                //gsDebug << "index='" << index << "'\n";
                //gsDebug << "vec='" << vec.size() << "'\n";
                gsXmlNode * bcNode = internal::makeNode("bc", data);
                gsXmlAttribute * typeNode = internal::makeAttribute("type",
                        label, data);
                gsXmlAttribute * indexNode = internal::makeAttribute("function",
                        index, data);
                bcNode->append_attribute(typeNode);
                bcNode->append_attribute(indexNode);
                bool first = true;
                std::ostringstream oss;
                for (bctype_vec_it bc = vec.begin(); bc != vec.end(); ++bc)
                {
                    const boundary_condition<T> b = (**bc);
                    //gsDebug << "iterate over boundary condition with '"
                    //        << b.m_label << "'\n";
                    if (first)
                    {
                        gsXmlAttribute * unknownNode = internal::makeAttribute(
                                "unknown", b.m_unknown, data);
                        bcNode->append_attribute(unknownNode);
                        first = false;
                    }
                    else
                    {
                        oss << " ";
                    }
                    oss << b.ps.patch << " " << b.ps.m_index;
                }
                char * value = data.allocate_string(oss.str().c_str());
                bcNode->value(value);
                BCs->append_node(bcNode);
                ++count;
            }
        }
        typename gsBoundaryConditions<T>::const_citerator ci;
        for (ci = obj.cornerValues().begin(); ci != obj.cornerValues().end();
                ci++)
        {
            corner_value<T> c = *ci;
            gsXmlNode * cvNode = internal::makeNode("cv", data);
            gsXmlAttribute * unknownNode = internal::makeAttribute("unknown",
                    c.unknown, data);
            gsXmlAttribute * patchNode = internal::makeAttribute("patch",
                    c.patch, data);
            gsXmlAttribute * cornerNode = internal::makeAttribute("corner",
                    c.corner.m_index, data);
            cvNode->append_attribute(unknownNode);
            cvNode->append_attribute(patchNode);
            cvNode->append_attribute(cornerNode);
            std::ostringstream oss;
            oss << c.value;
            char * value = data.allocate_string(oss.str().c_str());
            cvNode->value(value);
            /// gsDebug << "Corner value='" << c.value << ", " << c.patch << ", " << c.unknown << "'\n";
            BCs->append_node(cvNode);
        }
        return BCs;
    }

private:
    static gsXmlNode * putFunctionFromXml(
            const typename gsFunction<T>::Ptr & obj, gsXmlTree & data,
            int index)
    {
        gsXmlNode * result = internal::makeNode("Function", data);
        if (typeid(*obj) == typeid(gsFunctionExpr<T> ))
        {
            gsFunctionExpr<T> * ptr2 =
                    dynamic_cast<gsFunctionExpr<T> *>(obj.get());
            gsFunctionExpr<T> expr = *ptr2;
            result = putFunctionExprFromXml(expr, result, data);
        }
        gsXmlAttribute * indexNode = internal::makeAttribute("index", index,
                data);
        result->append_attribute(indexNode);
        return result;
    }

    static gsXmlNode * putFunctionExprFromXml(const gsFunctionExpr<T> & obj,
            gsXmlNode * result, gsXmlTree & data)
    {
        std::string typeStr = gsXml<gsFunctionExpr<T> >::type();
        gsXmlAttribute * type = internal::makeAttribute("type", typeStr, data);
        result->append_attribute(type);
        gsXmlAttribute * dim = internal::makeAttribute("dim", obj.domainDim(),
                data);
        result->append_attribute(dim);
        // set value
        std::ostringstream stream;
        bool first = true;
        for (short_t i = 0; i < obj.targetDim(); ++i)
        {
            if (!first)
            {
                stream << ", ";
            }
            stream << obj.expression(i);
            first = false;
        }
        //val = stream.str();
        char * value = data.allocate_string(stream.str().c_str());
        result->value(value);
        return result;
    }

};

} // end namespace internal

} // end namespace gismo
<commit_msg>improve reading of BC from xml file<commit_after>/** @file gsBoundaryConditions.hpp

    @brief Implementation file for the gsBoundaryConditions class.

    This file is part of the G+Smo library.

    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/.

    Author(s): A. Mantzaflaris
*/

#include <gsIO/gsXml.h>
#include <gsCore/gsFunctionExpr.h>
#include <gsUtils/gsSortedVector.h>

namespace gismo
{

namespace internal
{

/// @brief I/O for boundary conditions from file
template<class T>
class gsXml< gsBoundaryConditions<T> >
{
private:
    gsXml() { }
    typedef gsBoundaryConditions<T> Object;
public:
    GSXML_COMMON_FUNCTIONS(Object);
    static std::string tag  () { return "boundaryConditions"; }
    static std::string type () { return ""; }

    GSXML_GET_POINTER(Object);

    static void get_into(gsXmlNode * node, Object & result)
    {
        GISMO_ASSERT(!strcmp(node->name(), tag().c_str()),
                "Something went wrong. Expected tag "<< tag());

        //gsXmlNode * tmp = node->first_node("patches");
        //GISMO_ASSERT(tmp, "No pathes tag");
//
//        std::istringstream str;
//        str.str( tmp->value() );
//        // Resolve ID numbers
//        std::map<int,int> ids;
//        if ( ! strcmp( tmp->first_attribute("type")->value(), "id_range") )
//        {
//            int first, last;
//            gsGetInt(str, first);
//            gsGetInt(str, last);
//            for ( int i = first; i<=last; ++i )
//                ids[i] = i - first;
//        }
//        else if ( ! strcmp( tmp->first_attribute("type")->value(),"id_index") )
//        {
//            int c = 0;
//            for (int pindex; gsGetInt(str, pindex);)
//                ids[pindex] = c++;
//        }
//        else
//        {
//            gsWarn<<"Incomplete tag \"patch\" in boundaryConditions.\n";
//        }
        std::istringstream str;
        std::map<int, int> ids;

        // Read function inventory
        int count = countByTag("Function", node);
        std::vector<typename gsFunctionExpr<T>::Ptr> func(count); // todo: gsFunction::Ptr
        for (gsXmlNode * child = node->first_node("Function"); child; child =
                child->next_sibling("Function"))
        {
            const int i = atoi(child->first_attribute("index")->value());
            func[i] = memory::make_shared(new gsFunctionExpr<T>);
            getFunctionFromXml(child, *func[i]);
        }

        // Read boundary conditions
        std::vector<patchSide> boundaries;
        for (gsXmlNode * child = node->first_node("bc"); child;
                child = child->next_sibling("bc"))
        {
            const int uIndex = atoi(child->first_attribute("unknown")->value());
            const int fIndex = atoi(
                    child->first_attribute("function")->value());

            const gsXmlAttribute * comp = child->first_attribute("component");
            int cIndex = -1;
            if (NULL != comp)
                cIndex = atoi( comp->value() );

            const gsXmlAttribute * att_ispar = child->first_attribute("parametric");
            bool ispar = false;
            if (NULL != att_ispar)
                ispar = atoi( att_ispar->value() );

            getBoundaries(child, ids, boundaries);

            const gsXmlAttribute * bcat = child->first_attribute("type");
            GISMO_ASSERT(NULL != bcat, "No type provided");
            const char * bctype = bcat->value();
            for (std::vector<patchSide>::const_iterator it = boundaries.begin();
                    it != boundaries.end(); ++it)
                result.add(it->patch, it->side(), bctype,
                           func[fIndex], uIndex,cIndex, ispar);
        }

        T val(0);
        for (gsXmlNode * child = node->first_node("cv"); child;
                child = child->next_sibling("cv"))
        {
            str.clear();
            str.str(child->value());
            GISMO_ENSURE(gsGetReal(str, val), "No value");
            const int uIndex = atoi(child->first_attribute("unknown")->value());
            const int cIndex = atoi(child->first_attribute("corner")->value());
            int pIndex = atoi(child->first_attribute("patch")->value());
            pIndex = ids[pIndex];

            result.addCornerValue(cIndex, val, pIndex, uIndex);
        }
    }

    static gsXmlNode * put(const Object & obj, gsXmlTree & data)
    {
        // Check if the last node is a multipatch
        //gsXmlNode * mp = data.getRoot()->last_node("MultiPatch");

        gsXmlNode * BCs = internal::makeNode("boundaryConditions", data);
        //data.appendToRoot(BCs);
        gsXmlAttribute * multi = internal::makeAttribute("multipatch", "0",
                data);

        BCs->append_attribute(multi);

        // inventory of functions
        typedef typename gsBoundaryConditions<T>::const_bciterator bctype_it;
        typedef typename Object::const_iterator bc_it;

        std::vector<typename gsFunction<T>::Ptr> fun;
        //gsSortedVector<typename gsFunction<T>::Ptr> fun;
        typedef typename std::vector<const boundary_condition<T>*> bctype_vec;
        typedef typename std::map<int, bctype_vec> bctype_map;
        std::map<std::string, bctype_map> fi;

        for (bctype_it it = obj.beginAll(); it != obj.endAll(); ++it)
        {
            std::string label = it->first;
            bctype_map map;
            for (bc_it bc = it->second.begin(); bc != it->second.end(); ++bc)
            {
                typename gsFunction<T>::Ptr ptr = bc->function();
                bool contains = std::find(fun.begin(), fun.end(), ptr)
                        != fun.end();
                if (!contains)
                {
                    fun.push_back(ptr);
                }
                int index = std::find(fun.begin(), fun.end(), ptr)
                        - fun.begin();
//                fun.push_sorted_unique(ptr);
//                int index = fun.getIndex(ptr);
                std::vector<const boundary_condition<T>*> vec = map[index];
                const boundary_condition<T>* b = &(*bc);
                vec.push_back(b);
                map[index] = vec;
            }
            std::pair<std::string, bctype_map> pair(label, map);
            fi.insert(pair);
        }

        int count = 0;
        typedef typename std::vector<typename gsFunction<T>::Ptr>::const_iterator fun_it;
        for (fun_it fit = fun.begin(); fit != fun.end(); ++fit)
        {
            gsXmlNode * ff = putFunctionFromXml(*fit, data, count);
            BCs->append_node(ff);
            ++count;
        }

        // for all bcs, append bc, cv
        typedef typename std::map<std::string, bctype_map>::const_iterator bctype_map_it;
        typedef typename std::map<int, bctype_vec>::const_iterator bctype_iv_it;
        typedef typename bctype_vec::const_iterator bctype_vec_it;

        count = 0;
        for (bctype_map_it it = fi.begin(); it != fi.end(); ++it)
        {
            std::string label = it->first;
            //gsDebug << "Label='" << label << "'\n";
            bctype_map map = it->second;

            for (bctype_iv_it bcV = map.begin(); bcV != map.end(); ++bcV)
            {
                int index = bcV->first;
                bctype_vec vec = bcV->second;
                //gsDebug << "index='" << index << "'\n";
                //gsDebug << "vec='" << vec.size() << "'\n";
                gsXmlNode * bcNode = internal::makeNode("bc", data);
                gsXmlAttribute * typeNode = internal::makeAttribute("type",
                        label, data);
                gsXmlAttribute * indexNode = internal::makeAttribute("function",
                        index, data);
                bcNode->append_attribute(typeNode);
                bcNode->append_attribute(indexNode);
                bool first = true;
                std::ostringstream oss;
                for (bctype_vec_it bc = vec.begin(); bc != vec.end(); ++bc)
                {
                    const boundary_condition<T> b = (**bc);
                    //gsDebug << "iterate over boundary condition with '"
                    //        << b.m_label << "'\n";
                    if (first)
                    {
                        gsXmlAttribute * unknownNode = internal::makeAttribute(
                                "unknown", b.m_unknown, data);
                        bcNode->append_attribute(unknownNode);
                        first = false;
                    }
                    else
                    {
                        oss << " ";
                    }
                    oss << b.ps.patch << " " << b.ps.m_index;
                }
                char * value = data.allocate_string(oss.str().c_str());
                bcNode->value(value);
                BCs->append_node(bcNode);
                ++count;
            }
        }
        typename gsBoundaryConditions<T>::const_citerator ci;
        for (ci = obj.cornerValues().begin(); ci != obj.cornerValues().end();
                ci++)
        {
            corner_value<T> c = *ci;
            gsXmlNode * cvNode = internal::makeNode("cv", data);
            gsXmlAttribute * unknownNode = internal::makeAttribute("unknown",
                    c.unknown, data);
            gsXmlAttribute * patchNode = internal::makeAttribute("patch",
                    c.patch, data);
            gsXmlAttribute * cornerNode = internal::makeAttribute("corner",
                    c.corner.m_index, data);
            cvNode->append_attribute(unknownNode);
            cvNode->append_attribute(patchNode);
            cvNode->append_attribute(cornerNode);
            std::ostringstream oss;
            oss << c.value;
            char * value = data.allocate_string(oss.str().c_str());
            cvNode->value(value);
            /// gsDebug << "Corner value='" << c.value << ", " << c.patch << ", " << c.unknown << "'\n";
            BCs->append_node(cvNode);
        }
        return BCs;
    }

private:
    static gsXmlNode * putFunctionFromXml(
            const typename gsFunction<T>::Ptr & obj, gsXmlTree & data,
            int index)
    {
        gsXmlNode * result = internal::makeNode("Function", data);
        if (typeid(*obj) == typeid(gsFunctionExpr<T> ))
        {
            gsFunctionExpr<T> * ptr2 =
                    dynamic_cast<gsFunctionExpr<T> *>(obj.get());
            gsFunctionExpr<T> expr = *ptr2;
            result = putFunctionExprFromXml(expr, result, data);
        }
        gsXmlAttribute * indexNode = internal::makeAttribute("index", index,
                data);
        result->append_attribute(indexNode);
        return result;
    }

    static gsXmlNode * putFunctionExprFromXml(const gsFunctionExpr<T> & obj,
            gsXmlNode * result, gsXmlTree & data)
    {
        std::string typeStr = gsXml<gsFunctionExpr<T> >::type();
        gsXmlAttribute * type = internal::makeAttribute("type", typeStr, data);
        result->append_attribute(type);
        gsXmlAttribute * dim = internal::makeAttribute("dim", obj.domainDim(),
                data);
        result->append_attribute(dim);
        // set value
        std::ostringstream stream;
        bool first = true;
        for (short_t i = 0; i < obj.targetDim(); ++i)
        {
            if (!first)
            {
                stream << ", ";
            }
            stream << obj.expression(i);
            first = false;
        }
        //val = stream.str();
        char * value = data.allocate_string(stream.str().c_str());
        result->value(value);
        return result;
    }

};

} // end namespace internal

} // end namespace gismo
<|endoftext|>


<commit_before>#include "timerBlock.h"

#include <QtCore/QDebug>

using namespace qReal;
using namespace interpreters::robots::details::blocks;

void TimerBlock::run()
{
	int const interval = evaluate("Delay").toInt();
	qDebug() << "interval=" << interval;

	mTimer.setInterval(interval);
	mTimer.setSingleShot(true);
	connect(&mTimer, SIGNAL(timeout()), this, SLOT(timeout()));
	mTimer.start();
}

void TimerBlock::timeout()
{
	qDebug() << "emit done(mNextBlock)";
	emit done(mNextBlock);
}
<commit_msg>One more stupid bug with timer fixed.<commit_after>#include "timerBlock.h"

#include <QtCore/QDebug>

using namespace qReal;
using namespace interpreters::robots::details::blocks;

void TimerBlock::run()
{
	int const interval = evaluate("Delay").toInt();
	qDebug() << "interval=" << interval;

	mTimer.setInterval(interval);
	mTimer.setSingleShot(true);
	connect(&mTimer, SIGNAL(timeout()), this, SLOT(timeout()), Qt::UniqueConnection);
	mTimer.start();
}

void TimerBlock::timeout()
{
	qDebug() << "emit done(mNextBlock)";
	emit done(mNextBlock);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativeview.h>
#include <private/qdeclarativeflipable_p.h>
#include <private/qdeclarativevaluetype_p.h>
#include <QFontMetrics>
#include <private/qdeclarativerectangle_p.h>
#include <math.h>

class tst_qdeclarativeflipable : public QObject
{
    Q_OBJECT
public:
    tst_qdeclarativeflipable();

private slots:
    void create();
    void checkFrontAndBack();
    void setFrontAndBack();

    // below here task issues
    void QTBUG_9161_crash();
    void QTBUG_8474_qgv_abort();

private:
    QDeclarativeEngine engine;
};

tst_qdeclarativeflipable::tst_qdeclarativeflipable()
{
}

void tst_qdeclarativeflipable::create()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    delete obj;
}

void tst_qdeclarativeflipable::checkFrontAndBack()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    QVERIFY(obj->front() != 0);
    QVERIFY(obj->back() != 0);
    delete obj;
}

void tst_qdeclarativeflipable::setFrontAndBack()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    QVERIFY(obj->front() != 0);
    QVERIFY(obj->back() != 0);

    QString message = "QML Flipable (" + c.url().toString() + ":3:1) front is a write-once property";
    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
    obj->setFront(new QDeclarativeRectangle());

    message = "QML Flipable (" + c.url().toString() + ":3:1) back is a write-once property";
    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
    obj->setBack(new QDeclarativeRectangle());
    delete obj;
}

void tst_qdeclarativeflipable::QTBUG_9161_crash()
{
    QDeclarativeView *canvas = new QDeclarativeView;
    canvas->setSource(QUrl(SRCDIR "/data/crash.qml"));
    QGraphicsObject *root = canvas->rootObject();
    QVERIFY(root != 0);
    canvas->show();
    delete canvas;
}

void tst_qdeclarativeflipable::QTBUG_8474_qgv_abort()
{
    QDeclarativeView *canvas = new QDeclarativeView;
    canvas->setSource(QUrl(SRCDIR "/data/flipable-abort.qml"));
    QGraphicsObject *root = canvas->rootObject();
    QVERIFY(root != 0);
    canvas->show();
    delete canvas;
}

QTEST_MAIN(tst_qdeclarativeflipable)

#include "tst_qdeclarativeflipable.moc"
<commit_msg>Test fix.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QtDeclarative/qdeclarativecomponent.h>
#include <QtDeclarative/qdeclarativeview.h>
#include <private/qdeclarativeflipable_p.h>
#include <private/qdeclarativevaluetype_p.h>
#include <QFontMetrics>
#include <private/qdeclarativerectangle_p.h>
#include <math.h>

class tst_qdeclarativeflipable : public QObject
{
    Q_OBJECT
public:
    tst_qdeclarativeflipable();

private slots:
    void create();
    void checkFrontAndBack();
    void setFrontAndBack();

    // below here task issues
    void QTBUG_9161_crash();
    void QTBUG_8474_qgv_abort();

private:
    QDeclarativeEngine engine;
};

tst_qdeclarativeflipable::tst_qdeclarativeflipable()
{
}

void tst_qdeclarativeflipable::create()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    delete obj;
}

void tst_qdeclarativeflipable::checkFrontAndBack()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    QVERIFY(obj->front() != 0);
    QVERIFY(obj->back() != 0);
    delete obj;
}

void tst_qdeclarativeflipable::setFrontAndBack()
{
    QDeclarativeEngine engine;
    QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/test-flipable.qml"));
    QDeclarativeFlipable *obj = qobject_cast<QDeclarativeFlipable*>(c.create());

    QVERIFY(obj != 0);
    QVERIFY(obj->front() != 0);
    QVERIFY(obj->back() != 0);

    QString message = "QML Flipable (" + c.url().toString() + ":3:1) front is a write-once property";
    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
    obj->setFront(new QDeclarativeRectangle());

    message = "QML Flipable (" + c.url().toString() + ":3:1) back is a write-once property";
    QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
    obj->setBack(new QDeclarativeRectangle());
    delete obj;
}

void tst_qdeclarativeflipable::QTBUG_9161_crash()
{
    QDeclarativeView *canvas = new QDeclarativeView;
    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/crash.qml"));
    QGraphicsObject *root = canvas->rootObject();
    QVERIFY(root != 0);
    canvas->show();
    delete canvas;
}

void tst_qdeclarativeflipable::QTBUG_8474_qgv_abort()
{
    QDeclarativeView *canvas = new QDeclarativeView;
    canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/flipable-abort.qml"));
    QGraphicsObject *root = canvas->rootObject();
    QVERIFY(root != 0);
    canvas->show();
    delete canvas;
}

QTEST_MAIN(tst_qdeclarativeflipable)

#include "tst_qdeclarativeflipable.moc"
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ed.h"
#include "listen.h"

void
lwait_object::cleanup ()
{
  if (hevent)
    {
      SetEvent (hevent);
      CloseHandle (hevent);
      hevent = 0;
    }
}

static void
decref_waitobj (lisp lwaitobj)
{
  if (xwait_object_hevent (lwaitobj)
      && !--xwait_object_ref (lwaitobj))
    ((lwait_object *)lwaitobj)->cleanup ();
}

void
Buffer::cleanup_waitobj_list ()
{
  for (lisp p = lwaitobj_list; consp (p); p = xcdr (p))
    {
      lisp lwaitobj = xcar (p);
      if (wait_object_p (lwaitobj))
        decref_waitobj (lwaitobj);
    }
  lwaitobj_list = Qnil;
}

lisp
Fsi_create_wait_object ()
{
  lisp lwaitobj = make_wait_object ();
  xwait_object_hevent (lwaitobj) = CreateEvent (0, 0, 0, 0);
  if (!xwait_object_hevent (lwaitobj))
    FEsimple_win32_error (GetLastError ());
  xwait_object_ref (lwaitobj) = 0;
  return lwaitobj;
}

lisp
Fsi_add_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  bp->lwaitobj_list = xcons (lwaitobj, bp->lwaitobj_list);
  xwait_object_ref (lwaitobj)++;
  return Qt;
}

lisp
Fsi_remove_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  if (lwaitobj == Qnil)
    bp->cleanup_waitobj_list ();
  else if (delq (lwaitobj, &bp->lwaitobj_list))
    decref_waitobj (lwaitobj);
  return Qt;
}

UINT wm_private_xyzzysrv;
static HANDLE hevent_listen;

void
init_listen_server ()
{
  hevent_listen = CreateEvent (0, 1, 0, 0);
  if (hevent_listen)
    SetProp (app.toplev, xyzzysrv_name, hevent_listen);
  wm_private_xyzzysrv = RegisterWindowMessage (xyzzysrv_name);
}

void
start_listen_server ()
{
  if (hevent_listen)
    SetEvent (hevent_listen);
}

void
end_listen_server ()
{
  if (hevent_listen)
    {
      SetEvent (hevent_listen);
      CloseHandle (hevent_listen);
      hevent_listen = 0;
      RemoveProp (app.toplev, xyzzysrv_name);
    }
}

lisp
Fstart_xyzzy_server ()
{
  if (!hevent_listen)
    init_listen_server ();
  start_listen_server ();
  return boole (hevent_listen);
}

lisp
Fstop_xyzzy_server ()
{
  end_listen_server ();
  return Qnil;
}

int
read_listen_server (WPARAM wparam, LPARAM lparam)
{
  HANDLE hproc = OpenProcess (PROCESS_DUP_HANDLE, 0, wparam);
  if (!hproc)
    return 0;

  HANDLE hmap;
  int r = DuplicateHandle (hproc, HANDLE (lparam), GetCurrentProcess (), &hmap,
                           0, 0, DUPLICATE_SAME_ACCESS);
  CloseHandle (hproc);
  if (!r)
    return 0;

  r = 0;
  void *v = MapViewOfFile (hmap, FILE_MAP_WRITE, 0, 0, 0);
  if (v && !IsBadReadPtr (v, sizeof (xyzzysrv_param)))
    {
      xyzzysrv_param *param = (xyzzysrv_param *)v;
      param->pid = 0;
      param->hevent = 0;
      param->hwnd = 0;
      if (!IsBadReadPtr (param, param->size))
        {
          r = -1;
          lisp stream = Qnil;
          protect_gc gcpro (stream);
          dynamic_bind dynb (Vsi_accept_kill_xyzzy, boole (param->kill_ok));
          try
            {
              save_cursor_depth cursor_depth;
              stream = Fmake_string_input_stream (make_string (param->data), 0, 0);
              lisp obj = Feval (Fread (stream, Qnil, Qnil, Qnil));
              if (wait_object_p (obj)
                  && xwait_object_hevent (obj)
                  && xwait_object_ref (obj))
                {
                  param->pid = GetCurrentProcessId ();
                  param->hevent = xwait_object_hevent (obj);
                  param->hwnd = app.toplev;
                }
              r = 1;
            }
          catch (nonlocal_jump &)
            {
              print_condition (nonlocal_jump::data ());
            }
          if (stream != Qnil)
            {
              Fclose (stream, Qnil);
              refresh_screen (1);
            }
        }
      UnmapViewOfFile (v);
    }
  CloseHandle (hmap);
  return r;
}
<commit_msg>Extract eval_xyzzysrv_param (#359)<commit_after>#include "stdafx.h"
#include "ed.h"
#include "listen.h"

void
lwait_object::cleanup ()
{
  if (hevent)
    {
      SetEvent (hevent);
      CloseHandle (hevent);
      hevent = 0;
    }
}

static void
decref_waitobj (lisp lwaitobj)
{
  if (xwait_object_hevent (lwaitobj)
      && !--xwait_object_ref (lwaitobj))
    ((lwait_object *)lwaitobj)->cleanup ();
}

void
Buffer::cleanup_waitobj_list ()
{
  for (lisp p = lwaitobj_list; consp (p); p = xcdr (p))
    {
      lisp lwaitobj = xcar (p);
      if (wait_object_p (lwaitobj))
        decref_waitobj (lwaitobj);
    }
  lwaitobj_list = Qnil;
}

lisp
Fsi_create_wait_object ()
{
  lisp lwaitobj = make_wait_object ();
  xwait_object_hevent (lwaitobj) = CreateEvent (0, 0, 0, 0);
  if (!xwait_object_hevent (lwaitobj))
    FEsimple_win32_error (GetLastError ());
  xwait_object_ref (lwaitobj) = 0;
  return lwaitobj;
}

lisp
Fsi_add_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  bp->lwaitobj_list = xcons (lwaitobj, bp->lwaitobj_list);
  xwait_object_ref (lwaitobj)++;
  return Qt;
}

lisp
Fsi_remove_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  if (lwaitobj == Qnil)
    bp->cleanup_waitobj_list ();
  else if (delq (lwaitobj, &bp->lwaitobj_list))
    decref_waitobj (lwaitobj);
  return Qt;
}

UINT wm_private_xyzzysrv;
static HANDLE hevent_listen;

void
init_listen_server ()
{
  hevent_listen = CreateEvent (0, 1, 0, 0);
  if (hevent_listen)
    SetProp (app.toplev, xyzzysrv_name, hevent_listen);
  wm_private_xyzzysrv = RegisterWindowMessage (xyzzysrv_name);
}

void
start_listen_server ()
{
  if (hevent_listen)
    SetEvent (hevent_listen);
}

void
end_listen_server ()
{
  if (hevent_listen)
    {
      SetEvent (hevent_listen);
      CloseHandle (hevent_listen);
      hevent_listen = 0;
      RemoveProp (app.toplev, xyzzysrv_name);
    }
}

lisp
Fstart_xyzzy_server ()
{
  if (!hevent_listen)
    init_listen_server ();
  start_listen_server ();
  return boole (hevent_listen);
}

lisp
Fstop_xyzzy_server ()
{
  end_listen_server ();
  return Qnil;
}

static int
eval_xyzzysrv_param (xyzzysrv_param *param)
{
  int r = 0;
  param->pid = 0;
  param->hevent = 0;
  param->hwnd = 0;
  if (!IsBadReadPtr (param, param->size))
    {
      r = -1;
      lisp stream = Qnil;
      protect_gc gcpro (stream);
      dynamic_bind dynb (Vsi_accept_kill_xyzzy, boole (param->kill_ok));
      try
        {
          save_cursor_depth cursor_depth;
          stream = Fmake_string_input_stream (make_string (param->data), 0, 0);
          lisp obj = Feval (Fread (stream, Qnil, Qnil, Qnil));
          if (wait_object_p (obj)
              && xwait_object_hevent (obj)
              && xwait_object_ref (obj))
            {
              param->pid = GetCurrentProcessId ();
              param->hevent = xwait_object_hevent (obj);
              param->hwnd = app.toplev;
            }
          r = 1;
        }
      catch (nonlocal_jump &)
        {
          print_condition (nonlocal_jump::data ());
        }
      if (stream != Qnil)
        {
          Fclose (stream, Qnil);
          refresh_screen (1);
        }
    }
  return r;
}

int
read_listen_server (WPARAM wparam, LPARAM lparam)
{
  HANDLE hproc = OpenProcess (PROCESS_DUP_HANDLE, 0, wparam);
  if (!hproc)
    return 0;

  HANDLE hmap;
  int r = DuplicateHandle (hproc, HANDLE (lparam), GetCurrentProcess (), &hmap,
                           0, 0, DUPLICATE_SAME_ACCESS);
  CloseHandle (hproc);
  if (!r)
    return 0;

  r = 0;
  void *v = MapViewOfFile (hmap, FILE_MAP_WRITE, 0, 0, 0);
  if (v && !IsBadReadPtr (v, sizeof (xyzzysrv_param)))
    {
      xyzzysrv_param *param = (xyzzysrv_param *)v;
      r = eval_xyzzysrv_param (param);
      UnmapViewOfFile (v);
    }
  CloseHandle (hmap);
  return r;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ed.h"
#include "listen.h"

void
lwait_object::cleanup ()
{
  if (hevent)
    {
      SetEvent (hevent);
      CloseHandle (hevent);
      hevent = 0;
    }
}

static void
decref_waitobj (lisp lwaitobj)
{
  if (xwait_object_hevent (lwaitobj)
      && !--xwait_object_ref (lwaitobj))
    ((lwait_object *)lwaitobj)->cleanup ();
}

void
Buffer::cleanup_waitobj_list ()
{
  for (lisp p = lwaitobj_list; consp (p); p = xcdr (p))
    {
      lisp lwaitobj = xcar (p);
      if (wait_object_p (lwaitobj))
        decref_waitobj (lwaitobj);
    }
  lwaitobj_list = Qnil;
}

lisp
Fsi_create_wait_object ()
{
  lisp lwaitobj = make_wait_object ();
  xwait_object_hevent (lwaitobj) = CreateEvent (0, 0, 0, 0);
  if (!xwait_object_hevent (lwaitobj))
    FEsimple_win32_error (GetLastError ());
  xwait_object_ref (lwaitobj) = 0;
  return lwaitobj;
}

lisp
Fsi_add_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  bp->lwaitobj_list = xcons (lwaitobj, bp->lwaitobj_list);
  xwait_object_ref (lwaitobj)++;
  return Qt;
}

lisp
Fsi_remove_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  if (lwaitobj == Qnil)
    bp->cleanup_waitobj_list ();
  else if (delq (lwaitobj, &bp->lwaitobj_list))
    decref_waitobj (lwaitobj);
  return Qt;
}

UINT wm_private_xyzzysrv;
static HANDLE hevent_listen;

void
init_listen_server ()
{
  hevent_listen = CreateEvent (0, 1, 0, 0);
  if (hevent_listen)
    SetProp (active_app_frame().toplev, xyzzysrv_name, hevent_listen);
  wm_private_xyzzysrv = RegisterWindowMessage (xyzzysrv_name);
}

void
start_listen_server ()
{
  if (hevent_listen)
    SetEvent (hevent_listen);
}

void
end_listen_server ()
{
  if (hevent_listen)
    {
      SetEvent (hevent_listen);
      CloseHandle (hevent_listen);
      hevent_listen = 0;
      RemoveProp (active_app_frame().toplev, xyzzysrv_name);
    }
}

lisp
Fstart_xyzzy_server ()
{
  if (!hevent_listen)
    init_listen_server ();
  start_listen_server ();
  return boole (hevent_listen);
}

lisp
Fstop_xyzzy_server ()
{
  end_listen_server ();
  return Qnil;
}

int
read_listen_server (WPARAM wparam, LPARAM lparam)
{
  HANDLE hproc = OpenProcess (PROCESS_DUP_HANDLE, 0, wparam);
  if (!hproc)
    return 0;

  HANDLE hmap;
  int r = DuplicateHandle (hproc, HANDLE (lparam), GetCurrentProcess (), &hmap,
                           0, 0, DUPLICATE_SAME_ACCESS);
  CloseHandle (hproc);
  if (!r)
    return 0;

  r = 0;
  void *v = MapViewOfFile (hmap, FILE_MAP_WRITE, 0, 0, 0);
  if (v && !IsBadReadPtr (v, sizeof (xyzzysrv_param)))
    {
      xyzzysrv_param *param = (xyzzysrv_param *)v;
      param->pid = 0;
      param->hevent = 0;
      param->hwnd = 0;
      if (!IsBadReadPtr (param, param->size))
        {
          r = -1;
          lisp stream = Qnil;
          protect_gc gcpro (stream);
          dynamic_bind dynb (Vsi_accept_kill_xyzzy, boole (param->kill_ok));
          try
            {
              save_cursor_depth cursor_depth;
              stream = Fmake_string_input_stream (make_string (param->data), 0, 0);
              lisp obj = Feval (Fread (stream, Qnil, Qnil, Qnil));
              if (wait_object_p (obj)
                  && xwait_object_hevent (obj)
                  && xwait_object_ref (obj))
                {
                  param->pid = GetCurrentProcessId ();
                  param->hevent = xwait_object_hevent (obj);
                  param->hwnd = active_app_frame().toplev;
                }
              r = 1;
            }
          catch (nonlocal_jump &)
            {
              print_condition (nonlocal_jump::data ());
            }
          if (stream != Qnil)
            {
              Fclose (stream, Qnil);
              refresh_screen (1);
            }
        }
      UnmapViewOfFile (v);
    }
  CloseHandle (hmap);
  return r;
}
<commit_msg>Extract eval_xyzzysrv_param (#359)<commit_after>#include "stdafx.h"
#include "ed.h"
#include "listen.h"

void
lwait_object::cleanup ()
{
  if (hevent)
    {
      SetEvent (hevent);
      CloseHandle (hevent);
      hevent = 0;
    }
}

static void
decref_waitobj (lisp lwaitobj)
{
  if (xwait_object_hevent (lwaitobj)
      && !--xwait_object_ref (lwaitobj))
    ((lwait_object *)lwaitobj)->cleanup ();
}

void
Buffer::cleanup_waitobj_list ()
{
  for (lisp p = lwaitobj_list; consp (p); p = xcdr (p))
    {
      lisp lwaitobj = xcar (p);
      if (wait_object_p (lwaitobj))
        decref_waitobj (lwaitobj);
    }
  lwaitobj_list = Qnil;
}

lisp
Fsi_create_wait_object ()
{
  lisp lwaitobj = make_wait_object ();
  xwait_object_hevent (lwaitobj) = CreateEvent (0, 0, 0, 0);
  if (!xwait_object_hevent (lwaitobj))
    FEsimple_win32_error (GetLastError ());
  xwait_object_ref (lwaitobj) = 0;
  return lwaitobj;
}

lisp
Fsi_add_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  bp->lwaitobj_list = xcons (lwaitobj, bp->lwaitobj_list);
  xwait_object_ref (lwaitobj)++;
  return Qt;
}

lisp
Fsi_remove_wait_object (lisp lwaitobj, lisp lbuffer)
{
  check_wait_object (lwaitobj);
  Buffer *bp = Buffer::coerce_to_buffer (lbuffer);
  if (lwaitobj == Qnil)
    bp->cleanup_waitobj_list ();
  else if (delq (lwaitobj, &bp->lwaitobj_list))
    decref_waitobj (lwaitobj);
  return Qt;
}

UINT wm_private_xyzzysrv;
static HANDLE hevent_listen;

void
init_listen_server ()
{
  hevent_listen = CreateEvent (0, 1, 0, 0);
  if (hevent_listen)
    SetProp (active_app_frame().toplev, xyzzysrv_name, hevent_listen);
  wm_private_xyzzysrv = RegisterWindowMessage (xyzzysrv_name);
}

void
start_listen_server ()
{
  if (hevent_listen)
    SetEvent (hevent_listen);
}

void
end_listen_server ()
{
  if (hevent_listen)
    {
      SetEvent (hevent_listen);
      CloseHandle (hevent_listen);
      hevent_listen = 0;
      RemoveProp (active_app_frame().toplev, xyzzysrv_name);
    }
}

lisp
Fstart_xyzzy_server ()
{
  if (!hevent_listen)
    init_listen_server ();
  start_listen_server ();
  return boole (hevent_listen);
}

lisp
Fstop_xyzzy_server ()
{
  end_listen_server ();
  return Qnil;
}

static int
eval_xyzzysrv_param (xyzzysrv_param *param)
{
  int r = 0;
  param->pid = 0;
  param->hevent = 0;
  param->hwnd = 0;
  if (!IsBadReadPtr (param, param->size))
    {
      r = -1;
      lisp stream = Qnil;
      protect_gc gcpro (stream);
      dynamic_bind dynb (Vsi_accept_kill_xyzzy, boole (param->kill_ok));
      try
        {
          save_cursor_depth cursor_depth;
          stream = Fmake_string_input_stream (make_string (param->data), 0, 0);
          lisp obj = Feval (Fread (stream, Qnil, Qnil, Qnil));
          if (wait_object_p (obj)
              && xwait_object_hevent (obj)
              && xwait_object_ref (obj))
            {
              param->pid = GetCurrentProcessId ();
              param->hevent = xwait_object_hevent (obj);
              param->hwnd = active_app_frame().toplev;
            }
          r = 1;
        }
      catch (nonlocal_jump &)
        {
          print_condition (nonlocal_jump::data ());
        }
      if (stream != Qnil)
        {
          Fclose (stream, Qnil);
          refresh_screen (1);
        }
    }
  return r;
}

int
read_listen_server (WPARAM wparam, LPARAM lparam)
{
  HANDLE hproc = OpenProcess (PROCESS_DUP_HANDLE, 0, wparam);
  if (!hproc)
    return 0;

  HANDLE hmap;
  int r = DuplicateHandle (hproc, HANDLE (lparam), GetCurrentProcess (), &hmap,
                           0, 0, DUPLICATE_SAME_ACCESS);
  CloseHandle (hproc);
  if (!r)
    return 0;

  r = 0;
  void *v = MapViewOfFile (hmap, FILE_MAP_WRITE, 0, 0, 0);
  if (v && !IsBadReadPtr (v, sizeof (xyzzysrv_param)))
    {
      xyzzysrv_param *param = (xyzzysrv_param *)v;
      r = eval_xyzzysrv_param (param);
      UnmapViewOfFile (v);
    }
  CloseHandle (hmap);
  return r;
}
<|endoftext|>