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

#ifndef _XMLOFF_FORMS_CONTROLELEMENT_HXX_
#define _XMLOFF_FORMS_CONTROLELEMENT_HXX_

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif

//.........................................................................
namespace xmloff
{
//.........................................................................

    //=====================================================================
    //= OControlElement
    //=====================================================================
    /** helper for translating between control types and XML tags
    */
    class OControlElement
    {
    public:
        enum ElementType
        {
            TEXT = 0,
            TEXT_AREA,
            PASSWORD,
            FILE,
            FORMATTED_TEXT,
            FIXED_TEXT,
            COMBOBOX,
            LISTBOX,
            BUTTON,
            IMAGE,
            CHECKBOX,
            RADIO,
            FRAME,
            IMAGE_FRAME,
            HIDDEN,
            GRID,
            GENERIC_CONTROL,

            UNKNOWN // must be the last element
        };

    protected:
        /** ctor.

This default constructor is protected, 'cause this class is not intended to be instantiated
            directly. Instead, the derived classes should be used.

        */
        OControlElement() { }

    public:
        /** retrieves the tag name to be used to describe a control of the given type

The retuned string is the pure element name, without any namespace.

            @param  _eType
                the element type
        */
        static const sal_Char* getElementName(ElementType _eType);
    };

//.........................................................................
}   // namespace xmloff
//.........................................................................

#endif _XMLOFF_FORMS_CONTROLELEMENT_HXX_

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *  Revision 1.1  2000/12/06 17:30:27  fs
 *  initial checkin - implementations for formlayer import/export - still under construction
 *
 *
 *  Revision 1.0 06.12.00 14:00:25  fs
 ************************************************************************/

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

#ifndef _XMLOFF_FORMS_CONTROLELEMENT_HXX_
#define _XMLOFF_FORMS_CONTROLELEMENT_HXX_

#ifndef _SAL_TYPES_H_
#include <sal/types.h>
#endif

//.........................................................................
namespace xmloff
{
//.........................................................................

    //=====================================================================
    //= OControlElement
    //=====================================================================
    /** helper for translating between control types and XML tags
    */
    class OControlElement
    {
    public:
        enum ElementType
        {
            TEXT = 0,
            TEXT_AREA,
            PASSWORD,
            FILE,
            FORMATTED_TEXT,
            FIXED_TEXT,
            COMBOBOX,
            LISTBOX,
            BUTTON,
            IMAGE,
            CHECKBOX,
            RADIO,
            FRAME,
            IMAGE_FRAME,
            HIDDEN,
            GRID,
            GENERIC_CONTROL,

            UNKNOWN // must be the last element
        };

    protected:
        /** ctor.

This default constructor is protected, 'cause this class is not intended to be instantiated
            directly. Instead, the derived classes should be used.

        */
        OControlElement() { }

    public:
        /** retrieves the tag name to be used to describe a control of the given type

The retuned string is the pure element name, without any namespace.

            @param  _eType
                the element type
        */
        static const sal_Char* getElementName(ElementType _eType);
    };

//.........................................................................
}   // namespace xmloff
//.........................................................................

#endif // _XMLOFF_FORMS_CONTROLELEMENT_HXX_

/*************************************************************************
 * history:
 *  $Log: not supported by cvs2svn $
 *  Revision 1.2.152.1  2003/06/06 11:08:47  mh
 *  join: from cws_srx644_ooo11beta2
 *
 *  Revision 1.2.130.1  2003/05/21 13:37:06  waratah
 *  1858: Simple patch to comment out trailing text after #endif, waring removal
 *
 *  Revision 1.2  2001/01/03 16:25:34  fs
 *  file format change (extra wrapper element for controls, similar to columns)
 *
 *  Revision 1.1  2000/12/06 17:30:27  fs
 *  initial checkin - implementations for formlayer import/export - still under construction
 *
 *
 *  Revision 1.0 06.12.00 14:00:25  fs
 ************************************************************************/

<|endoftext|>


<commit_before>/**
 * Created by TekuConcept on 8/3/2016.
 */

#include "C_Thrusters.h"

#define MOD_COUNT 6u // thruster modifiers
#define THRUST_COUNT 6u
float    hw_modifiers_[MOD_COUNT];
float    hw_trim_[THRUST_COUNT];
uint16_t hw_thrust_mem_[THRUST_COUNT];
//Servo  hw_servos_[THRUST_COUNT];

void update_pair(uint8_t,uint8_t,uint8_t,uint8_t);

void HW_configure(
	int aPairFirst, int aPairSecond,
	int bPairFirst, int bPairSecond,
	int cPairFirst, int cPairSecond) {
	//hw_servos_[HW_A_FIRST ].attach(aPairFirst );
	//hw_servos_[HW_A_SECOND].attach(aPairSecond);
	//hw_servos_[HW_B_FIRST ].attach(bPairFirst );
	//hw_servos_[HW_B_SECOND].attach(bPairSecond);
	//hw_servos_[HW_C_FIRST ].attach(cPairFirst );
	//hw_servos_[HW_C_SECOND].attach(cPairSecond);
	HW_hard_reset();
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - *\
 *            Thruster Modifier Functions            *
\* - - - - - - - - - - - - - - - - - - - - - - - - - */

void HW_set_modifier(uint8_t index, float value) {
	if(index >= MOD_COUNT)
		return;

	if(value > 1)
		value = 1;
	else if(value < -1)
		value = -1;
	hw_modifiers_[index] = value;

	// update thrust output
	switch(index) {
	case HW_MOD_LIN1:
	case HW_MOD_ANG1:
		update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
		break;
	case HW_MOD_LIN2:
	case HW_MOD_ANG2:
		update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
		break;
	case HW_MOD_LIN3:
	case HW_MOD_ANG3:
		update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
		break;
	}
}

float HW_get_modifier(uint8_t index) {
	if(index >= MOD_COUNT)
		return -2;
	return hw_modifiers_[index];
}

/**
 * Warning: This does not guarantee the thrusters
 *          will turn off because of offset and
 *          trim values.
 */
void HW_reset_modifiers() {
	for(int i = 0; i < MOD_COUNT; i++) {
		hw_modifiers_[i] = 0;
	}
	update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
	update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
	update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - *\
 *              Core Thruster Functions              *
\* - - - - - - - - - - - - - - - - - - - - - - - - - */

void HW_soft_reset() {
	for(int i = 0; i < MOD_COUNT; i++) {
		hw_modifiers_[i] = 0;
	}
	for(int i = 0; i < THRUST_COUNT; i++) {
		//hw_servos_[i].writeMicroseconds(HW_IDLE);
		hw_thrust_mem_[i] = HW_IDLE;
	}
}

void HW_hard_reset() {
	HW_soft_reset();
	for(int i = 0; i < THRUST_COUNT; i++) {
		hw_trim_[i] = 1;
	}
}

void set_safe_ratio(float* a, float* b) {
	if(*a >  1)	{
		*b /= *a;
		*a = 1;
	}
	else if(*a < -1) {
		*b /= -*a;
		*a = -1;
	}
	else if(*b >  1) {
		*a /= *b;
		*b = 1;
	}
	else if(*b < -1) {
		*a /= -*b;
		*b = -1;
	}
}

void update_pair(uint8_t hw_left, uint8_t hw_right,
	uint8_t linear_mod, uint8_t angular_mod) {
	float left = 0, right = 0, temp = 0;

	// blend move and yaw
	left = hw_modifiers_[linear_mod];
	right = left;
	temp = hw_modifiers_[angular_mod];
	left += temp;
	right -= temp;

	// set safe ranges as a ratio of the current values
	set_safe_ratio(&left, &right);

	HW_set_thruster(hw_left,
		(uint16_t)(HW_IDLE + left *hw_trim_[hw_left ]*HW_DIFF));
	HW_set_thruster(hw_right,
		(uint16_t)(HW_IDLE + right*hw_trim_[hw_right]*HW_DIFF));
}

void HW_set_thruster(uint8_t index, uint16_t value) {
	if(index >= THRUST_COUNT)
		return;
	//hw_servos_[index].writeMicroseconds(value);
	hw_thrust_mem_[index] = value;
}

uint16_t HW_get_thruster(uint8_t index) {
	if(index >= THRUST_COUNT)
		return 0;
	return hw_thrust_mem_[index];
}

void HW_set_trim(uint8_t index, float value) {
	if(index >= THRUST_COUNT)
		return;
	if(value > 1)
		value = 1;
	else if(value < -1)
		value = -1;

	hw_trim_[index] = value;
	switch(index) {
	case HW_A_FIRST:
	case HW_A_SECOND:
		update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
		break;
	case HW_B_FIRST:
	case HW_B_SECOND:
		update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
		break;
	case HW_C_FIRST:
	case HW_C_SECOND:
		update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
		break;
	}
}

float HW_get_trim(uint8_t index) {
	if(index >= THRUST_COUNT)
		return -2;
	return hw_trim_[index];
}

void HW_reset_trim() {
	for(int i = 0; i < THRUST_COUNT; i++) {
		hw_trim_[i] = 1;
	}
	update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
	update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
	update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
}<commit_msg>Enable Servo Control<commit_after>/**
 * Created by TekuConcept on 8/3/2016.
 */

#include "C_Thrusters.h"

#define MOD_COUNT 6u // thruster modifiers
#define THRUST_COUNT 6u
float    hw_modifiers_[MOD_COUNT];
float    hw_trim_[THRUST_COUNT];
uint16_t hw_thrust_mem_[THRUST_COUNT];
Servo    hw_servos_[THRUST_COUNT];

void update_pair(uint8_t,uint8_t,uint8_t,uint8_t);

void HW_configure(
	int aPairFirst, int aPairSecond,
	int bPairFirst, int bPairSecond,
	int cPairFirst, int cPairSecond) {
	hw_servos_[HW_A_FIRST ].attach(aPairFirst );
	hw_servos_[HW_A_SECOND].attach(aPairSecond);
	hw_servos_[HW_B_FIRST ].attach(bPairFirst );
	hw_servos_[HW_B_SECOND].attach(bPairSecond);
	hw_servos_[HW_C_FIRST ].attach(cPairFirst );
	hw_servos_[HW_C_SECOND].attach(cPairSecond);
	HW_hard_reset();
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - *\
 *            Thruster Modifier Functions            *
\* - - - - - - - - - - - - - - - - - - - - - - - - - */

void HW_set_modifier(uint8_t index, float value) {
	if(index >= MOD_COUNT)
		return;

	if(value > 1)
		value = 1;
	else if(value < -1)
		value = -1;
	hw_modifiers_[index] = value;

	// update thrust output
	switch(index) {
	case HW_MOD_LIN1:
	case HW_MOD_ANG1:
		update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
		break;
	case HW_MOD_LIN2:
	case HW_MOD_ANG2:
		update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
		break;
	case HW_MOD_LIN3:
	case HW_MOD_ANG3:
		update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
		break;
	}
}

float HW_get_modifier(uint8_t index) {
	if(index >= MOD_COUNT)
		return -2;
	return hw_modifiers_[index];
}

/**
 * Warning: This does not guarantee the thrusters
 *          will turn off because of offset and
 *          trim values.
 */
void HW_reset_modifiers() {
	for(int i = 0; i < MOD_COUNT; i++) {
		hw_modifiers_[i] = 0;
	}
	update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
	update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
	update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - *\
 *              Core Thruster Functions              *
\* - - - - - - - - - - - - - - - - - - - - - - - - - */

void HW_soft_reset() {
	for(int i = 0; i < MOD_COUNT; i++) {
		hw_modifiers_[i] = 0;
	}
	for(int i = 0; i < THRUST_COUNT; i++) {
		hw_servos_[i].writeMicroseconds(HW_IDLE);
		hw_thrust_mem_[i] = HW_IDLE;
	}
}

void HW_hard_reset() {
	HW_soft_reset();
	for(int i = 0; i < THRUST_COUNT; i++) {
		hw_trim_[i] = 1;
	}
}

void set_safe_ratio(float* a, float* b) {
	if(*a >  1)	{
		*b /= *a;
		*a = 1;
	}
	else if(*a < -1) {
		*b /= -*a;
		*a = -1;
	}
	else if(*b >  1) {
		*a /= *b;
		*b = 1;
	}
	else if(*b < -1) {
		*a /= -*b;
		*b = -1;
	}
}

void update_pair(uint8_t hw_left, uint8_t hw_right,
	uint8_t linear_mod, uint8_t angular_mod) {
	float left = 0, right = 0, temp = 0;

	// blend move and yaw
	left = hw_modifiers_[linear_mod];
	right = left;
	temp = hw_modifiers_[angular_mod];
	left += temp;
	right -= temp;

	// set safe ranges as a ratio of the current values
	set_safe_ratio(&left, &right);

	HW_set_thruster(hw_left,
		(uint16_t)(HW_IDLE + left *hw_trim_[hw_left ]*HW_DIFF));
	HW_set_thruster(hw_right,
		(uint16_t)(HW_IDLE + right*hw_trim_[hw_right]*HW_DIFF));
}

void HW_set_thruster(uint8_t index, uint16_t value) {
	if(index >= THRUST_COUNT)
		return;
	hw_servos_[index].writeMicroseconds(value);
	hw_thrust_mem_[index] = value;
}

uint16_t HW_get_thruster(uint8_t index) {
	if(index >= THRUST_COUNT)
		return 0;
	return hw_thrust_mem_[index];
}

void HW_set_trim(uint8_t index, float value) {
	if(index >= THRUST_COUNT)
		return;
	if(value > 1)
		value = 1;
	else if(value < -1)
		value = -1;

	hw_trim_[index] = value;
	switch(index) {
	case HW_A_FIRST:
	case HW_A_SECOND:
		update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
		break;
	case HW_B_FIRST:
	case HW_B_SECOND:
		update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
		break;
	case HW_C_FIRST:
	case HW_C_SECOND:
		update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
		break;
	}
}

float HW_get_trim(uint8_t index) {
	if(index >= THRUST_COUNT)
		return -2;
	return hw_trim_[index];
}

void HW_reset_trim() {
	for(int i = 0; i < THRUST_COUNT; i++) {
		hw_trim_[i] = 1;
	}
	update_pair(HW_A_FIRST, HW_A_SECOND, HW_MOD_LIN1, HW_MOD_ANG1);
	update_pair(HW_B_FIRST, HW_B_SECOND, HW_MOD_LIN2, HW_MOD_ANG2);
	update_pair(HW_C_FIRST, HW_C_SECOND, HW_MOD_LIN3, HW_MOD_ANG3);
}<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkIdList.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkIdList.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkIdList);

vtkIdList::vtkIdList()
{
  this->NumberOfIds = 0;
  this->Size = 0;
  this->Ids = NULL;
}

vtkIdList::~vtkIdList()
{
  delete [] this->Ids;
}

void vtkIdList::Initialize()
{
  delete [] this->Ids;
  this->Ids = NULL;
  this->NumberOfIds = 0;
  this->Size = 0;
}

int vtkIdList::Allocate(const vtkIdType sz, const int vtkNotUsed(strategy))
{
  if ( sz > this->Size)
    {
    this->Initialize();
    this->Size = ( sz > 0 ? sz : 1);
    if ( (this->Ids = new vtkIdType[this->Size]) == NULL )
      {
      return 0;
      }
    }
  this->NumberOfIds = 0;
  return 1;
}

void vtkIdList::SetNumberOfIds(const vtkIdType number)
{
  this->Allocate(number,0);
  this->NumberOfIds = number;
}

vtkIdType vtkIdList::InsertUniqueId(const vtkIdType vtkid)
{
  for (vtkIdType i=0; i < this->NumberOfIds; i++)
    {
    if ( vtkid == this->Ids[i] )
      {
      return i;
      }
    }

  return this->InsertNextId(vtkid);
}

vtkIdType *vtkIdList::WritePointer(const vtkIdType i, const vtkIdType number)
{
  vtkIdType newSize=i+number;
  if ( newSize > this->Size )
    {
    this->Resize(newSize);
    }
  if ( newSize > this->NumberOfIds )
    {
    this->NumberOfIds = newSize;
    }
  return this->Ids + i;
}

void vtkIdList::DeleteId(vtkIdType vtkid)
{
  vtkIdType i=0;

  // while loop is necessary to delete all occurrences of vtkid
  while ( i < this->NumberOfIds )
    {
    for ( ; i < this->NumberOfIds; i++)
      {
      if ( this->Ids[i] == vtkid )
        {
        break;
        }
      }

    // if found; replace current id with last
    if ( i < this->NumberOfIds )
      {
      this->SetId(i,this->Ids[this->NumberOfIds-1]);
      this->NumberOfIds--;
      }
    }
}

void vtkIdList::DeepCopy(vtkIdList *ids)
{
  this->SetNumberOfIds(ids->NumberOfIds);
  std::copy(ids->Ids, ids->Ids + ids->NumberOfIds, this->Ids);
  this->Squeeze();
}

vtkIdType *vtkIdList::Resize(const vtkIdType sz)
{
  vtkIdType *newIds;
  vtkIdType newSize;

  if ( sz > this->Size )
    {
    newSize = this->Size + sz;
    }
  else if (sz == this->Size)
    {
    return this->Ids;
    }
  else
    {
    newSize = sz;
    }

  if (newSize <= 0)
    {
    this->Initialize();
    return 0;
    }

  if ( (newIds = new vtkIdType[newSize]) == NULL )
    {
    vtkErrorMacro(<< "Cannot allocate memory\n");
    return 0;
    }

  if (this->Ids)
    {
    memcpy(newIds, this->Ids,
           static_cast<size_t>(sz < this->Size ? sz : this->Size) * sizeof(vtkIdType));
    delete [] this->Ids;
    }

  this->Size = newSize;
  this->Ids = newIds;
  return this->Ids;
}

#define VTK_TMP_ARRAY_SIZE 500
// Intersect this list with another vtkIdList. Updates current list according
// to result of intersection operation.
void vtkIdList::IntersectWith(vtkIdList* otherIds)
{
  // Fast method due to Dr. Andreas Mueller of ISE Integrated Systems
  // Engineering (CH).
  vtkIdType thisNumIds = this->GetNumberOfIds();

  if (thisNumIds <= VTK_TMP_ARRAY_SIZE)
    {//Use fast method if we can fit in temporary storage
    vtkIdType  thisIds[VTK_TMP_ARRAY_SIZE];
    vtkIdType i, vtkid;

    for (i=0; i < thisNumIds; i++)
      {
      thisIds[i] = this->GetId(i);
      }
    for (this->Reset(), i=0; i < thisNumIds; i++)
      {
      vtkid = thisIds[i];
      if ( otherIds->IsId(vtkid) != (-1) )
        {
        this->InsertNextId(vtkid);
        }
      }
    }
  else
    {//use slower method for extreme cases
    vtkIdType *thisIds = new vtkIdType [thisNumIds];
    vtkIdType  i, vtkid;

    for (i=0; i < thisNumIds; i++)
      {
      *(thisIds + i) = this->GetId(i);
      }
    for (this->Reset(), i=0; i < thisNumIds; i++)
      {
      vtkid = *(thisIds + i);
      if ( otherIds->IsId(vtkid) != (-1) )
        {
        this->InsertNextId(vtkid);
        }
      }
    delete [] thisIds;
    }
}
#undef VTK_TMP_ARRAY_SIZE

void vtkIdList::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Number of Ids: " << this->NumberOfIds << "\n";
}
<commit_msg>BUG: Fix NULL dereference in std::copy argument<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkIdList.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkIdList.h"
#include "vtkObjectFactory.h"

vtkStandardNewMacro(vtkIdList);

vtkIdList::vtkIdList()
{
  this->NumberOfIds = 0;
  this->Size = 0;
  this->Ids = NULL;
}

vtkIdList::~vtkIdList()
{
  delete [] this->Ids;
}

void vtkIdList::Initialize()
{
  delete [] this->Ids;
  this->Ids = NULL;
  this->NumberOfIds = 0;
  this->Size = 0;
}

int vtkIdList::Allocate(const vtkIdType sz, const int vtkNotUsed(strategy))
{
  if ( sz > this->Size)
    {
    this->Initialize();
    this->Size = ( sz > 0 ? sz : 1);
    if ( (this->Ids = new vtkIdType[this->Size]) == NULL )
      {
      return 0;
      }
    }
  this->NumberOfIds = 0;
  return 1;
}

void vtkIdList::SetNumberOfIds(const vtkIdType number)
{
  this->Allocate(number,0);
  this->NumberOfIds = number;
}

vtkIdType vtkIdList::InsertUniqueId(const vtkIdType vtkid)
{
  for (vtkIdType i=0; i < this->NumberOfIds; i++)
    {
    if ( vtkid == this->Ids[i] )
      {
      return i;
      }
    }

  return this->InsertNextId(vtkid);
}

vtkIdType *vtkIdList::WritePointer(const vtkIdType i, const vtkIdType number)
{
  vtkIdType newSize=i+number;
  if ( newSize > this->Size )
    {
    this->Resize(newSize);
    }
  if ( newSize > this->NumberOfIds )
    {
    this->NumberOfIds = newSize;
    }
  return this->Ids + i;
}

void vtkIdList::DeleteId(vtkIdType vtkid)
{
  vtkIdType i=0;

  // while loop is necessary to delete all occurrences of vtkid
  while ( i < this->NumberOfIds )
    {
    for ( ; i < this->NumberOfIds; i++)
      {
      if ( this->Ids[i] == vtkid )
        {
        break;
        }
      }

    // if found; replace current id with last
    if ( i < this->NumberOfIds )
      {
      this->SetId(i,this->Ids[this->NumberOfIds-1]);
      this->NumberOfIds--;
      }
    }
}

void vtkIdList::DeepCopy(vtkIdList *ids)
{
  this->SetNumberOfIds(ids->NumberOfIds);
  if (ids->NumberOfIds > 0)
    {
    std::copy(ids->Ids, ids->Ids + ids->NumberOfIds, this->Ids);
    }
  this->Squeeze();
}

vtkIdType *vtkIdList::Resize(const vtkIdType sz)
{
  vtkIdType *newIds;
  vtkIdType newSize;

  if ( sz > this->Size )
    {
    newSize = this->Size + sz;
    }
  else if (sz == this->Size)
    {
    return this->Ids;
    }
  else
    {
    newSize = sz;
    }

  if (newSize <= 0)
    {
    this->Initialize();
    return 0;
    }

  if ( (newIds = new vtkIdType[newSize]) == NULL )
    {
    vtkErrorMacro(<< "Cannot allocate memory\n");
    return 0;
    }

  if (this->Ids)
    {
    memcpy(newIds, this->Ids,
           static_cast<size_t>(sz < this->Size ? sz : this->Size) * sizeof(vtkIdType));
    delete [] this->Ids;
    }

  this->Size = newSize;
  this->Ids = newIds;
  return this->Ids;
}

#define VTK_TMP_ARRAY_SIZE 500
// Intersect this list with another vtkIdList. Updates current list according
// to result of intersection operation.
void vtkIdList::IntersectWith(vtkIdList* otherIds)
{
  // Fast method due to Dr. Andreas Mueller of ISE Integrated Systems
  // Engineering (CH).
  vtkIdType thisNumIds = this->GetNumberOfIds();

  if (thisNumIds <= VTK_TMP_ARRAY_SIZE)
    {//Use fast method if we can fit in temporary storage
    vtkIdType  thisIds[VTK_TMP_ARRAY_SIZE];
    vtkIdType i, vtkid;

    for (i=0; i < thisNumIds; i++)
      {
      thisIds[i] = this->GetId(i);
      }
    for (this->Reset(), i=0; i < thisNumIds; i++)
      {
      vtkid = thisIds[i];
      if ( otherIds->IsId(vtkid) != (-1) )
        {
        this->InsertNextId(vtkid);
        }
      }
    }
  else
    {//use slower method for extreme cases
    vtkIdType *thisIds = new vtkIdType [thisNumIds];
    vtkIdType  i, vtkid;

    for (i=0; i < thisNumIds; i++)
      {
      *(thisIds + i) = this->GetId(i);
      }
    for (this->Reset(), i=0; i < thisNumIds; i++)
      {
      vtkid = *(thisIds + i);
      if ( otherIds->IsId(vtkid) != (-1) )
        {
        this->InsertNextId(vtkid);
        }
      }
    delete [] thisIds;
    }
}
#undef VTK_TMP_ARRAY_SIZE

void vtkIdList::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  os << indent << "Number of Ids: " << this->NumberOfIds << "\n";
}
<|endoftext|>


<commit_before>#include <iostream>
#include <seqan/graph_types.h>
using namespace seqan;
// part 2
int main ()
{
	typedef unsigned int TCargo;
	typedef Graph<Undirected<TCargo> > TGraph;
	typedef VertexDescriptor<TGraph>::Type TVertexDescriptor;
// part 3
	TGraph g;

	TVertexDescriptor vertBerlin = addVertex(g);
	TVertexDescriptor vertHamburg = addVertex(g);
	TVertexDescriptor vertHannover = addVertex(g);
	TVertexDescriptor vertMainz = addVertex(g);
	TVertexDescriptor vertMuenchen = addVertex(g);

	addEdge(g, vertBerlin, vertHamburg, 289);
	addEdge(g, vertBerlin, vertHannover, 286);
	addEdge(g, vertBerlin, vertMainz, 573);
	addEdge(g, vertBerlin, vertMuenchen, 586);
	addEdge(g, vertHannover, vertMuenchen, 572);
	addEdge(g, vertHamburg, vertMainz, 521);
// part 4
	FILE* strmWrite = fopen("graph.dot", "w");
	write(strmWrite, g, DotDrawing());
	fclose(strmWrite);

	return 0;
}
<commit_msg>Using new-style FRAGMENT markers to mark fragments.<commit_after>// The lines FRAGMENT(fragment-name) mark the begin of fragments for being
// included in the documentation.  You can ignore them.
// FRAGMENT(includes)
#include <iostream>
#include <seqan/graph_types.h>
using namespace seqan;
// FRAGMENT(main-typedefs)
int main ()
{
	typedef unsigned int TCargo;
	typedef Graph<Undirected<TCargo> > TGraph;
	typedef VertexDescriptor<TGraph>::Type TVertexDescriptor;
// FRAGMENT(main-graph-construction)
	TGraph g;

	TVertexDescriptor vertBerlin = addVertex(g);
	TVertexDescriptor vertHamburg = addVertex(g);
	TVertexDescriptor vertHannover = addVertex(g);
	TVertexDescriptor vertMainz = addVertex(g);
	TVertexDescriptor vertMuenchen = addVertex(g);

	addEdge(g, vertBerlin, vertHamburg, 289);
	addEdge(g, vertBerlin, vertHannover, 286);
	addEdge(g, vertBerlin, vertMainz, 573);
	addEdge(g, vertBerlin, vertMuenchen, 586);
	addEdge(g, vertHannover, vertMuenchen, 572);
	addEdge(g, vertHamburg, vertMainz, 521);
// FRAGMENT(main-graph-io)
	FILE* strmWrite = fopen("graph.dot", "w");
	write(strmWrite, g, DotDrawing());
	fclose(strmWrite);

	return 0;
}
<|endoftext|>


<commit_before>/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* enchant
 * Copyright (C) 2003 Joan Moratinos <jmo@softcatala.org>, Dom Lachowicz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * In addition, as a special exception, Dom Lachowicz
 * gives permission to link the code of this program with
 * non-LGPL Spelling Provider libraries (eg: a MSFT Office
 * spell checker backend) and distribute linked combinations including
 * the two.  You must obey the GNU General Public License in all
 * respects for all of the code used other than said providers.  If you modify
 * this file, you may extend this exception to your version of the
 * file, but you are not obligated to do so.  If you do not wish to
 * do so, delete this exception statement from your version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <vector>

#include "myspell_checker.h"
#include "enchant.h"
#include "enchant-provider.h"

#define G_ICONV_INVALID (GIConv)-1

/***************************************************************************/

/* in preparation for using win32 registry keys, if necessary */

static char *
myspell_checker_get_prefix (void)
{
#ifdef ENCHANT_MYSPELL_DICT_DIR
	return g_strdup (ENCHANT_MYSPELL_DICT_DIR);
#else
	return NULL;
#endif
}

static bool
g_iconv_is_valid(GIConv i)
{
	return (i != G_ICONV_INVALID);
}

MySpellChecker::MySpellChecker()
{
	myspell = 0;
	m_translate_in = 0;
	m_translate_out = 0;
}

MySpellChecker::~MySpellChecker()
{
	delete myspell;
	if (g_iconv_is_valid (m_translate_in ))
		g_iconv_close(m_translate_in);
	m_translate_in = G_ICONV_INVALID;
	if (g_iconv_is_valid(m_translate_out))
		g_iconv_close(m_translate_out);
	m_translate_out = G_ICONV_INVALID;
}

bool
MySpellChecker::checkWord(const char *utf8Word, size_t len)
{
	if (len > MAXWORDLEN || !g_iconv_is_valid(m_translate_in))
		return false;

	std::string word (utf8Word, len);
	if (m_personal[word])
		return true;
	if (m_session[word])
		return true;

	char *in = (char*) utf8Word;
	char word8[MAXWORDLEN + 1];
	char *out = word8;
	size_t len_in = len * sizeof(char);
	size_t len_out = sizeof( word8 ) - 1;
	g_iconv(m_translate_in, &in, &len_in, &out, &len_out);
	*out = '\0';
	if (myspell->spell(word8))
		return true;
	else
		return false;
}

char**
MySpellChecker::suggestWord(const char* const utf8Word, size_t len, size_t *nsug)
{
	if (len > MAXWORDLEN
		|| !g_iconv_is_valid(m_translate_in)
		|| !g_iconv_is_valid(m_translate_out))
		return 0;
	char *in = (char*) utf8Word;
	char word8[MAXWORDLEN + 1];
	char *out = word8;
	size_t len_in = len;
	size_t len_out = sizeof(word8) - 1;
	g_iconv(m_translate_in, &in, &len_in, &out, &len_out);
	*out = '\0';
	char **sugMS;
	*nsug = myspell->suggest(&sugMS, word8);
	if (*nsug > 0) {
		char **sug = g_new0 (char *, *nsug + 1);
		for (int i=0; i<*nsug; i++) {
			in = sugMS[i];
			len_in = strlen(in);
			len_out = sizeof(char) * (len_in + 1);
			char *word = g_new0(char, len_out);
			out = reinterpret_cast<char *>(word);
			g_iconv(m_translate_out, &in, &len_in, &out, &len_out);
			*(out) = 0;
			sug[i] = word;
			free(sugMS[i]);
		}
		free(sugMS);
		return sug;
	}
	else
		return 0;
}

static void
s_buildHashNames (std::vector<std::string> & names, const char * dict)
{
	char * tmp, * private_dir, * home_dir, * ispell_prefix;

	names.clear ();

	home_dir = enchant_get_user_home_dir ();

	if (home_dir) {
		private_dir = g_build_filename (home_dir, ".enchant",
						"myspell", NULL);

		tmp = g_build_filename (private_dir, dict, NULL);
		names.push_back (tmp);
		g_free (tmp);

		g_free (private_dir);
		g_free (home_dir);
	}

	ispell_prefix = myspell_checker_get_prefix ();
	if (ispell_prefix) {
		tmp = g_build_filename (ispell_prefix, dict, NULL);
		names.push_back (tmp);
		g_free (tmp);
		g_free (ispell_prefix);
	}
}

static char *
myspell_request_dictionary (const char * tag)
{
	char * dic = NULL;

	std::vector<std::string> names;

	s_buildHashNames (names, tag);

	for (size_t i = 0; i < names.size () && !dic; i++) {
		if (g_file_test(names[i].c_str(), G_FILE_TEST_EXISTS))
			dic = g_strdup (names[i].c_str());
	}

	return dic;
}

bool
MySpellChecker::requestDictionary(const char *szLang)
{
	const char *dictBase = NULL;
	char *dic = NULL, *aff = NULL;
	char *home_dir = enchant_get_user_home_dir();

	dic = myspell_request_dictionary (szLang);
	if (!dic) {
		std::string shortened_dict (szLang);
		size_t uscore_pos;

		// try abbreviated form
		if ((uscore_pos = shortened_dict.rfind ('_')) != ((size_t)-1)) {
			shortened_dict = shortened_dict.substr(0, uscore_pos);
			dic = myspell_request_dictionary (shortened_dict.c_str());
		}
	}
	if (!dic)
		return false;

	aff = g_strdup(dic);
	int len_dic = strlen(dic);
	strcpy(aff+len_dic-3, "aff");
	myspell = new MySpell(aff, dic);
	g_free(dic);
	g_free(aff);
	char *enc = myspell->get_dic_encoding();

	m_translate_in = g_iconv_open(enc, "UTF-8");
	m_translate_out = g_iconv_open("UTF-8", enc);

	return true;
}

/*
 * Enchant
 */

static char **
myspell_dict_suggest (EnchantDict * me, const char *const word,
		     size_t len, size_t * out_n_suggs)
{
	MySpellChecker * checker;

	checker = (MySpellChecker *) me->user_data;
	return checker->suggestWord (word, len, out_n_suggs);
}

static int
myspell_dict_check (EnchantDict * me, const char *const word, size_t len)
{
	MySpellChecker * checker;

	checker = (MySpellChecker *) me->user_data;

	if (checker->checkWord(word, len))
		return 0;

	return 1;
}

static void
myspell_dict_add_to_personal (EnchantDict * me,
			     const char *const word, size_t len)
{
	MySpellChecker * checker;

	// emulate adding to a personal dictionary via a session-like
	// interface

	checker = (MySpellChecker *) me->user_data;
	checker->addToPersonal(word, len);
}

static void
myspell_dict_add_to_session(EnchantDict * me,
			    const char *const word, size_t len)
{
	MySpellChecker * checker;

	// implement a session interface

	checker = (MySpellChecker *) me->user_data;
	checker->addToSession(word, len);
}

static void
myspell_dict_free_suggestions (EnchantDict * me, char **str_list)
{
	g_strfreev (str_list);
}

static EnchantDict *
myspell_provider_request_dict(EnchantProvider * me, const char *const tag)
{
	EnchantDict *dict;
	MySpellChecker * checker;

	checker = new MySpellChecker();

	if (!checker)
		return NULL;

	if (!checker->requestDictionary(tag)) {
		delete checker;
		return NULL;
	}

	dict = g_new0(EnchantDict, 1);
	dict->user_data = (void *) checker;
	dict->check = myspell_dict_check;
	dict->suggest = myspell_dict_suggest;
	dict->add_to_personal = myspell_dict_add_to_personal;
	dict->add_to_session = myspell_dict_add_to_session;
	dict->free_suggestions = myspell_dict_free_suggestions;

	return dict;
}

static void
myspell_provider_dispose_dict (EnchantProvider * me, EnchantDict * dict)
{
	MySpellChecker *checker;

	checker = (MySpellChecker *) dict->user_data;
	delete checker;

	g_free (dict);
}

static EnchantDictStatus
myspell_provider_dictionary_status (struct str_enchant_provider * me,
				    const char *const tag)
{
	std::vector <std::string> names;

	s_buildHashNames (names, tag);
	for (size_t i = 0; i < names.size(); i++) {
		if (g_file_test (names[i].c_str(), G_FILE_TEST_EXISTS))
			return EDS_EXISTS;
	}

	std::string shortened_dict (tag);
	size_t uscore_pos;

	if ((uscore_pos = shortened_dict.rfind ('_')) != ((size_t)-1)) {
		shortened_dict = shortened_dict.substr(0, uscore_pos);

		s_buildHashNames (names, shortened_dict.c_str());
		for (size_t i = 0; i < names.size(); i++) {
			if (g_file_test (names[i].c_str(), G_FILE_TEST_EXISTS))
				return EDS_EXISTS;
		}
	}

	return EDS_DOESNT_EXIST;
}

static void
myspell_provider_dispose (EnchantProvider * me)
{
	g_free (me);
}

static char *
myspell_provider_identify (EnchantProvider * me)
{
	return "myspell";
}

static char *
myspell_provider_describe (EnchantProvider * me)
{
	return "Myspell Provider";
}

extern "C" {

ENCHANT_MODULE_EXPORT (EnchantProvider *)
init_enchant_provider (void)
{
	EnchantProvider *provider;

	provider = g_new0(EnchantProvider, 1);
	provider->dispose = myspell_provider_dispose;
	provider->request_dict = myspell_provider_request_dict;
	provider->dispose_dict = myspell_provider_dispose_dict;
	provider->dictionary_status = myspell_provider_dictionary_status;
	provider->identify = myspell_provider_identify;
	provider->describe = myspell_provider_describe;

	return provider;
}

} // extern C linkage
<commit_msg>fix myspell<commit_after>/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* enchant
 * Copyright (C) 2003 Joan Moratinos <jmo@softcatala.org>, Dom Lachowicz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * In addition, as a special exception, Dom Lachowicz
 * gives permission to link the code of this program with
 * non-LGPL Spelling Provider libraries (eg: a MSFT Office
 * spell checker backend) and distribute linked combinations including
 * the two.  You must obey the GNU General Public License in all
 * respects for all of the code used other than said providers.  If you modify
 * this file, you may extend this exception to your version of the
 * file, but you are not obligated to do so.  If you do not wish to
 * do so, delete this exception statement from your version.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <vector>

#include "myspell_checker.h"
#include "enchant.h"
#include "enchant-provider.h"

#define G_ICONV_INVALID (GIConv)-1

/***************************************************************************/

/* in preparation for using win32 registry keys, if necessary */

static char *
myspell_checker_get_prefix (void)
{
#ifdef ENCHANT_MYSPELL_DICT_DIR
	return g_strdup (ENCHANT_MYSPELL_DICT_DIR);
#else
	return NULL;
#endif
}

static bool
g_iconv_is_valid(GIConv i)
{
	return (i != G_ICONV_INVALID);
}

MySpellChecker::MySpellChecker()
{
	myspell = 0;
	m_translate_in = 0;
	m_translate_out = 0;
}

MySpellChecker::~MySpellChecker()
{
	delete myspell;
	if (g_iconv_is_valid (m_translate_in ))
		g_iconv_close(m_translate_in);
	m_translate_in = G_ICONV_INVALID;
	if (g_iconv_is_valid(m_translate_out))
		g_iconv_close(m_translate_out);
	m_translate_out = G_ICONV_INVALID;
}

bool
MySpellChecker::checkWord(const char *utf8Word, size_t len)
{
	if (len > MAXWORDLEN || !g_iconv_is_valid(m_translate_in))
		return false;

	std::string word (utf8Word, len);
	if (m_personal[word])
		return true;
	if (m_session[word])
		return true;

	char *in = (char*) utf8Word;
	char word8[MAXWORDLEN + 1];
	char *out = word8;
	size_t len_in = len * sizeof(char);
	size_t len_out = sizeof( word8 ) - 1;
	g_iconv(m_translate_in, &in, &len_in, &out, &len_out);
	*out = '\0';
	if (myspell->spell(word8))
		return true;
	else
		return false;
}

char**
MySpellChecker::suggestWord(const char* const utf8Word, size_t len, size_t *nsug)
{
	if (len > MAXWORDLEN
		|| !g_iconv_is_valid(m_translate_in)
		|| !g_iconv_is_valid(m_translate_out))
		return 0;
	char *in = (char*) utf8Word;
	char word8[MAXWORDLEN + 1];
	char *out = word8;
	size_t len_in = len;
	size_t len_out = sizeof(word8) - 1;
	g_iconv(m_translate_in, &in, &len_in, &out, &len_out);
	*out = '\0';
	char **sugMS;
	*nsug = myspell->suggest(&sugMS, word8);
	if (*nsug > 0) {
		char **sug = g_new0 (char *, *nsug + 1);
		for (int i=0; i<*nsug; i++) {
			in = sugMS[i];
			len_in = strlen(in);
			len_out = sizeof(char) * (len_in + 1);
			char *word = g_new0(char, len_out);
			out = reinterpret_cast<char *>(word);
			g_iconv(m_translate_out, &in, &len_in, &out, &len_out);
			*(out) = 0;
			sug[i] = word;
			free(sugMS[i]);
		}
		free(sugMS);
		return sug;
	}
	else
		return 0;
}

static void
s_buildHashNames (std::vector<std::string> & names, const char * dict)
{
	char * tmp, * private_dir, * home_dir, * ispell_prefix, * dict_dic;

	names.clear ();

	dict_dic = g_strconcat(dict, ".dic", NULL);

	home_dir = enchant_get_user_home_dir ();
	if (home_dir) {
		private_dir = g_build_filename (home_dir, ".enchant",
						"myspell", NULL);

		tmp = g_build_filename (private_dir, dict_dic, NULL);
		names.push_back (tmp);
		g_free (tmp);

		g_free (private_dir);
		g_free (home_dir);
	}

	myspell_prefix = myspell_checker_get_prefix ();
	if (myspell_prefix) {
		tmp = g_build_filename (myspell_prefix, dict_dict, NULL);
		names.push_back (tmp);
		g_free (tmp);
		g_free (myspell_prefix);
	}

	g_free(dict_dic);
}

static char *
myspell_request_dictionary (const char * tag)
{
	char * dic = NULL;

	std::vector<std::string> names;

	s_buildHashNames (names, tag);

	for (size_t i = 0; i < names.size () && !dic; i++) {
		if (g_file_test(names[i].c_str(), G_FILE_TEST_EXISTS))
			dic = g_strdup (names[i].c_str());
	}

	return dic;
}

bool
MySpellChecker::requestDictionary(const char *szLang)
{
	const char *dictBase = NULL;
	char *dic = NULL, *aff = NULL;
	char *home_dir = enchant_get_user_home_dir();

	dic = myspell_request_dictionary (szLang);
	if (!dic) {
		std::string shortened_dict (szLang);
		size_t uscore_pos;

		// try abbreviated form
		if ((uscore_pos = shortened_dict.rfind ('_')) != ((size_t)-1)) {
			shortened_dict = shortened_dict.substr(0, uscore_pos);
			dic = myspell_request_dictionary (shortened_dict.c_str());
		}
	}
	if (!dic)
		return false;

	aff = g_strdup(dic);
	int len_dic = strlen(dic);
	strcpy(aff+len_dic-3, "aff");
	myspell = new MySpell(aff, dic);
	g_free(dic);
	g_free(aff);
	char *enc = myspell->get_dic_encoding();

	m_translate_in = g_iconv_open(enc, "UTF-8");
	m_translate_out = g_iconv_open("UTF-8", enc);

	return true;
}

/*
 * Enchant
 */

static char **
myspell_dict_suggest (EnchantDict * me, const char *const word,
		     size_t len, size_t * out_n_suggs)
{
	MySpellChecker * checker;

	checker = (MySpellChecker *) me->user_data;
	return checker->suggestWord (word, len, out_n_suggs);
}

static int
myspell_dict_check (EnchantDict * me, const char *const word, size_t len)
{
	MySpellChecker * checker;

	checker = (MySpellChecker *) me->user_data;

	if (checker->checkWord(word, len))
		return 0;

	return 1;
}

static void
myspell_dict_add_to_personal (EnchantDict * me,
			     const char *const word, size_t len)
{
	MySpellChecker * checker;

	// emulate adding to a personal dictionary via a session-like
	// interface

	checker = (MySpellChecker *) me->user_data;
	checker->addToPersonal(word, len);
}

static void
myspell_dict_add_to_session(EnchantDict * me,
			    const char *const word, size_t len)
{
	MySpellChecker * checker;

	// implement a session interface

	checker = (MySpellChecker *) me->user_data;
	checker->addToSession(word, len);
}

static void
myspell_dict_free_suggestions (EnchantDict * me, char **str_list)
{
	g_strfreev (str_list);
}

static EnchantDict *
myspell_provider_request_dict(EnchantProvider * me, const char *const tag)
{
	EnchantDict *dict;
	MySpellChecker * checker;

	checker = new MySpellChecker();

	if (!checker)
		return NULL;

	if (!checker->requestDictionary(tag)) {
		delete checker;
		return NULL;
	}

	dict = g_new0(EnchantDict, 1);
	dict->user_data = (void *) checker;
	dict->check = myspell_dict_check;
	dict->suggest = myspell_dict_suggest;
	dict->add_to_personal = myspell_dict_add_to_personal;
	dict->add_to_session = myspell_dict_add_to_session;
	dict->free_suggestions = myspell_dict_free_suggestions;

	return dict;
}

static void
myspell_provider_dispose_dict (EnchantProvider * me, EnchantDict * dict)
{
	MySpellChecker *checker;

	checker = (MySpellChecker *) dict->user_data;
	delete checker;

	g_free (dict);
}

static EnchantDictStatus
myspell_provider_dictionary_status (struct str_enchant_provider * me,
				    const char *const tag)
{
	std::vector <std::string> names;

	s_buildHashNames (names, tag);
	for (size_t i = 0; i < names.size(); i++) {
		if (g_file_test (names[i].c_str(), G_FILE_TEST_EXISTS))
			return EDS_EXISTS;
	}

	std::string shortened_dict (tag);
	size_t uscore_pos;

	if ((uscore_pos = shortened_dict.rfind ('_')) != ((size_t)-1)) {
		shortened_dict = shortened_dict.substr(0, uscore_pos);

		s_buildHashNames (names, shortened_dict.c_str());
		for (size_t i = 0; i < names.size(); i++) {
			if (g_file_test (names[i].c_str(), G_FILE_TEST_EXISTS))
				return EDS_EXISTS;
		}
	}

	return EDS_DOESNT_EXIST;
}

static void
myspell_provider_dispose (EnchantProvider * me)
{
	g_free (me);
}

static char *
myspell_provider_identify (EnchantProvider * me)
{
	return "myspell";
}

static char *
myspell_provider_describe (EnchantProvider * me)
{
	return "Myspell Provider";
}

extern "C" {

ENCHANT_MODULE_EXPORT (EnchantProvider *)
init_enchant_provider (void)
{
	EnchantProvider *provider;

	provider = g_new0(EnchantProvider, 1);
	provider->dispose = myspell_provider_dispose;
	provider->request_dict = myspell_provider_request_dict;
	provider->dispose_dict = myspell_provider_dispose_dict;
	provider->dictionary_status = myspell_provider_dictionary_status;
	provider->identify = myspell_provider_identify;
	provider->describe = myspell_provider_describe;

	return provider;
}

} // extern C linkage
<|endoftext|>


<commit_before>#include "task_mnist.h"
#include "common/logger.h"
#include "common/cast.hpp"
#include "common/io_arch.h"
#include "common/io_stream.h"
#include "loss.h"

namespace ncv
{
        mnist_task_t::mnist_task_t(const string_t& configuration)
                :       task_t(configuration)
        {
        }

        bool mnist_task_t::load(const string_t& dir)
        {
                const string_t test_ifile = dir + "/t10k-images-idx3-ubyte.gz";
                const string_t test_gfile = dir + "/t10k-labels-idx1-ubyte.gz";
                const size_t n_test_samples = 10000;

                const string_t train_ifile = dir + "/train-images-idx3-ubyte.gz";
                const string_t train_gfile = dir + "/train-labels-idx1-ubyte.gz";
                const size_t n_train_samples = 60000;

                clear_memory(n_train_samples + n_test_samples);

                return  load(train_ifile, train_gfile, protocol::train, n_train_samples) &&
                        load(test_ifile, test_gfile, protocol::test, n_test_samples);
        }

        bool mnist_task_t::load(const string_t& ifile, const string_t& gfile, protocol p, size_t count)
        {
                size_t icount = 0;
                size_t gcount = 0;

                std::vector<char> vbuffer(n_rows() * n_cols());
                char* buffer = vbuffer.data();
                char label[2];

                // load image file
                const auto iop = [&] (const string_t&, const io::data_t& data)
                {
                        io::stream_t stream(data.data(), data.size());

                        stream.read(buffer, 16);
                        while (stream.read(buffer, vbuffer.size()) && stream.gcount() == vbuffer.size())
                        {
                                image_t image;
                                image.load_luma(buffer, n_rows(), n_cols());
                                m_images.push_back(image);

                                ++ icount;
                        }

                        return true;
                };

                log_info() << "MNIST: loading file <" << ifile << "> ...";
                if (!io::decode(ifile, "MNIST: ", iop))
                {
                        log_error() << "MNIST: failed to load file <" << ifile << ">!";
                        return 0;
                }

                // load ground truth file
                const auto gop = [&] (const string_t&, const io::data_t& data)
                {
                        io::stream_t stream(data.data(), data.size());

                        stream.read(buffer, 8);
                        while (stream.read(label, 1) && stream.gcount() == 1)
                        {
                                const size_t ilabel = math::cast<size_t>(label[0]);

                                sample_t sample(m_samples.size(), sample_region(0, 0));
                                sample.m_label = "digit" + text::to_string(ilabel);
                                sample.m_target = ncv::class_target(ilabel, n_outputs());
                                sample.m_fold = { 0, p };
                                m_samples.push_back(sample);

                                ++ gcount;
                        }

                        return true;
                };

                log_info() << "MNIST: loading file <" << gfile << "> ...";
                if (!io::decode(gfile, "MNIST: ", gop))
                {
                        log_error() << "MNIST: failed to load file <" << gfile << ">!";
                        return 0;
                }

                // OK
                log_info() << "MNIST: loaded " << icount << "/" << gcount << " samples.";
                return (icount == gcount == count) > 0;
        }
}
<commit_msg>fix MNIST loading<commit_after>#include "task_mnist.h"
#include "common/logger.h"
#include "common/cast.hpp"
#include "common/io_arch.h"
#include "common/io_stream.h"
#include "loss.h"

namespace ncv
{
        mnist_task_t::mnist_task_t(const string_t& configuration)
                :       task_t(configuration)
        {
        }

        bool mnist_task_t::load(const string_t& dir)
        {
                const string_t test_ifile = dir + "/t10k-images-idx3-ubyte.gz";
                const string_t test_gfile = dir + "/t10k-labels-idx1-ubyte.gz";
                const size_t n_test_samples = 10000;

                const string_t train_ifile = dir + "/train-images-idx3-ubyte.gz";
                const string_t train_gfile = dir + "/train-labels-idx1-ubyte.gz";
                const size_t n_train_samples = 60000;

                clear_memory(n_train_samples + n_test_samples);

                return  load(train_ifile, train_gfile, protocol::train, n_train_samples) &&
                        load(test_ifile, test_gfile, protocol::test, n_test_samples);
        }

        bool mnist_task_t::load(const string_t& ifile, const string_t& gfile, protocol p, size_t count)
        {
                size_t icount = 0;
                size_t gcount = 0;

                std::vector<char> vbuffer(n_rows() * n_cols());
                char* buffer = vbuffer.data();
                char label[2];

                // load image file
                const auto iop = [&] (const string_t&, const io::data_t& data)
                {
                        io::stream_t stream(data.data(), data.size());

                        stream.read(buffer, 16);
                        while (stream.read(buffer, vbuffer.size()) && stream.gcount() == vbuffer.size())
                        {
                                image_t image;
                                image.load_luma(buffer, n_rows(), n_cols());
                                m_images.push_back(image);

                                ++ icount;
                        }

                        return true;
                };

                log_info() << "MNIST: loading file <" << ifile << "> ...";
                if (!io::decode(ifile, "MNIST: ", iop))
                {
                        log_error() << "MNIST: failed to load file <" << ifile << ">!";
                        return false;
                }

                // load ground truth file
                const auto gop = [&] (const string_t&, const io::data_t& data)
                {
                        io::stream_t stream(data.data(), data.size());

                        stream.read(buffer, 8);
                        while (stream.read(label, 1) && stream.gcount() == 1)
                        {
                                const size_t ilabel = math::cast<size_t>(label[0]);

                                sample_t sample(m_samples.size(), sample_region(0, 0));
                                sample.m_label = "digit" + text::to_string(ilabel);
                                sample.m_target = ncv::class_target(ilabel, n_outputs());
                                sample.m_fold = { 0, p };
                                m_samples.push_back(sample);

                                ++ gcount;
                        }

                        return true;
                };

                log_info() << "MNIST: loading file <" << gfile << "> ...";
                if (!io::decode(gfile, "MNIST: ", gop))
                {
                        log_error() << "MNIST: failed to load file <" << gfile << ">!";
                        return false;
                }

                // OK
                log_info() << "MNIST: loaded " << icount << "/" << gcount << " samples.";
                return (count == gcount) && (count == icount);
        }
}
<|endoftext|>


<commit_before>/// \file nested_traversal_finder.cpp: Contains implementation for a TraversalFinder that works on non-leaf Snarls.

#include "genotypekit.hpp"

namespace vg {

using namespace std;

/**
 * This TraversalFinder emits at least one traversal representing every node,
 * edge, or child Snarl. Only works on ultrabubbles, and so does not handle
 * cycles.
 */
class NestedTraversalFinder : public TraversalFinder {

protected:
    /// The annotated, augmented graph we're finding traversals in
    AugmentedGraph& augmented;
    /// The SnarlManager managiung the snarls we use
    SnarlManager& snarl_manager;

    /**
     * Given an edge or node or child snarl in the augmented graph, look out
     * from the edge or node or child in both directions to find a shortest
     * bubble connecting the start and end of the given site.
     *
     * Exactly one of edge and node and child must be non-null.
     *
     * Return the found traversal as a vector of Visits, including anchoring
     * Visits to the site's start and end nodes. Also return the minimum support
     * found on any edge or node in the bubble that is not contained within a
     * child.
     */
    pair<Support, vector<Visit>> find_bubble(Node* node, Edge* edge, Snarl* child, const Snarl& site);

    /**
     * Get the minimum support of all nodes and edges used in the given path
     * that are not inside child snarls.
     */
    Support min_support_in_path(const vector<Visit>& path);

    /**
     * Do a breadth-first search left from the given node traversal, and return
     * lengths (in visits) and paths starting at the given node and ending on
     * the given indexed path. Refuses to visit nodes with no support.
     *
     * Lengths are included so that shorter paths sort first.
     */
    set<pair<size_t, list<Visit>>> search_left(Visit root, const Snarl& site,
        const map<NodeTraversal, const Snarl*>& child_boundary_index);

    /**
     * Do a breadth-first search right from the given node traversal, and return
     * lengths (in visits) and paths starting at the given node and ending on
     * the given indexed path.
     *
     * Lengths are included so that shorter paths sort first.
     */
    set<pair<size_t, list<Visit>>> search_right(Visit root, const Snarl& site,
        const map<NodeTraversal, const Snarl*>& child_boundary_index);

    /**
     * Get the length of a path through nodes and child sites, in base pairs.
     * Ignores any bases inside child sites.
     */
    size_t bp_length(const list<Visit>& path);

public:

    NestedTraversalFinder(AugmentedGraph& augmented, SnarlManager& snarl_manager);

    /// Should we emit verbose debugging info?
    bool verbose = false;

    virtual ~NestedTraversalFinder() = default;

    /**
     * Find traversals to cover the nodes, edges, and children of the snarl.
     * Always emits the primary path traversal first, if applicable.
     */
    virtual vector<SnarlTraversal> find_traversals(const Snarl& site);

};

NestedTraversalFinder::NestedTraversalFinder(AugmentedGraph& augmented,
    SnarlManager& snarl_manager) : augmented(augmented), snarl_manager(snarl_manager) {

    // Nothing to do!

}

vector<SnarlTraversal> NestedTraversalFinder::find_traversals(const Snarl& site) {

    // TODO: implement
}

pair<Support, vector<Visit>> NestedTraversalFinder::find_bubble(Node* node, Edge* edge, Snarl* child, const Snarl& site) {

    // TODO: implement

}

Support NestedTraversalFinder::min_support_in_path(const vector<Visit>& path) {

    // TODO: implement
}

set<pair<size_t, list<Visit>>> NestedTraversalFinder::search_left(Visit root, const Snarl& site,
    const map<NodeTraversal, const Snarl*>& child_boundary_index) {

    // Find paths left from the given visit to the start or end of the given
    // ultrabubble.

    // Right now just finds the shortest path in nodes.

    // Holds partial paths we want to return, with their lengths in visits.
    set<pair<size_t, list<Visit>>> to_return;

    // Do a BFS

    // This holds the parent of each Visit in the queue, back to the initial
    // rooting visit.
    map<Visit, Visit> parents;

    // This holds all the visits we need to look at.
    list<Visit> queue {root};

    while(!queue.empty()) {
        // Keep going until we've emptied the queue

        // Dequeue a visit to continue from.
        Visit to_extend_from = queue.front();
        queue.pop_front();

        if (to_extend_from == site.start() || to_extend_from == site.end()) {
            // We're done! Do a trace back.

            // Fill in this path
            list<Visit> path;

            // With this cursor
            Visit v = to_extend_from;

            while (v != root) {
                // Until we get to the root, put this node on the path and get
                // its parent.
                path.push_back(v);
                v = parents.at(v);
            }
            // We hit the root so add it to the path too.
            path.push_back(v);

            // Add the path and its length to the list to return
            to_return.insert(make_pair(path.size(), path));

            // And go ahead and return it right now (since it's maximally short)
            return to_return;
        } else {
            // We haven't reached a boundary, so just keep searching left from
            // this visit.
            vector<Visit> neighbors = visits_left(to_extend_from, augmented.graph, child_boundary_index);

            // TODO: implement
            // For each thing off the left

            // Check the edge to it to make sure it has coverage

            // If the next thing is a node, check it to make sure it has coverage

            // If the next thing is a snarl, maybe check its attached boundary node to make sure it has coverage?

            // If it checks out, queue each neighbor with this visit as its parent

        }

    }

    // We should never get here becuase we should eventually reach the end of
    // the site we're searching.
    throw runtime_error("Got lost in site in search_left!");
}

set<pair<size_t, list<Visit>>> NestedTraversalFinder::search_right(Visit root, const Snarl& site,
    const map<NodeTraversal, const Snarl*>& child_boundary_index) {

    // Make a backwards version of the root
    Visit root_rev = root;
    root_rev.set_backward(!root_rev.backward());

    // Look left from the backward version of the root
    auto to_convert = search_left(root_rev, site, child_boundary_index);

    // Since we can't modify set records in place, we need to do a copy
    set<pair<size_t, list<Visit>>> to_return;

    for(auto length_and_path : to_convert) {
        // Flip every path to run the other way
        length_and_path.second.reverse();
        for(auto& visit : length_and_path.second) {
            // And invert the orientation of every visit in the path in place.
            visit.set_backward(!visit.backward());
        }
        // Stick it in the new set
        to_return.emplace(move(length_and_path));
    }

    return to_return;
}

}
<commit_msg>Add more implementations<commit_after>/// \file nested_traversal_finder.cpp: Contains implementation for a TraversalFinder that works on non-leaf Snarls.

#include "genotypekit.hpp"

namespace vg {

using namespace std;

/**
 * This TraversalFinder emits at least one traversal representing every node,
 * edge, or child Snarl. Only works on ultrabubbles, and so does not handle
 * cycles.
 */
class NestedTraversalFinder : public TraversalFinder {

protected:
    /// The annotated, augmented graph we're finding traversals in
    AugmentedGraph& augmented;
    /// The SnarlManager managiung the snarls we use
    SnarlManager& snarl_manager;

    /**
     * Given an edge or node or child snarl in the augmented graph, look out
     * from the edge or node or child in both directions to find a shortest
     * bubble connecting the start and end of the given site.
     *
     * Exactly one of edge and node and child must be non-null.
     *
     * Return the found traversal as a vector of Visits, including anchoring
     * Visits to the site's start and end nodes. Also return the minimum support
     * found on any edge or node in the bubble that is not contained within a
     * child.
     *
     * If there is no path with any support, returns a zero Support and an empty
     * vector.
     */
    pair<Support, vector<Visit>> find_bubble(Node* node, Edge* edge, Snarl* child,
        const Snarl& site, const map<NodeTraversal, const Snarl*>& child_boundary_index);

    /**
     * Get the minimum support of all nodes and edges used in the given path
     * that are not inside child snarls.
     */
    Support min_support_in_path(const vector<Visit>& path);

    /**
     * Do a breadth-first search left from the given node traversal, and return
     * lengths (in visits) and paths starting at the given node and ending on
     * the given indexed path. Refuses to visit nodes with no support.
     *
     * Lengths are included so that shorter paths sort first.
     */
    set<pair<size_t, list<Visit>>> search_left(const Visit& root, const Snarl& site,
        const map<NodeTraversal, const Snarl*>& child_boundary_index);

    /**
     * Do a breadth-first search right from the given node traversal, and return
     * lengths (in visits) and paths starting at the given node and ending on
     * the given indexed path.
     *
     * Lengths are included so that shorter paths sort first.
     */
    set<pair<size_t, list<Visit>>> search_right(const Visit& root, const Snarl& site,
        const map<NodeTraversal, const Snarl*>& child_boundary_index);

    /**
     * Get the length of a path through nodes and child sites, in base pairs.
     * Ignores any bases inside child sites.
     */
    size_t bp_length(const list<Visit>& path);

public:

    NestedTraversalFinder(AugmentedGraph& augmented, SnarlManager& snarl_manager);

    /// Should we emit verbose debugging info?
    bool verbose = false;

    virtual ~NestedTraversalFinder() = default;

    /**
     * Find traversals to cover the nodes, edges, and children of the snarl.
     * Always emits the primary path traversal first, if applicable.
     */
    virtual vector<SnarlTraversal> find_traversals(const Snarl& site);

};

NestedTraversalFinder::NestedTraversalFinder(AugmentedGraph& augmented,
    SnarlManager& snarl_manager) : augmented(augmented), snarl_manager(snarl_manager) {

    // Nothing to do!

}

vector<SnarlTraversal> NestedTraversalFinder::find_traversals(const Snarl& site) {

    // For each node, edge, and child snarl, try and find a traversal that visits it
}

pair<Support, vector<Visit>> NestedTraversalFinder::find_bubble(Node* node, Edge* edge, Snarl* child, const Snarl& site, const map<NodeTraversal, const Snarl*>& child_boundary_index) {

    // What are we going to find our left and right path halves based on?
    Visit left_visit;
    Visit right_visit;

    if(edge != nullptr) {
        // Be edge-based

        // TODO: if the edge has no support, don't go looking for a path

        // Find the nodes at the ends of the edges. Look at them traversed in the
        // edge's local orientation.
        left_visit.set_node_id(edge->from());
        left_visit.set_backward(edge->from_start());

        right_visit.set_node_id(edge->to());
        right_visit.set_backward(edge->to_end());
    } else if (node != nullptr) {
        // Be node-based. Both roots are the same visit
        left_visit.set_node_id(node->id());
        right_visit = left_visit;
    } else {
        // We must be child-based
        assert(child != nullptr);

        // Both roots are the same child snarl visit
        transfer_boundary_info(*child, *left_visit.mutable_snarl());
        right_visit = left_visit;
    }

    // Find paths on both sides, anchored into the outside of our snarl. Returns
    // path lengths (in visits) and paths in pairs in a set.
    auto left_paths = search_left(left_visit, site, child_boundary_index);
    auto right_paths = search_right(right_visit, site, child_boundary_index);

    // Now splice the paths together to get max support.

    // TODO: implement that. For now just get any path with nonzero support.

    for (auto& left : left_paths) {
        for (auto& right : right_paths) {
            // Splice together the first path from each set

            // Start witht he whole left path
            vector<Visit> spliced_path {left.second.begin(), left.second.end()};

            auto it = right.second.begin();
            if (it != right.second.end() && !spliced_path.empty() && *it == spliced_path.back()) {
                // If the right path starts with the same visit the left path ended with, skip it.
                ++it;
            }

            // Copy over the rest of the right side path
            copy(it, right.second.end(), back_inserter(spliced_path));

            // Return this spliced-together path with its support
            return make_pair(min_support_in_path(spliced_path), spliced_path);

        }
    }

    // If we get here there's no pair of paths to combine. Return the zero value.
    return pair<Support, vector<Visit>>();

}

Support NestedTraversalFinder::min_support_in_path(const vector<Visit>& path) {

    if (path.empty()) {
        return Support();
    }
    // We look at the current visit and the next visit so we can think about
    // edges.
    auto cur = path.begin();
    auto next = path.begin();
    ++next;

    // We have a function to get the support for a visit
    function<Support(const Visit&)> support_for_visit = [&](const Visit& v) {
        if (v.node_id()) {
            // This is a node visit
            Node* node = augmented.graph.get_node(v.node_id());

            // Return the support for it, or 0 if it's not in the map.
            return augmented.node_supports.count(node) ? augmented.node_supports.at(node) : Support();
        } else {
            // It's a snarl visit. We assume it goes in one side and out the
            // other.

            // We don't inspect the whole snarl, but we know you have to visit
            // the start and end nodes, so we look at them.
            return support_min(support_for_visit(v.snarl().start()), support_for_visit(v.snarl().end()));
        }
    };

    // Start out with the support for the current visit.
    Support min_support = support_for_visit(*cur);
    for (; next != path.end(); ++cur, ++next) {
        // For each subsequent node next

        // check the node support
        min_support = support_min(min_support, support_for_visit(*next));

        // check the edge support
        Edge* edge = augmented.graph.get_edge(to_left_side(*cur), to_right_side(*next));
        assert(edge != NULL);
        Support edge_support = augmented.edge_supports.count(edge) ? augmented.edge_supports.at(edge) : Support();
        min_support = support_min(min_support, edge_support);
    }

    return min_support;
}

set<pair<size_t, list<Visit>>> NestedTraversalFinder::search_left(const Visit& root, const Snarl& site,
    const map<NodeTraversal, const Snarl*>& child_boundary_index) {

    // Find paths left from the given visit to the start or end of the given
    // ultrabubble.

    // Right now just finds the shortest path in nodes.

    // Holds partial paths we want to return, with their lengths in visits.
    set<pair<size_t, list<Visit>>> to_return;

    // Do a BFS

    // This holds the parent of each Visit in the queue, back to the initial
    // rooting visit.
    map<Visit, Visit> parents;

    // This holds all the visits we need to look at.
    list<Visit> queue {root};

    while(!queue.empty()) {
        // Keep going until we've emptied the queue

        // Dequeue a visit to continue from.
        Visit to_extend_from = queue.front();
        queue.pop_front();

        if (to_extend_from == site.start() || to_extend_from == site.end()) {
            // We're done! Do a trace back.

            // Fill in this path
            list<Visit> path;

            // With this cursor
            Visit v = to_extend_from;

            while (v != root) {
                // Until we get to the root, put this node on the path and get
                // its parent.
                path.push_back(v);
                v = parents.at(v);
            }
            // We hit the root so add it to the path too.
            path.push_back(v);

            // Add the path and its length to the list to return
            to_return.insert(make_pair(path.size(), path));

            // And go ahead and return it right now (since it's maximally short)
            return to_return;
        } else {
            // We haven't reached a boundary, so just keep searching left from
            // this visit.
            vector<Visit> neighbors = visits_left(to_extend_from, augmented.graph, child_boundary_index);

            for (auto& extension : neighbors) {
                // For each thing off the left

                if (parents.count(extension)) {
                    // This next node is already reachable by a path this short or shorter.
                    continue;
                }

                // Check the edge to it to make sure it has coverage
                Edge* edge = augmented.graph.get_edge(to_right_side(extension), to_left_side(to_extend_from));

                if (!augmented.edge_supports.count(edge) || total(augmented.edge_supports.at(edge)) == 0) {
                    // This edge is not supported, so don't explore this extension.
                    continue;
                }

                // Look up the node we're entering (either the snarl boundary or
                // just the node we're going to visit), so we can check to make
                // sure it has coverage.
                Node* node = augmented.graph.get_node(to_right_side(extension).node);

                if (!augmented.node_supports.count(node) || total(augmented.node_supports.at(node)) == 0) {
                    // This node is not supported, so don't explore this extension.
                    continue;
                }

                // If it checks out, queue the neighbor with this visit as its parent
                parents[extension] = to_extend_from;
                queue.push_back(extension);
            }

        }

    }

    // If we get here, no path with any support was found. Return our still-empty set.
    return to_return;
}

set<pair<size_t, list<Visit>>> NestedTraversalFinder::search_right(const Visit& root, const Snarl& site,
    const map<NodeTraversal, const Snarl*>& child_boundary_index) {

    // Make a backwards version of the root
    Visit root_rev = root;
    root_rev.set_backward(!root_rev.backward());

    // Look left from the backward version of the root
    auto to_convert = search_left(root_rev, site, child_boundary_index);

    // Since we can't modify set records in place, we need to do a copy
    set<pair<size_t, list<Visit>>> to_return;

    for(auto length_and_path : to_convert) {
        // Flip every path to run the other way
        length_and_path.second.reverse();
        for(auto& visit : length_and_path.second) {
            // And invert the orientation of every visit in the path in place.
            visit.set_backward(!visit.backward());
        }
        // Stick it in the new set
        to_return.emplace(move(length_and_path));
    }

    return to_return;
}

}
<|endoftext|>


<commit_before>#include <qcstring.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qtimer.h>

#include <kiconloader.h>

#include "kapplication.h"       // kapp
#include "kdebug.h"

#include "event.h"

#include "karmutility.h"
#include "task.h"
#include "taskview.h"
#include "preferences.h"

const int gSecondsPerMinute = 60;

QPtrVector<QPixmap> *Task::icons = 0;

Task::Task( const QString& taskName, long minutes, long sessionTime,
            DesktopList desktops, TaskView *parent)
  : QObject(), QListViewItem(parent)
{
  init(taskName, minutes, sessionTime, desktops, 0);
}

Task::Task( const QString& taskName, long minutes, long sessionTime,
            DesktopList desktops, Task *parent)
  : QObject(), QListViewItem(parent)
{
  init(taskName, minutes, sessionTime, desktops, 0);
}

Task::Task( KCal::Todo* todo, TaskView* parent )
  : QObject(), QListViewItem( parent )
{
  long minutes = 0;
  QString name;
  long sessionTime = 0;
  int percent_complete = 0;
  DesktopList desktops;

  parseIncidence(todo, minutes, sessionTime, name, desktops, percent_complete);
  init(name, minutes, sessionTime, desktops, percent_complete);
}

void Task::init( const QString& taskName, long minutes, long sessionTime,
                 DesktopList desktops, int percent_complete)
{
  // If our parent is the taskview then connect our totalTimesChanged
  // signal to its receiver
  if ( ! parent() )
    connect( this, SIGNAL( totalTimesChanged ( long, long ) ),
             listView(), SLOT( taskTotalTimesChanged( long, long) ));

  connect( this, SIGNAL( deletingTask( Task* ) ),
           listView(), SLOT( deletingTask( Task* ) ));

  if (icons == 0) {
    icons = new QPtrVector<QPixmap>(8);
    for (int i=0; i<8; i++)
    {
      QPixmap *icon = new QPixmap();
      QString name;
      name.sprintf("watch-%d.xpm",i);
      *icon = UserIcon(name);
      icons->insert(i,icon);
    }
  }

  //kdDebug(5970) << "Task::init(" << taskName << ", " << minutes << ", "
  //  << sessionTime << ", desktops)" << endl;

  _name = taskName.stripWhiteSpace();
  _lastStart = QDateTime::currentDateTime();
  _totalTime = _time = minutes;
  _totalSessionTime = _sessionTime = sessionTime;
  noNegativeTimes();
  _timer = new QTimer(this);
  _desktops = desktops;
  connect(_timer, SIGNAL(timeout()), this, SLOT(updateActiveIcon()));
  setPixmap(1, UserIcon(QString::fromLatin1("empty-watch.xpm")));
  _currentPic = 0;
  _percentcomplete = percent_complete;

  update();
  changeParentTotalTimes( _sessionTime, _time);
}

Task::~Task() {
  emit deletingTask(this);
  delete _timer;
}

void Task::setRunning( bool on, KarmStorage* storage )
{
  if ( on ) {
    if (!_timer->isActive()) {
      _timer->start(1000);
      storage->startTimer(this);
      _currentPic=7;
      _lastStart = QDateTime::currentDateTime();
      updateActiveIcon();
    }
  }
  else {
    if (_timer->isActive()) {
      _timer->stop();
      storage->stopTimer(this);
      setPixmap(1, UserIcon(QString::fromLatin1("empty-watch.xpm")));
    }
  }
}

void Task::setUid(QString uid) {
  _uid = uid;
}

bool Task::isRunning() const
{
  return _timer->isActive();
}

void Task::setName( const QString& name, KarmStorage* storage )
{
  kdDebug(5970) << "Task:setName: " << name << endl;

  QString oldname = _name;
  if ( oldname != name ) {
    _name = name;
    storage->setName(this, oldname);
    update();
  }
}

void Task::setPercentComplete(const int percent, KarmStorage *storage)
{
  kdDebug(5970) << "Task::setPercentComplete(" << percent << ", storage): "
    << _uid << endl;

  if (isRunning()) setRunning(false, storage);

  setEnabled(false);
  setOpen(false);

  if (!percent)
    _percentcomplete = 0;
  else if (percent > 100)
    _percentcomplete = 100;
  else if (percent < 0)
    _percentcomplete = 0;
  else
    _percentcomplete = percent;

  // When parent marked as complete, mark all children as complete as well.
  // Complete tasks are not displayed in the task view, so if a parent is
  // marked as complete and some of the children are not, then we get an error
  // message.  KArm actually keep chugging along in this case and displays the
  // child tasks just fine, so an alternative solution is to remove that error
  // message (from KarmStorage::load).  But I think it makes more sense that
  // if you mark a parent task as complete, then all children should be
  // complete as well.
  //
  // This behavior is consistent with KOrganizer (as of 2003-09-24).
  if (_percentcomplete == 100)
  {
    for (Task* child= this->firstChild(); child; child = child->nextSibling())
      child->setPercentComplete(_percentcomplete, storage);
  }
}

bool Task::isComplete() { return _percentcomplete == 100; }

void Task::removeFromView()
{
  for (Task* child= this->firstChild(); child; child= child->nextSibling())
    child->removeFromView();
  delete this;
}

void Task::setDesktopList ( DesktopList desktopList )
{
  _desktops = desktopList;
}

void Task::changeTime( long minutes, KarmStorage* storage )
{
  changeTimes( minutes, minutes, storage);
}

void Task::changeTimes( long minutesSession, long minutes, KarmStorage* storage)
{
  if( minutesSession != 0 || minutes != 0)
  {
    _sessionTime += minutesSession;
    _time += minutes;
    if ( storage ) storage->changeTime(this, minutes * gSecondsPerMinute);
    noNegativeTimes();
    changeTotalTimes( minutesSession, minutes );
  }
}

void Task::changeTotalTimes( long minutesSession, long minutes )
{
  //kdDebug(5970)
  //  << "Task::changeTotalTimes(" << minutesSession << ", "
  //  << minutes << ") for " << name() << endl;

  _totalSessionTime += minutesSession;
  _totalTime += minutes;
  noNegativeTimes();
  update();
  changeParentTotalTimes( minutesSession, minutes );
}

void Task::resetTimes()
{
  _totalSessionTime -= _sessionTime;
  _totalTime -= _time;
  changeParentTotalTimes( -_sessionTime, -_time);
  _sessionTime = 0;
  _time = 0;
  update();
}

void Task::changeParentTotalTimes( long minutesSession, long minutes )
{
  //kdDebug(5970)
  //  << "Task::changeParentTotalTimes(" << minutesSession << ", "
  //  << minutes << ") for " << name() << endl;

  if ( isRoot() )
    emit totalTimesChanged( minutesSession, minutes );
  else
    parent()->changeTotalTimes( minutesSession, minutes );
}

bool Task::remove( QPtrList<Task>& activeTasks, KarmStorage* storage)
{
  kdDebug(5970) << "Task::remove: " << _name << endl;

  bool ok = true;

  storage->removeTask(this);

  if( isRunning() ) setRunning( false, storage );

  for (Task* child = this->firstChild(); child; child = child->nextSibling())
  {
    if (child->isRunning())
      child->setRunning(false, storage);
    child->remove(activeTasks, storage);
  }

  changeParentTotalTimes( -_sessionTime, -_time);

  return ok;
}

void Task::updateActiveIcon()
{
  _currentPic = (_currentPic+1) % 8;
  setPixmap(1, *(*icons)[_currentPic]);
}

void Task::noNegativeTimes()
{
  if ( _time < 0 )
      _time = 0;
  if ( _sessionTime < 0 )
      _sessionTime = 0;
}

QString Task::fullName() const
{
  if (isRoot())
    return name();
  else
    return parent()->fullName() + QString::fromLatin1("/") + name();
}

KCal::Todo* Task::asTodo(KCal::Todo* todo) const
{

  todo->setSummary( name() );

  // Note: if the date start is empty, the KOrganizer GUI will have the
  // checkbox blank, but will prefill the todo's starting datetime to the
  // time the file is opened.
  // todo->setDtStart( current );

  todo->setCustomProperty( kapp->instanceName(),
      QCString( "totalTaskTime" ), QString::number( _time ) );
  todo->setCustomProperty( kapp->instanceName(),
      QCString( "totalSessionTime" ), QString::number( _sessionTime) );

  if (getDesktopStr().isEmpty())
    todo->removeCustomProperty(kapp->instanceName(), QCString("desktopList"));
  else
    todo->setCustomProperty( kapp->instanceName(),
        QCString( "desktopList" ), getDesktopStr() );

  todo->setOrganizer( Preferences::instance()->userRealName() );

  todo->setPercentComplete(_percentcomplete);

  return todo;
}

bool Task::parseIncidence( KCal::Incidence* incident, long& minutes,
    long& sessionMinutes, QString& name, DesktopList& desktops,
    int& percent_complete )
{
  bool ok;

  name = incident->summary();
  _uid = incident->uid();

  _comment = incident->description();

  ok = false;
  minutes = incident->customProperty( kapp->instanceName(),
      QCString( "totalTaskTime" )).toInt( &ok );
  if ( !ok )
    minutes = 0;

  ok = false;
  sessionMinutes = incident->customProperty( kapp->instanceName(),
      QCString( "totalSessionTime" )).toInt( &ok );
  if ( !ok )
    sessionMinutes = 0;

  QString desktopList = incident->customProperty( kapp->instanceName(),
      QCString( "desktopList" ) );
  QStringList desktopStrList = QStringList::split( QString::fromLatin1(","),
      desktopList );
  desktops.clear();

  for ( QStringList::iterator iter = desktopStrList.begin();
        iter != desktopStrList.end();
        ++iter ) {
    int desktopInt = (*iter).toInt( &ok );
    if ( ok ) {
      desktops.push_back( desktopInt );
    }
  }

  percent_complete = static_cast<KCal::Todo*>(incident)->percentComplete();

  //kdDebug(5970) << "Task::parseIncidence: "
  //  << name << ", Minutes: " << minutes
  //  <<  ", desktop: " << desktopList << endl;

  return true;
}

QString Task::getDesktopStr() const
{
  if ( _desktops.empty() )
    return QString();

  QString desktopstr;
  for ( DesktopList::const_iterator iter = _desktops.begin();
        iter != _desktops.end();
        ++iter ) {
    desktopstr += QString::number( *iter ) + QString::fromLatin1( "," );
  }
  desktopstr.remove( desktopstr.length() - 1, 1 );
  return desktopstr;
}

void Task::cut()
{
  //kdDebug(5970) << "Task::cut - " << name() << endl;
  changeParentTotalTimes( -_totalSessionTime, -_totalTime);
  if ( ! parent())
    listView()->takeItem(this);
  else
    parent()->takeItem(this);
}

void Task::move(Task* destination)
{
  cut();
  paste(destination);
}

void Task::paste(Task* destination)
{
  destination->insertItem(this);
  changeParentTotalTimes( _totalSessionTime, _totalTime);
}

void Task::update()
{
  setText(0, _name);
  setText(1, formatTime(_sessionTime));
  setText(2, formatTime(_time));
  setText(3, formatTime(_totalSessionTime));
  setText(4, formatTime(_totalTime));
}

void Task::addComment( QString comment, KarmStorage* storage )
{
  _comment = _comment + QString::fromLatin1("\n") + comment;
  storage->addComment(this, comment);
}

QString Task::comment() const
{
  return _comment;
}

int Task::compare ( QListViewItem * i, int col, bool ascending ) const
{
  long thistime = 0;
  long thattime = 0;
  Task *task = static_cast<Task*>(i);

  switch ( col )
  {
    case 1:
      thistime = _sessionTime;
      thattime = task->sessionTime();
      break;
    case 2:
      thistime = _time;
      thattime = task->time();
      break;
    case 3:
      thistime = _totalSessionTime;
      thattime = task->totalSessionTime();
      break;
    case 4:
      thistime = _totalTime;
      thattime = task->totalTime();
      break;
    default:
      return key(col, ascending).localeAwareCompare( i->key(col, ascending) );
  }

  if ( thistime < thattime ) return -1;
  if ( thistime > thattime ) return 1;
  return 0;

}

#include "task.moc"
<commit_msg>Allow negative task times.  Fixes data loss bug.<commit_after>#include <qcstring.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qtimer.h>

#include <kiconloader.h>

#include "kapplication.h"       // kapp
#include "kdebug.h"

#include "event.h"

#include "karmutility.h"
#include "task.h"
#include "taskview.h"
#include "preferences.h"

const int gSecondsPerMinute = 60;

QPtrVector<QPixmap> *Task::icons = 0;

Task::Task( const QString& taskName, long minutes, long sessionTime,
            DesktopList desktops, TaskView *parent)
  : QObject(), QListViewItem(parent)
{
  init(taskName, minutes, sessionTime, desktops, 0);
}

Task::Task( const QString& taskName, long minutes, long sessionTime,
            DesktopList desktops, Task *parent)
  : QObject(), QListViewItem(parent)
{
  init(taskName, minutes, sessionTime, desktops, 0);
}

Task::Task( KCal::Todo* todo, TaskView* parent )
  : QObject(), QListViewItem( parent )
{
  long minutes = 0;
  QString name;
  long sessionTime = 0;
  int percent_complete = 0;
  DesktopList desktops;

  parseIncidence(todo, minutes, sessionTime, name, desktops, percent_complete);
  init(name, minutes, sessionTime, desktops, percent_complete);
}

void Task::init( const QString& taskName, long minutes, long sessionTime,
                 DesktopList desktops, int percent_complete)
{
  // If our parent is the taskview then connect our totalTimesChanged
  // signal to its receiver
  if ( ! parent() )
    connect( this, SIGNAL( totalTimesChanged ( long, long ) ),
             listView(), SLOT( taskTotalTimesChanged( long, long) ));

  connect( this, SIGNAL( deletingTask( Task* ) ),
           listView(), SLOT( deletingTask( Task* ) ));

  if (icons == 0) {
    icons = new QPtrVector<QPixmap>(8);
    for (int i=0; i<8; i++)
    {
      QPixmap *icon = new QPixmap();
      QString name;
      name.sprintf("watch-%d.xpm",i);
      *icon = UserIcon(name);
      icons->insert(i,icon);
    }
  }

  //kdDebug(5970) << "Task::init(" << taskName << ", " << minutes << ", "
  //  << sessionTime << ", desktops)" << endl;

  _name = taskName.stripWhiteSpace();
  _lastStart = QDateTime::currentDateTime();
  _totalTime = _time = minutes;
  _totalSessionTime = _sessionTime = sessionTime;
  _timer = new QTimer(this);
  _desktops = desktops;
  connect(_timer, SIGNAL(timeout()), this, SLOT(updateActiveIcon()));
  setPixmap(1, UserIcon(QString::fromLatin1("empty-watch.xpm")));
  _currentPic = 0;
  _percentcomplete = percent_complete;

  update();
  changeParentTotalTimes( _sessionTime, _time);
}

Task::~Task() {
  emit deletingTask(this);
  delete _timer;
}

void Task::setRunning( bool on, KarmStorage* storage )
{
  if ( on ) {
    if (!_timer->isActive()) {
      _timer->start(1000);
      storage->startTimer(this);
      _currentPic=7;
      _lastStart = QDateTime::currentDateTime();
      updateActiveIcon();
    }
  }
  else {
    if (_timer->isActive()) {
      _timer->stop();
      storage->stopTimer(this);
      setPixmap(1, UserIcon(QString::fromLatin1("empty-watch.xpm")));
    }
  }
}

void Task::setUid(QString uid) {
  _uid = uid;
}

bool Task::isRunning() const
{
  return _timer->isActive();
}

void Task::setName( const QString& name, KarmStorage* storage )
{
  kdDebug(5970) << "Task:setName: " << name << endl;

  QString oldname = _name;
  if ( oldname != name ) {
    _name = name;
    storage->setName(this, oldname);
    update();
  }
}

void Task::setPercentComplete(const int percent, KarmStorage *storage)
{
  kdDebug(5970) << "Task::setPercentComplete(" << percent << ", storage): "
    << _uid << endl;

  if (isRunning()) setRunning(false, storage);

  setEnabled(false);
  setOpen(false);

  if (!percent)
    _percentcomplete = 0;
  else if (percent > 100)
    _percentcomplete = 100;
  else if (percent < 0)
    _percentcomplete = 0;
  else
    _percentcomplete = percent;

  // When parent marked as complete, mark all children as complete as well.
  // Complete tasks are not displayed in the task view, so if a parent is
  // marked as complete and some of the children are not, then we get an error
  // message.  KArm actually keep chugging along in this case and displays the
  // child tasks just fine, so an alternative solution is to remove that error
  // message (from KarmStorage::load).  But I think it makes more sense that
  // if you mark a parent task as complete, then all children should be
  // complete as well.
  //
  // This behavior is consistent with KOrganizer (as of 2003-09-24).
  if (_percentcomplete == 100)
  {
    for (Task* child= this->firstChild(); child; child = child->nextSibling())
      child->setPercentComplete(_percentcomplete, storage);
  }
}

bool Task::isComplete() { return _percentcomplete == 100; }

void Task::removeFromView()
{
  for (Task* child= this->firstChild(); child; child= child->nextSibling())
    child->removeFromView();
  delete this;
}

void Task::setDesktopList ( DesktopList desktopList )
{
  _desktops = desktopList;
}

void Task::changeTime( long minutes, KarmStorage* storage )
{
  changeTimes( minutes, minutes, storage);
}

void Task::changeTimes( long minutesSession, long minutes, KarmStorage* storage)
{
  if( minutesSession != 0 || minutes != 0)
  {
    _sessionTime += minutesSession;
    _time += minutes;
    if ( storage ) storage->changeTime(this, minutes * gSecondsPerMinute);
    changeTotalTimes( minutesSession, minutes );
  }
}

void Task::changeTotalTimes( long minutesSession, long minutes )
{
  //kdDebug(5970)
  //  << "Task::changeTotalTimes(" << minutesSession << ", "
  //  << minutes << ") for " << name() << endl;

  _totalSessionTime += minutesSession;
  _totalTime += minutes;
  update();
  changeParentTotalTimes( minutesSession, minutes );
}

void Task::resetTimes()
{
  _totalSessionTime -= _sessionTime;
  _totalTime -= _time;
  changeParentTotalTimes( -_sessionTime, -_time);
  _sessionTime = 0;
  _time = 0;
  update();
}

void Task::changeParentTotalTimes( long minutesSession, long minutes )
{
  //kdDebug(5970)
  //  << "Task::changeParentTotalTimes(" << minutesSession << ", "
  //  << minutes << ") for " << name() << endl;

  if ( isRoot() )
    emit totalTimesChanged( minutesSession, minutes );
  else
    parent()->changeTotalTimes( minutesSession, minutes );
}

bool Task::remove( QPtrList<Task>& activeTasks, KarmStorage* storage)
{
  kdDebug(5970) << "Task::remove: " << _name << endl;

  bool ok = true;

  storage->removeTask(this);

  if( isRunning() ) setRunning( false, storage );

  for (Task* child = this->firstChild(); child; child = child->nextSibling())
  {
    if (child->isRunning())
      child->setRunning(false, storage);
    child->remove(activeTasks, storage);
  }

  changeParentTotalTimes( -_sessionTime, -_time);

  return ok;
}

void Task::updateActiveIcon()
{
  _currentPic = (_currentPic+1) % 8;
  setPixmap(1, *(*icons)[_currentPic]);
}

QString Task::fullName() const
{
  if (isRoot())
    return name();
  else
    return parent()->fullName() + QString::fromLatin1("/") + name();
}

KCal::Todo* Task::asTodo(KCal::Todo* todo) const
{

  todo->setSummary( name() );

  // Note: if the date start is empty, the KOrganizer GUI will have the
  // checkbox blank, but will prefill the todo's starting datetime to the
  // time the file is opened.
  // todo->setDtStart( current );

  todo->setCustomProperty( kapp->instanceName(),
      QCString( "totalTaskTime" ), QString::number( _time ) );
  todo->setCustomProperty( kapp->instanceName(),
      QCString( "totalSessionTime" ), QString::number( _sessionTime) );

  if (getDesktopStr().isEmpty())
    todo->removeCustomProperty(kapp->instanceName(), QCString("desktopList"));
  else
    todo->setCustomProperty( kapp->instanceName(),
        QCString( "desktopList" ), getDesktopStr() );

  todo->setOrganizer( Preferences::instance()->userRealName() );

  todo->setPercentComplete(_percentcomplete);

  return todo;
}

bool Task::parseIncidence( KCal::Incidence* incident, long& minutes,
    long& sessionMinutes, QString& name, DesktopList& desktops,
    int& percent_complete )
{
  bool ok;

  name = incident->summary();
  _uid = incident->uid();

  _comment = incident->description();

  ok = false;
  minutes = incident->customProperty( kapp->instanceName(),
      QCString( "totalTaskTime" )).toInt( &ok );
  if ( !ok )
    minutes = 0;

  ok = false;
  sessionMinutes = incident->customProperty( kapp->instanceName(),
      QCString( "totalSessionTime" )).toInt( &ok );
  if ( !ok )
    sessionMinutes = 0;

  QString desktopList = incident->customProperty( kapp->instanceName(),
      QCString( "desktopList" ) );
  QStringList desktopStrList = QStringList::split( QString::fromLatin1(","),
      desktopList );
  desktops.clear();

  for ( QStringList::iterator iter = desktopStrList.begin();
        iter != desktopStrList.end();
        ++iter ) {
    int desktopInt = (*iter).toInt( &ok );
    if ( ok ) {
      desktops.push_back( desktopInt );
    }
  }

  percent_complete = static_cast<KCal::Todo*>(incident)->percentComplete();

  //kdDebug(5970) << "Task::parseIncidence: "
  //  << name << ", Minutes: " << minutes
  //  <<  ", desktop: " << desktopList << endl;

  return true;
}

QString Task::getDesktopStr() const
{
  if ( _desktops.empty() )
    return QString();

  QString desktopstr;
  for ( DesktopList::const_iterator iter = _desktops.begin();
        iter != _desktops.end();
        ++iter ) {
    desktopstr += QString::number( *iter ) + QString::fromLatin1( "," );
  }
  desktopstr.remove( desktopstr.length() - 1, 1 );
  return desktopstr;
}

void Task::cut()
{
  //kdDebug(5970) << "Task::cut - " << name() << endl;
  changeParentTotalTimes( -_totalSessionTime, -_totalTime);
  if ( ! parent())
    listView()->takeItem(this);
  else
    parent()->takeItem(this);
}

void Task::move(Task* destination)
{
  cut();
  paste(destination);
}

void Task::paste(Task* destination)
{
  destination->insertItem(this);
  changeParentTotalTimes( _totalSessionTime, _totalTime);
}

void Task::update()
{
  setText(0, _name);
  setText(1, formatTime(_sessionTime));
  setText(2, formatTime(_time));
  setText(3, formatTime(_totalSessionTime));
  setText(4, formatTime(_totalTime));
}

void Task::addComment( QString comment, KarmStorage* storage )
{
  _comment = _comment + QString::fromLatin1("\n") + comment;
  storage->addComment(this, comment);
}

QString Task::comment() const
{
  return _comment;
}

int Task::compare ( QListViewItem * i, int col, bool ascending ) const
{
  long thistime = 0;
  long thattime = 0;
  Task *task = static_cast<Task*>(i);

  switch ( col )
  {
    case 1:
      thistime = _sessionTime;
      thattime = task->sessionTime();
      break;
    case 2:
      thistime = _time;
      thattime = task->time();
      break;
    case 3:
      thistime = _totalSessionTime;
      thattime = task->totalSessionTime();
      break;
    case 4:
      thistime = _totalTime;
      thattime = task->totalTime();
      break;
    default:
      return key(col, ascending).localeAwareCompare( i->key(col, ascending) );
  }

  if ( thistime < thattime ) return -1;
  if ( thistime > thattime ) return 1;
  return 0;

}

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