<commit_before>/*********************************************************************/
/*	EESchema - edition des librairies: Edition des champs ( Fields ) */
/*********************************************************************/

/*	Fichier libfield.cpp	*/

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "drawtxt.h"
#include "confirm.h"

#include "program.h"
#include "libcmp.h"
#include "general.h"

#include "protos.h"

#include "wx/spinctrl.h"

/* Routines locales */
static void     ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );

/* if the field is the reference, return reference like schematic, i.e U -> U? or U?A
 * or the field text for others
 */
static wxString ReturnFieldFullText( LibDrawField* aField );

/* Variables locales */

extern int     CurrentUnit;
static wxPoint StartCursor, LastTextPosition;

/***********************************************************/
static void ExitMoveField( WinEDA_DrawPanel* Panel, wxDC* DC )
/***********************************************************/
{
    Panel->ManageCurseur = NULL;
    Panel->ForceCloseManageCurseur = NULL;
    if( CurrentDrawItem == NULL )
        return;

    wxPoint             curpos;
    curpos = Panel->GetScreen()->m_Curseur;
    Panel->GetScreen()->m_Curseur = StartCursor;
    ShowMoveField( Panel, DC, TRUE );
    Panel->GetScreen()->m_Curseur = curpos;
    CurrentDrawItem->m_Flags = 0;

    CurrentDrawItem = NULL;
}

/****************************************************************************/
void WinEDA_LibeditFrame::StartMoveField( wxDC* DC, LibDrawField* field )
/****************************************************************************/
/* Initialise le deplacement d'un champ ( ref ou Name) */
{
    wxPoint startPos;

    if( (CurrentLibEntry == NULL) || ( field == NULL ) )
        return;
    CurrentDrawItem  = field;
    LastTextPosition = field->m_Pos;
    CurrentDrawItem->m_Flags |= IS_MOVED;

    startPos.x = LastTextPosition.x;
    startPos.y = -LastTextPosition.y;
    DrawPanel->CursorOff( DC );
    GetScreen()->m_Curseur = startPos;
    DrawPanel->MouseToCursorSchema();

    DrawPanel->ManageCurseur = ShowMoveField;
    DrawPanel->ForceCloseManageCurseur = ExitMoveField;
    DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
    StartCursor = GetScreen()->m_Curseur;

    DrawPanel->CursorOn( DC );
}

/* if the field is the reference, return reference like schematic, i.e U -> U? or U?A
 * or the field text for others
 */
static wxString ReturnFieldFullText( LibDrawField* aField )
{
    if( aField->m_FieldId != REFERENCE )
        return aField->m_Text;

    wxString text = aField->m_Text;

    if( CurrentLibEntry->m_UnitCount > 1 )
    {
#if defined(KICAD_GOST)
        text.Printf( wxT( "%s?.%c" ),
                     aField->m_Text.GetData(), CurrentUnit + '1' - 1 );
#else

        text.Printf( wxT( "%s?%c" ),
                     aField->m_Text.GetData(), CurrentUnit + 'A' - 1 );
#endif
    }
    else
        text << wxT( "?" );

    return text;
}

/*****************************************************************/
/* Routine d'affichage du texte 'Field' en cours de deplacement. */
/*	Routine normalement attachee au curseur						*/
/*****************************************************************/
static void ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
{
    int           color;
    LibDrawField* Field = (LibDrawField*) CurrentDrawItem;

    if( (CurrentLibEntry == NULL) || (Field == NULL) )
        return;

    switch( Field->m_FieldId )
    {
    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    wxString text = ReturnFieldFullText( Field );

    int      TransMat[2][2];
    TransMat[0][0] = 1; TransMat[1][1] = -1;
    TransMat[1][0] = TransMat[0][1] = 0;

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;
    if( erase )
        Field->Draw( panel, DC, wxPoint( 0, 0 ),
                     color,
                     g_XorMode, &text, TransMat );

    LastTextPosition.x = panel->GetScreen()->m_Curseur.x;
    LastTextPosition.y = -panel->GetScreen()->m_Curseur.y;

    Field->m_Pos = LastTextPosition;

    Field->Draw( panel, DC, wxPoint( 0, 0 ),
                 color,
                 g_XorMode, &text, TransMat );
}

/*******************************************************************/
void WinEDA_LibeditFrame::PlaceField( wxDC* DC, LibDrawField* Field )
/*******************************************************************/
{
    EDA_Colors color;

    if( Field == NULL )
        return;

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    Field->m_Flags = 0;

    if( (Field->m_Attributs & TEXT_NO_VISIBLE) != 0 )
        color = DARKGRAY;
    Field->m_Pos.x = GetScreen()->m_Curseur.x;
    Field->m_Pos.y = -GetScreen()->m_Curseur.y;
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );
    DrawPanel->CursorOff( DC );

    GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
                     Field->m_Italic, Field->m_Bold);

    DrawPanel->CursorOn( DC );

    GetScreen()->SetModify();
    DrawPanel->ManageCurseur = NULL;
    DrawPanel->ForceCloseManageCurseur = NULL;
    CurrentDrawItem = NULL;
}

/******************************************************************/
void WinEDA_LibeditFrame::EditField( wxDC* DC, LibDrawField* Field )
/******************************************************************/
{
    wxString   Text;
    wxString   title;
    EDA_Colors color;
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );

    if( Field == NULL )
        return;

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        title = wxT( "Reference:" );
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        title = wxT( "Component Name / Value:" );
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;

    Text = Field->m_Text;
    Get_Message( title, _( "Edit field" ), Text, this );
    Text.Replace( wxT( " " ), wxT( "_" ) );

    /* If the value is changed, this is equivalent to create a new component from the old one
     * So we must check for an existing alias of this "new" component
     * and change the value only if there is no existing alias with the same name
     * for this component
     */
    if( Field->m_FieldId == VALUE )
    {
        /* test for an existing name in alias list: */
        for( unsigned ii = 0; ii < CurrentLibEntry->m_AliasList.GetCount(); ii += ALIAS_NEXT )
        {
            wxString aliasname = CurrentLibEntry->m_AliasList[ii + ALIAS_NAME];
            if( Text.CmpNoCase( aliasname ) == 0 )
            {
                DisplayError( this,
                              _( "This name is an existing alias of the component\nAborting" ), 10 );
                return;
            }
        }
    }

    GRSetDrawMode( DC, g_XorMode );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    if( !Text.IsEmpty() )
    {
        SaveCopyInUndoList( CurrentLibEntry );
        Field->m_Text = Text;
    }
    else
        DisplayError( this, _( "No new text: no change" ) );

    if( Field->m_Flags == 0 )
        GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    GetScreen()->SetModify();

    if( Field->m_FieldId == VALUE )
        ReCreateHToolbar();
}

/********************************************************************/
void WinEDA_LibeditFrame::RotateField( wxDC* DC, LibDrawField* Field )
/********************************************************************/

/* Routine de modification de l'orientation ( Horiz ou Vert. ) du champ.
 * si un champ est en cours d'edition, modif de celui ci.
 * sinon Modif du champ pointe par la souris
 */
{
    EDA_Colors color;

    if( Field == NULL )
        return;

    GetScreen()->SetModify();

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( (Field->m_Attributs & TEXT_NO_VISIBLE) != 0 )
        color = DARKGRAY;

    DrawPanel->CursorOff( DC );

    GRSetDrawMode( DC, g_XorMode );
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    if( Field->m_Orient )
        Field->m_Orient = 0;
    else
        Field->m_Orient = 1;

    if( Field->m_Flags == 0 )
        GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);
    DrawPanel->CursorOn( DC );
}

/****************************************************************************/
LibDrawField* WinEDA_LibeditFrame::LocateField( EDA_LibComponentStruct* LibEntry )
/****************************************************************************/

/* Locate the component fiels (ref, name or auxiliary fields) under the mouse cursor
 * return:
 *     pointer on the field (or NULL )
 */
{
    wxPoint refpos;

    refpos.x = GetScreen()->m_Curseur.x;
    refpos.y = -GetScreen()->m_Curseur.y;  // Y axis is from bottom to top in library
    /* Test reference */
    if( LibEntry->m_Name.HitTest( refpos ) )
        return &LibEntry->m_Name;

    /* Test Prefix */
    if( LibEntry->m_Prefix.HitTest( refpos ) )
        return &LibEntry->m_Prefix;

    /* Localisation des autres fields */
    for( LibDrawField* field = LibEntry->m_Fields;  field;  field = field->Next() )
    {
        if( field->m_Text.IsEmpty() )
            continue;

        if( field->HitTest( refpos ) )
            return field;
    }

    return NULL;
}

/********************************************************************************/
LibEDA_BaseStruct* WinEDA_LibeditFrame::LocateItemUsingCursor()
/********************************************************************************/
{
    LibEDA_BaseStruct* DrawEntry = CurrentDrawItem;

    if( CurrentLibEntry == NULL )
        return NULL;

    if( (DrawEntry == NULL) || (DrawEntry->m_Flags == 0) ) // Simple localisation des elements
    {
        DrawEntry = LocatePin(
            GetScreen()->m_Curseur, CurrentLibEntry, CurrentUnit, CurrentConvert );
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = LocateDrawItem( (SCH_SCREEN*) GetScreen(),
                                                         GetScreen()->m_MousePosition,
                                                         CurrentLibEntry, CurrentUnit,
                                                         CurrentConvert, LOCATE_ALL_DRAW_ITEM );
        }
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = LocateDrawItem( (SCH_SCREEN*) GetScreen(),
                                                         GetScreen()->m_Curseur, CurrentLibEntry,
                                                         CurrentUnit,
                                                         CurrentConvert, LOCATE_ALL_DRAW_ITEM );
        }
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = (LibEDA_BaseStruct*)
                                          LocateField( CurrentLibEntry );
        }
    }
    return DrawEntry;
}
<commit_msg>libedit: move field bug<commit_after>/*********************************************************************/
/*	EESchema - edition des librairies: Edition des champs ( Fields ) */
/*********************************************************************/

/*	Fichier libfield.cpp	*/

#include "fctsys.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
#include "drawtxt.h"
#include "confirm.h"

#include "program.h"
#include "libcmp.h"
#include "general.h"

#include "protos.h"

#include "wx/spinctrl.h"

/* Routines locales */
static void     ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );

/* if the field is the reference, return reference like schematic, i.e U -> U? or U?A
 * or the field text for others
 */
static wxString ReturnFieldFullText( LibDrawField* aField );

/* Variables locales */

extern int     CurrentUnit;
static wxPoint StartCursor, LastTextPosition;

/***********************************************************/
static void ExitMoveField( WinEDA_DrawPanel* Panel, wxDC* DC )
/***********************************************************/
{
    Panel->ManageCurseur = NULL;
    Panel->ForceCloseManageCurseur = NULL;
    if( CurrentDrawItem == NULL )
        return;

    wxPoint             curpos;
    curpos = Panel->GetScreen()->m_Curseur;
    Panel->GetScreen()->m_Curseur = StartCursor;
    ShowMoveField( Panel, DC, TRUE );
    Panel->GetScreen()->m_Curseur = curpos;
    CurrentDrawItem->m_Flags = 0;

    CurrentDrawItem = NULL;
}

/****************************************************************************/
void WinEDA_LibeditFrame::StartMoveField( wxDC* DC, LibDrawField* field )
/****************************************************************************/
/* Initialise le deplacement d'un champ ( ref ou Name) */
{
    wxPoint startPos;

    if( (CurrentLibEntry == NULL) || ( field == NULL ) )
        return;
    CurrentDrawItem  = field;
    LastTextPosition = field->m_Pos;
    CurrentDrawItem->m_Flags |= IS_MOVED;

    startPos.x = LastTextPosition.x;
    startPos.y = -LastTextPosition.y;
    DrawPanel->CursorOff( DC );
    GetScreen()->m_Curseur = startPos;
    DrawPanel->MouseToCursorSchema();

    DrawPanel->ManageCurseur = ShowMoveField;
    DrawPanel->ForceCloseManageCurseur = ExitMoveField;
    DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
    StartCursor = GetScreen()->m_Curseur;

    DrawPanel->CursorOn( DC );
}

/* if the field is the reference, return reference like schematic, i.e U -> U? or U?A
 * or the field text for others
 */
static wxString ReturnFieldFullText( LibDrawField* aField )
{
    if( aField->m_FieldId != REFERENCE )
        return aField->m_Text;

    wxString text = aField->m_Text;

    if( CurrentLibEntry->m_UnitCount > 1 )
    {
#if defined(KICAD_GOST)
        text.Printf( wxT( "%s?.%c" ),
                     aField->m_Text.GetData(), CurrentUnit + '1' - 1 );
#else

        text.Printf( wxT( "%s?%c" ),
                     aField->m_Text.GetData(), CurrentUnit + 'A' - 1 );
#endif
    }
    else
        text << wxT( "?" );

    return text;
}

/*****************************************************************/
/* Routine d'affichage du texte 'Field' en cours de deplacement. */
/*	Routine normalement attachee au curseur						*/
/*****************************************************************/
static void ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
{
    int           color;
    LibDrawField* Field = (LibDrawField*) CurrentDrawItem;

    if( (CurrentLibEntry == NULL) || (Field == NULL) )
        return;

    switch( Field->m_FieldId )
    {
    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    wxString text = ReturnFieldFullText( Field );

    int      TransMat[2][2];
    TransMat[0][0] = 1; TransMat[1][1] = -1;
    TransMat[1][0] = TransMat[0][1] = 0;

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;
    if( erase )
        Field->Draw( panel, DC, wxPoint( 0, 0 ),
                     color,
                     g_XorMode, &text, TransMat );

    LastTextPosition.x = panel->GetScreen()->m_Curseur.x;
    LastTextPosition.y = -panel->GetScreen()->m_Curseur.y;

    Field->m_Pos = LastTextPosition;

    Field->Draw( panel, DC, wxPoint( 0, 0 ),
                 color,
                 g_XorMode, &text, TransMat );
}

/*******************************************************************/
void WinEDA_LibeditFrame::PlaceField( wxDC* DC, LibDrawField* Field )
/*******************************************************************/
{
    EDA_Colors color;

    if( Field == NULL )
        return;

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    Field->m_Flags = 0;

    if( (Field->m_Attributs & TEXT_NO_VISIBLE) != 0 )
        color = DARKGRAY;
    Field->m_Pos.x = GetScreen()->m_Curseur.x;
    Field->m_Pos.y = -GetScreen()->m_Curseur.y;
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );
    DrawPanel->CursorOff( DC );

    GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
                     Field->m_Italic, Field->m_Bold);

    DrawPanel->CursorOn( DC );

    GetScreen()->SetModify();
    DrawPanel->ManageCurseur = NULL;
    DrawPanel->ForceCloseManageCurseur = NULL;
    CurrentDrawItem = NULL;
}

/******************************************************************/
void WinEDA_LibeditFrame::EditField( wxDC* DC, LibDrawField* Field )
/******************************************************************/
{
    wxString   Text;
    wxString   title;
    EDA_Colors color;
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );

    if( Field == NULL )
        return;

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        title = wxT( "Reference:" );
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        title = wxT( "Component Name / Value:" );
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( Field->m_Attributs & TEXT_NO_VISIBLE )
        color = DARKGRAY;

    Text = Field->m_Text;
    Get_Message( title, _( "Edit field" ), Text, this );
    Text.Replace( wxT( " " ), wxT( "_" ) );

    /* If the value is changed, this is equivalent to create a new component from the old one
     * So we must check for an existing alias of this "new" component
     * and change the value only if there is no existing alias with the same name
     * for this component
     */
    if( Field->m_FieldId == VALUE )
    {
        /* test for an existing name in alias list: */
        for( unsigned ii = 0; ii < CurrentLibEntry->m_AliasList.GetCount(); ii += ALIAS_NEXT )
        {
            wxString aliasname = CurrentLibEntry->m_AliasList[ii + ALIAS_NAME];
            if( Text.CmpNoCase( aliasname ) == 0 )
            {
                DisplayError( this,
                              _( "This name is an existing alias of the component\nAborting" ), 10 );
                return;
            }
        }
    }

    GRSetDrawMode( DC, g_XorMode );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    if( !Text.IsEmpty() )
    {
        SaveCopyInUndoList( CurrentLibEntry );
        Field->m_Text = Text;
    }
    else
        DisplayError( this, _( "No new text: no change" ) );

    if( Field->m_Flags == 0 )
        GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    GetScreen()->SetModify();

    if( Field->m_FieldId == VALUE )
        ReCreateHToolbar();
}

/********************************************************************/
void WinEDA_LibeditFrame::RotateField( wxDC* DC, LibDrawField* Field )
/********************************************************************/

/* Routine de modification de l'orientation ( Horiz ou Vert. ) du champ.
 * si un champ est en cours d'edition, modif de celui ci.
 * sinon Modif du champ pointe par la souris
 */
{
    EDA_Colors color;

    if( Field == NULL )
        return;

    GetScreen()->SetModify();

    switch( Field->m_FieldId )
    {
    case REFERENCE:
        color = ReturnLayerColor( LAYER_REFERENCEPART );
        break;

    case VALUE:
        color = ReturnLayerColor( LAYER_VALUEPART );
        break;

    default:
        color = ReturnLayerColor( LAYER_FIELDS );
        break;
    }

    if( (Field->m_Attributs & TEXT_NO_VISIBLE) != 0 )
        color = DARKGRAY;

    DrawPanel->CursorOff( DC );

    GRSetDrawMode( DC, g_XorMode );
    int linewidth = (Field->m_Width == 0) ? g_DrawDefaultLineThickness : Field->m_Width;
    linewidth = Clamp_Text_PenSize( linewidth, Field->m_Size, Field->m_Bold );
    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);

    if( Field->m_Orient )
        Field->m_Orient = 0;
    else
        Field->m_Orient = 1;

    if( Field->m_Flags == 0 )
        GRSetDrawMode( DC, GR_DEFAULT_DRAWMODE );

    DrawGraphicText( DrawPanel, DC, wxPoint( Field->m_Pos.x, -Field->m_Pos.y ),
                     color, ReturnFieldFullText( Field ),
                     Field->m_Orient ? TEXT_ORIENT_VERT : TEXT_ORIENT_HORIZ,
                     Field->m_Size,
                     Field->m_HJustify, Field->m_VJustify, linewidth,
		      Field->m_Italic, Field->m_Bold);
    DrawPanel->CursorOn( DC );
}

/****************************************************************************/
LibDrawField* WinEDA_LibeditFrame::LocateField( EDA_LibComponentStruct* LibEntry )
/****************************************************************************/

/* Locate the component fiels (ref, name or auxiliary fields) under the mouse cursor
 * return:
 *     pointer on the field (or NULL )
 */
{
    wxPoint refpos;

    refpos.x = GetScreen()->m_Curseur.x;
    refpos.y = GetScreen()->m_Curseur.y;  // Y axis is from bottom to top in library
    /* Test reference */
    if( LibEntry->m_Name.HitTest( refpos ) )
        return &LibEntry->m_Name;

    /* Test Prefix */
    if( LibEntry->m_Prefix.HitTest( refpos ) )
        return &LibEntry->m_Prefix;

    /* Localisation des autres fields */
    for( LibDrawField* field = LibEntry->m_Fields;  field;  field = field->Next() )
    {
        if( field->m_Text.IsEmpty() )
            continue;

        if( field->HitTest( refpos ) )
            return field;
    }

    return NULL;
}

/********************************************************************************/
LibEDA_BaseStruct* WinEDA_LibeditFrame::LocateItemUsingCursor()
/********************************************************************************/
{
    LibEDA_BaseStruct* DrawEntry = CurrentDrawItem;

    if( CurrentLibEntry == NULL )
        return NULL;

    if( (DrawEntry == NULL) || (DrawEntry->m_Flags == 0) ) // Simple localisation des elements
    {
        DrawEntry = LocatePin(
            GetScreen()->m_Curseur, CurrentLibEntry, CurrentUnit, CurrentConvert );
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = LocateDrawItem( (SCH_SCREEN*) GetScreen(),
                                                         GetScreen()->m_MousePosition,
                                                         CurrentLibEntry, CurrentUnit,
                                                         CurrentConvert, LOCATE_ALL_DRAW_ITEM );
        }
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = LocateDrawItem( (SCH_SCREEN*) GetScreen(),
                                                         GetScreen()->m_Curseur, CurrentLibEntry,
                                                         CurrentUnit,
                                                         CurrentConvert, LOCATE_ALL_DRAW_ITEM );
        }
        if( DrawEntry == NULL )
        {
            DrawEntry = CurrentDrawItem = (LibEDA_BaseStruct*)
                                          LocateField( CurrentLibEntry );
        }
    }
    return DrawEntry;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
#include "opciones.h"
#include "funcionesDeBiblioteca.h"

using namespace std;

int xRectangulo = 0, yRectangulo = 0;
Color c = ROJO;

void dibujar()
{
    dibujarRectangulo(10 + xRectangulo,100 + yRectangulo,300+xRectangulo,365 + yRectangulo, c);
    c.verde = (c.verde + 5) % 256;
    c.azul = (c.azul + 7) % 256;
}

// Las siguientes funciones son las que espera el "framework"

int numeroDelBotonUno = -1, numeroDelBotonDos = -1;
int numeroDelCuadroUno = -1, numeroDelCuadroDos = -1;

void ejecutarAlIniciarElPrograma()
{
    // Aca se escribe el codigo que se ejecuta siempre al momento que comienza el programa
    numeroDelBotonUno = crearBoton(50,30,120,70, "Boton1");
    numeroDelBotonDos = crearBoton(130,30,200,70, "Boton2");
    numeroDelCuadroUno = crearCuadroDeTexto(350,30,420,70, "10");
    numeroDelCuadroDos = crearCuadroDeTexto(430,30,495,70, "5");
    dibujar();
    escribirTexto(10,2, "Finalmente podemos escribir", AMARILLO);
}

string toString(int x)
{
    ostringstream s; s << x;
    return s.str();
}

int fromString(string x)
{
    int ret; istringstream s(x); s >> ret;
    return ret;
}

int numero1 = 10, numero2 = 5;

void procesarCargaDeTextoEnCuadro(int numeroDeCuadroDeTexto, string texto)
{
    // Aca se escribe el codigo que se ejecuta cuando se carga texto en un cuadro de texto interactivo
    cout << "Se carga el texto \"" << texto << "\" en el cuadro de texto numero " << numeroDeCuadroDeTexto << endl;
    if (numeroDeCuadroDeTexto == numeroDelCuadroUno)
        numero1 = fromString(texto);
    else if (numeroDeCuadroDeTexto == numeroDelCuadroDos)
        numero2 = fromString(texto);
    else
        assert(false);
    dibujarRectangulo(0,400,500,500, NEGRO);
    escribirTexto(200, 415, string("La suma de los numeros cargados es ") + toString(numero1 + numero2), AMARILLO);
}

void procesarClicEnBoton(int numeroDeBoton)
{
    // Aca se escribe el codigo que se ejecuta cuando se hace clic en un boton
    dibujarRectangulo(0,400,500,500, NEGRO);
    if (numeroDeBoton == numeroDelBotonUno)
        escribirTexto(200, 415, "Se apreto el boton 1 UNO 1!", AMARILLO);
    else if (numeroDeBoton == numeroDelBotonDos)
        escribirTexto(200, 415, "Se apreto el boton 2 DOS 2!", AMARILLO);
    else
        assert(false);
    cout << "Se hace clic en el boton numero " << numeroDeBoton << endl;
}

void procesarPulsacionDeTecla(char tecla)
{
    // Aca se escribe el codigo que se ejecuta cuando se pulsa una tecla.
    cout << "Se pulsa la tecla " << tecla  << endl;
    const int SPEED = 3;
    if (tecla == 'a') xRectangulo -= SPEED;
    if (tecla == 'd') xRectangulo += SPEED;
    if (tecla == 'w') yRectangulo -= SPEED;
    if (tecla == 's') yRectangulo += SPEED;
    if (tecla == 'c') dibujarRectangulo(0 ,0,RESOLUCION_HORIZONTAL,RESOLUCION_VERTICAL, NEGRO);
    if (tecla == 'z') eliminarBoton(numeroDelBotonDos);
    if (tecla == 'x') eliminarCuadroDeTexto(numeroDelCuadroDos);
    if (tecla == 'l')
    {
        int k = 0;
        for (double alpha = 0.0; alpha < 2 * M_PI; alpha += 0.1, k ^= 1)
            dibujarLinea(250 ,250,250 * (1 + cos(alpha)) ,250 * (1 + sin(alpha)), AZUL, 1 + k);
    }
    dibujar();
}

void procesarClic(int X, int Y)
{
    // Aca se escribe el codigo que se ejecuta cuando se hace un clic en (X,Y)
    cout << "Se hace clic en (" << X << "," << Y << ")" << endl;
    dibujarCirculo(X,Y,12, CIAN);
}
<commit_msg>Adapto el ejemplo existente al cambio de opciones.h.<commit_after>#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
#include <cmath>
#include "funcionesDeBiblioteca.h"

using namespace std;

int xRectangulo = 0, yRectangulo = 0;
Color c = ROJO;

void dibujar()
{
    dibujarRectangulo(10 + xRectangulo,100 + yRectangulo,300+xRectangulo,365 + yRectangulo, c);
    c.verde = (c.verde + 5) % 256;
    c.azul = (c.azul + 7) % 256;
}

// Las siguientes funciones son las que espera el "framework"

extern const int RESOLUCION_HORIZONTAL = 500;
extern const int RESOLUCION_VERTICAL = 500;
extern const int TAMANIO_TEXTO = 12;
extern const string TITULO_PROGRAMA = "Programa OIA";

int numeroDelBotonUno = -1, numeroDelBotonDos = -1;
int numeroDelCuadroUno = -1, numeroDelCuadroDos = -1;

void ejecutarAlIniciarElPrograma()
{
    // Aca se escribe el codigo que se ejecuta siempre al momento que comienza el programa
    numeroDelBotonUno = crearBoton(50,30,120,70, "Boton1");
    numeroDelBotonDos = crearBoton(130,30,200,70, "Boton2");
    numeroDelCuadroUno = crearCuadroDeTexto(350,30,420,70, "10");
    numeroDelCuadroDos = crearCuadroDeTexto(430,30,495,70, "5");
    dibujar();
    escribirTexto(10,2, "Finalmente podemos escribir", AMARILLO);
}

string toString(int x)
{
    ostringstream s; s << x;
    return s.str();
}

int fromString(string x)
{
    int ret; istringstream s(x); s >> ret;
    return ret;
}

int numero1 = 10, numero2 = 5;

void procesarCargaDeTextoEnCuadro(int numeroDeCuadroDeTexto, string texto)
{
    // Aca se escribe el codigo que se ejecuta cuando se carga texto en un cuadro de texto interactivo
    cout << "Se carga el texto \"" << texto << "\" en el cuadro de texto numero " << numeroDeCuadroDeTexto << endl;
    if (numeroDeCuadroDeTexto == numeroDelCuadroUno)
        numero1 = fromString(texto);
    else if (numeroDeCuadroDeTexto == numeroDelCuadroDos)
        numero2 = fromString(texto);
    else
        assert(false);
    dibujarRectangulo(0,400,500,500, NEGRO);
    escribirTexto(200, 415, string("La suma de los numeros cargados es ") + toString(numero1 + numero2), AMARILLO);
}

void procesarClicEnBoton(int numeroDeBoton)
{
    // Aca se escribe el codigo que se ejecuta cuando se hace clic en un boton
    dibujarRectangulo(0,400,500,500, NEGRO);
    if (numeroDeBoton == numeroDelBotonUno)
        escribirTexto(200, 415, "Se apreto el boton 1 UNO 1!", AMARILLO);
    else if (numeroDeBoton == numeroDelBotonDos)
        escribirTexto(200, 415, "Se apreto el boton 2 DOS 2!", AMARILLO);
    else
        assert(false);
    cout << "Se hace clic en el boton numero " << numeroDeBoton << endl;
}

void procesarPulsacionDeTecla(char tecla)
{
    // Aca se escribe el codigo que se ejecuta cuando se pulsa una tecla.
    cout << "Se pulsa la tecla " << tecla  << endl;
    const int SPEED = 3;
    if (tecla == 'a') xRectangulo -= SPEED;
    if (tecla == 'd') xRectangulo += SPEED;
    if (tecla == 'w') yRectangulo -= SPEED;
    if (tecla == 's') yRectangulo += SPEED;
    if (tecla == 'c') dibujarRectangulo(0 ,0,RESOLUCION_HORIZONTAL,RESOLUCION_VERTICAL, NEGRO);
    if (tecla == 'z') eliminarBoton(numeroDelBotonDos);
    if (tecla == 'x') eliminarCuadroDeTexto(numeroDelCuadroDos);
    if (tecla == 'l')
    {
        int k = 0;
        for (double alpha = 0.0; alpha < 2 * M_PI; alpha += 0.1, k ^= 1)
            dibujarLinea(250 ,250,250 * (1 + cos(alpha)) ,250 * (1 + sin(alpha)), AZUL, 1 + k);
    }
    dibujar();
}

void procesarClic(int X, int Y)
{
    // Aca se escribe el codigo que se ejecuta cuando se hace un clic en (X,Y)
    cout << "Se hace clic en (" << X << "," << Y << ")" << endl;
    dibujarCirculo(X,Y,12, CIAN);
}
<|endoftext|>


<commit_before>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "tcp_socket_binding.h"
#include <Poco/NObserver.h>
#include <Poco/RunnableAdapter.h>
#include <kroll/kroll.h>

#define BUFFER_SIZE 1024   // choose a reasonable size to send back to JS

namespace ti
{
	static kroll::Logger* GetLogger()
	{
		return kroll::Logger::Get("Network.TCPSocket");
	}

	TCPSocketBinding::TCPSocketBinding(Host* ti_host, std::string host, int port) :
		StaticBoundObject("Network.TCPSocket"),
		ti_host(ti_host),
		host(host),
		port(port),
		opened(false),
		currentSendDataOffset(0),
		readStarted(false),
		onRead(0),
		onWrite(0),
		onTimeout(0),
		onReadComplete(0),
		readObserver(*this, &TCPSocketBinding::ReadyForRead),
		writeObserver(*this, &TCPSocketBinding::ReadyForWrite),
		timeoutObserver(*this, &TCPSocketBinding::OnTimeout),
		errorObserver(*this, &TCPSocketBinding::OnError),
		writeReadyHandlerInstalled(false),
		connectAdapter(new Poco::RunnableAdapter<TCPSocketBinding>(
			*this, &TCPSocketBinding::ConnectThread))
	{
		/**
		 * @tiapi(method=True,name=Network.TCPSocket.connect,since=0.2)
		 * @tiapi Connect the Socket object to the host specified during creation.
		 * @tiapi The connection will be made asynchronously. Use onError
		 * @tiapi to detect failures.
		 */
		this->SetMethod("connect", &TCPSocketBinding::Connect);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.close,since=0.2)
		 * Close the Socket object's connection, if it is open.
		 * @tiresult[Boolean] true if the connection was successfully close, false if otherwise
		 */
		this->SetMethod("close", &TCPSocketBinding::Close);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.write,since=0.2)
		 * @tiapi Write data to the Socket's connection, if open.
		 * @tiarg[String, data] The data to write to the connection.
		 * @tiresult[Boolean] True if the write was successful, false otherwise.
		 */
		this->SetMethod("write", &TCPSocketBinding::Write);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.isClosed,since=0.2)
		 * @tiapi Check whether the Socket is closed.
		 * @tiresult[Boolean] true if a Socket object is closed, false if otherwise
		 */
		this->SetMethod("isClosed",&TCPSocketBinding::IsClosed);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onRead,since=0.2)
		 * @tiapi Set a callback that will be fired when data is received on the Socket.
		 * @tiarg[Function, onRead] Function to be called when data is received.
		 */
		this->SetMethod("onRead",&TCPSocketBinding::SetOnRead);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onWrite,since=0.2)
		 * @tiapi Set a callback that will be fired when data is written on the Socket.
		 * @tiarg[Function, onWrite] Function to be called when data is written.
		 */
		this->SetMethod("onWrite",&TCPSocketBinding::SetOnWrite);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onTimeout,since=0.2)
		 * @tiapi Set the callback that will be fired when an operation times out on the Socket.
		 * @tiarg[Function, onTimeout] Function to be called when an operation times out.
		 */
		this->SetMethod("onTimeout",&TCPSocketBinding::SetOnTimeout);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onError,version=0.5)
		 * @tiapi Set the callback that will be fired when the Socket encounters an error.
		 * @tiarg[Function, onError] Function to be called when an error happens.
		 */
		this->SetMethod("onError",&TCPSocketBinding::SetOnError);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onReadComplete,since=0.2)
		 * @tiapi Set the callback function that will be fired when a read finishes. A read is
		 * @tiapi considered finished if some bytes have been read and a subsequent call to read
		 * @tiapi returns zero bytes.
		 * @tiarg[Function, onReadComplete] Function be called when a read completes.
		 */
		this->SetMethod("onReadComplete",&TCPSocketBinding::SetOnReadComplete);

		// Attach the reactor event handlers
		this->reactor.addEventHandler(this->socket, readObserver);
		this->reactor.addEventHandler(this->socket, timeoutObserver);
		this->reactor.addEventHandler(this->socket, errorObserver);
	}

	TCPSocketBinding::~TCPSocketBinding()
	{
		// Remove the reactor event handlers
		this->reactor.removeEventHandler(this->socket, readObserver);
		this->reactor.removeEventHandler(this->socket, writeObserver);
		this->reactor.removeEventHandler(this->socket, timeoutObserver);
		this->reactor.removeEventHandler(this->socket, errorObserver);

		if (this->opened)
		{
			this->reactor.stop();
			this->socket.close();
		}

		connectThread.join();
		delete connectAdapter;
	}

	void TCPSocketBinding::SetOnRead(const ValueList& args, KValueRef result)
	{
		this->onRead = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnWrite(const ValueList& args, KValueRef result)
	{
		this->onWrite = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnTimeout(const ValueList& args, KValueRef result)
	{
		this->onTimeout = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnError(const ValueList& args, KValueRef result)
	{
		this->onError = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnReadComplete(const ValueList& args, KValueRef result)
	{
		this->onReadComplete = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::IsClosed(const ValueList& args, KValueRef result)
	{
		return result->SetBool(!this->opened);
	}

	void TCPSocketBinding::ConnectThread()
	{
		static std::string error("Connection failed: ");
		try
		{
			// Give the connetion process and the reactor the same timeout.
			this->socket.connect(Poco::Net::SocketAddress(
				this->host, this->port), this->timeout);

			// Enable Keepalive mode on this socket. See:
			// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/index.html
			this->socket.setKeepAlive(true);

			this->reactor.setTimeout(this->timeout);
			this->thread.start(this->reactor);
			this->opened = true;
			return;
		}
		catch (Poco::IOException &e)
		{
			error.append(e.displayText());
		}
		catch (std::exception &e)
		{
			error.append(e.what());
		}
		catch (...)
		{
			error.append("Unknown exception");
		}

		if (!this->onError.isNull())
			RunOnMainThread(this->onError, ValueList(Value::NewString(error)), false);
	}

	void TCPSocketBinding::Connect(const ValueList& args, KValueRef result)
	{
		int timeout = 10;
		if (args.size() > 0)
		{
			timeout = args.at(0)->ToInt();
		}

		if (this->opened || connectThread.isRunning())
		{
			throw ValueException::FromString("Socket is already open");
		}

		result->SetBool(true);
		this->timeout = Poco::Timespan(timeout, 0);
		connectThread.start(*connectAdapter);
	}

	void TCPSocketBinding::ReadyForRead(
		const Poco::AutoPtr<Poco::Net::ReadableNotification>& n)
	{
		static std::string eprefix("TCPSocketBinding::OnRead: ");

		try
		{
			// Always read bytes, so that the tubes get cleared.
			char data[BUFFER_SIZE + 1];
			int size = socket.receiveBytes(&data, BUFFER_SIZE);

			// A read is only complete if we've already read some bytes from the socket.
			bool readComplete = this->readStarted && (size <= 0);
			this->readStarted = (size > 0);

			if (readComplete && !this->onReadComplete.isNull())
			{
				ValueList args;
				RunOnMainThread(this->onReadComplete, args, false);
			}
			else if (size > 0 && !this->onRead.isNull())
			{
				data[size] = '\0';

				BytesRef bytes(new Bytes(data, size));
				ValueList args(Value::NewObject(bytes));
				RunOnMainThread(this->onRead, args, false);
			}
		}
		catch (ValueException& e)
		{
			GetLogger()->Error("Read failed: %s", e.ToString().c_str());
			ValueList args(Value::NewString(e.ToString()));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
		catch (Poco::Exception &e)
		{
			GetLogger()->Error("Read failed: %s", e.displayText().c_str());
			ValueList args(Value::NewString(e.displayText()));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
		catch (...)
		{
			GetLogger()->Error("Read failed: unknown exception");
			ValueList args(Value::NewString("Unknown exception during read"));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
	}

	void TCPSocketBinding::ReadyForWrite(
		const Poco::AutoPtr<Poco::Net::WritableNotification>& n)
	{
		if (sendData.empty())
			return;

		BytesRef buffer(0);
		{
			Poco::Mutex::ScopedLock lock(sendDataMutex);
			buffer = sendData.front();
		}

		const char* data = buffer->Get() + currentSendDataOffset;
		size_t length = buffer->Length() - currentSendDataOffset;
		size_t count = this->socket.sendBytes(data, length);
		currentSendDataOffset += count;

		if (currentSendDataOffset == (size_t) buffer->Length())
		{
			// Only send the onWrite message when we've exhausted a Bytes.
			if (!this->onWrite.isNull())
			{
				ValueList args(Value::NewInt(buffer->Length()));
				RunOnMainThread(this->onWrite, args, false);
			}

			Poco::Mutex::ScopedLock lock(sendDataMutex);
			sendData.pop();

			// Uninstall the ReadyForWrite reactor handler, because it will push
			// the CPU to 100% usage if there is nothing to write.
			if (sendData.size() == 0)
			{
				this->reactor.removeEventHandler(this->socket, writeObserver);
				writeReadyHandlerInstalled = false;
			}
		}
	}

	void TCPSocketBinding::OnTimeout(
		const Poco::AutoPtr<Poco::Net::TimeoutNotification>& n)
	{
		if (this->onTimeout.isNull())
		{
			return;
		}
		RunOnMainThread(this->onTimeout, ValueList(), false);
	}

	void TCPSocketBinding::OnError(
		const Poco::AutoPtr<Poco::Net::ErrorNotification>& n)
	{
		if (this->onError.isNull())
		{
			return;
		}
		ValueList args(Value::NewString(n->name()));
		RunOnMainThread(this->onError, args, false);
	}

	void TCPSocketBinding::Write(const ValueList& args, KValueRef result)
	{
		args.VerifyException("Send", "o|s");

		static std::string eprefix("TCPSocketBinding::Write: ");
		if (!this->opened && !this->connectThread.isRunning())
			throw ValueException::FromString(eprefix +  "Socket is not open");

		BytesRef data(0);
		if (args.at(0)->IsString())
		{
			std::string sendString(args.GetString(0));
			data = new Bytes(sendString.c_str(), sendString.size());
		}
		else if (args.at(0)->IsObject())
		{
			KObjectRef dataObject(args.GetObject(0));
			data = dataObject.cast<Bytes>();
		}

		if (data.isNull())
			throw ValueException::FromString("Cannot send non-Bytes object");

		{
			Poco::Mutex::ScopedLock lock(sendDataMutex);
			sendData.push(data);

			// Only install the ReadyForWrite handler when there is actually data
			// to write, because otherwise the CPU usage will spike to 100%
			if (!writeReadyHandlerInstalled)
			{
				this->reactor.addEventHandler(this->socket, writeObserver);
				writeReadyHandlerInstalled = true;
			}
		}

		result->SetBool(true);
	}

	void TCPSocketBinding::Close(const ValueList& args, KValueRef result)
	{
		if (this->opened)
		{
			this->opened = false;
			this->reactor.stop();
			this->socket.close();
			result->SetBool(true);
		}
		else
		{
			result->SetBool(false);
		}
	}
}

<commit_msg>Fix for corruption after multiples uses of TCPSocket.write(...).<commit_after>/**
 * Appcelerator Titanium - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "tcp_socket_binding.h"
#include <Poco/NObserver.h>
#include <Poco/RunnableAdapter.h>
#include <kroll/kroll.h>

#define BUFFER_SIZE 1024   // choose a reasonable size to send back to JS

namespace ti
{
	static kroll::Logger* GetLogger()
	{
		return kroll::Logger::Get("Network.TCPSocket");
	}

	TCPSocketBinding::TCPSocketBinding(Host* ti_host, std::string host, int port) :
		StaticBoundObject("Network.TCPSocket"),
		ti_host(ti_host),
		host(host),
		port(port),
		opened(false),
		currentSendDataOffset(0),
		readStarted(false),
		onRead(0),
		onWrite(0),
		onTimeout(0),
		onReadComplete(0),
		readObserver(*this, &TCPSocketBinding::ReadyForRead),
		writeObserver(*this, &TCPSocketBinding::ReadyForWrite),
		timeoutObserver(*this, &TCPSocketBinding::OnTimeout),
		errorObserver(*this, &TCPSocketBinding::OnError),
		writeReadyHandlerInstalled(false),
		connectAdapter(new Poco::RunnableAdapter<TCPSocketBinding>(
			*this, &TCPSocketBinding::ConnectThread))
	{
		/**
		 * @tiapi(method=True,name=Network.TCPSocket.connect,since=0.2)
		 * @tiapi Connect the Socket object to the host specified during creation.
		 * @tiapi The connection will be made asynchronously. Use onError
		 * @tiapi to detect failures.
		 */
		this->SetMethod("connect", &TCPSocketBinding::Connect);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.close,since=0.2)
		 * Close the Socket object's connection, if it is open.
		 * @tiresult[Boolean] true if the connection was successfully close, false if otherwise
		 */
		this->SetMethod("close", &TCPSocketBinding::Close);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.write,since=0.2)
		 * @tiapi Write data to the Socket's connection, if open.
		 * @tiarg[String, data] The data to write to the connection.
		 * @tiresult[Boolean] True if the write was successful, false otherwise.
		 */
		this->SetMethod("write", &TCPSocketBinding::Write);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.isClosed,since=0.2)
		 * @tiapi Check whether the Socket is closed.
		 * @tiresult[Boolean] true if a Socket object is closed, false if otherwise
		 */
		this->SetMethod("isClosed",&TCPSocketBinding::IsClosed);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onRead,since=0.2)
		 * @tiapi Set a callback that will be fired when data is received on the Socket.
		 * @tiarg[Function, onRead] Function to be called when data is received.
		 */
		this->SetMethod("onRead",&TCPSocketBinding::SetOnRead);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onWrite,since=0.2)
		 * @tiapi Set a callback that will be fired when data is written on the Socket.
		 * @tiarg[Function, onWrite] Function to be called when data is written.
		 */
		this->SetMethod("onWrite",&TCPSocketBinding::SetOnWrite);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onTimeout,since=0.2)
		 * @tiapi Set the callback that will be fired when an operation times out on the Socket.
		 * @tiarg[Function, onTimeout] Function to be called when an operation times out.
		 */
		this->SetMethod("onTimeout",&TCPSocketBinding::SetOnTimeout);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onError,version=0.5)
		 * @tiapi Set the callback that will be fired when the Socket encounters an error.
		 * @tiarg[Function, onError] Function to be called when an error happens.
		 */
		this->SetMethod("onError",&TCPSocketBinding::SetOnError);

		/**
		 * @tiapi(method=True,name=Network.TCPSocket.onReadComplete,since=0.2)
		 * @tiapi Set the callback function that will be fired when a read finishes. A read is
		 * @tiapi considered finished if some bytes have been read and a subsequent call to read
		 * @tiapi returns zero bytes.
		 * @tiarg[Function, onReadComplete] Function be called when a read completes.
		 */
		this->SetMethod("onReadComplete",&TCPSocketBinding::SetOnReadComplete);

		// Attach the reactor event handlers
		this->reactor.addEventHandler(this->socket, readObserver);
		this->reactor.addEventHandler(this->socket, timeoutObserver);
		this->reactor.addEventHandler(this->socket, errorObserver);
	}

	TCPSocketBinding::~TCPSocketBinding()
	{
		// Remove the reactor event handlers
		this->reactor.removeEventHandler(this->socket, readObserver);
		this->reactor.removeEventHandler(this->socket, writeObserver);
		this->reactor.removeEventHandler(this->socket, timeoutObserver);
		this->reactor.removeEventHandler(this->socket, errorObserver);

		if (this->opened)
		{
			this->reactor.stop();
			this->socket.close();
		}

		connectThread.join();
		delete connectAdapter;
	}

	void TCPSocketBinding::SetOnRead(const ValueList& args, KValueRef result)
	{
		this->onRead = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnWrite(const ValueList& args, KValueRef result)
	{
		this->onWrite = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnTimeout(const ValueList& args, KValueRef result)
	{
		this->onTimeout = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnError(const ValueList& args, KValueRef result)
	{
		this->onError = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::SetOnReadComplete(const ValueList& args, KValueRef result)
	{
		this->onReadComplete = args.at(0)->ToMethod();
	}

	void TCPSocketBinding::IsClosed(const ValueList& args, KValueRef result)
	{
		return result->SetBool(!this->opened);
	}

	void TCPSocketBinding::ConnectThread()
	{
		static std::string error("Connection failed: ");
		try
		{
			// Give the connetion process and the reactor the same timeout.
			this->socket.connect(Poco::Net::SocketAddress(
				this->host, this->port), this->timeout);

			// Enable Keepalive mode on this socket. See:
			// http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/index.html
			this->socket.setKeepAlive(true);

			this->reactor.setTimeout(this->timeout);
			this->thread.start(this->reactor);
			this->opened = true;
			return;
		}
		catch (Poco::IOException &e)
		{
			error.append(e.displayText());
		}
		catch (std::exception &e)
		{
			error.append(e.what());
		}
		catch (...)
		{
			error.append("Unknown exception");
		}

		if (!this->onError.isNull())
			RunOnMainThread(this->onError, ValueList(Value::NewString(error)), false);
	}

	void TCPSocketBinding::Connect(const ValueList& args, KValueRef result)
	{
		int timeout = 10;
		if (args.size() > 0)
		{
			timeout = args.at(0)->ToInt();
		}

		if (this->opened || connectThread.isRunning())
		{
			throw ValueException::FromString("Socket is already open");
		}

		result->SetBool(true);
		this->timeout = Poco::Timespan(timeout, 0);
		connectThread.start(*connectAdapter);
	}

	void TCPSocketBinding::ReadyForRead(
		const Poco::AutoPtr<Poco::Net::ReadableNotification>& n)
	{
		static std::string eprefix("TCPSocketBinding::OnRead: ");

		try
		{
			// Always read bytes, so that the tubes get cleared.
			char data[BUFFER_SIZE + 1];
			int size = socket.receiveBytes(&data, BUFFER_SIZE);

			// A read is only complete if we've already read some bytes from the socket.
			bool readComplete = this->readStarted && (size <= 0);
			this->readStarted = (size > 0);

			if (readComplete && !this->onReadComplete.isNull())
			{
				ValueList args;
				RunOnMainThread(this->onReadComplete, args, false);
			}
			else if (size > 0 && !this->onRead.isNull())
			{
				data[size] = '\0';

				BytesRef bytes(new Bytes(data, size));
				ValueList args(Value::NewObject(bytes));
				RunOnMainThread(this->onRead, args, false);
			}
		}
		catch (ValueException& e)
		{
			GetLogger()->Error("Read failed: %s", e.ToString().c_str());
			ValueList args(Value::NewString(e.ToString()));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
		catch (Poco::Exception &e)
		{
			GetLogger()->Error("Read failed: %s", e.displayText().c_str());
			ValueList args(Value::NewString(e.displayText()));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
		catch (...)
		{
			GetLogger()->Error("Read failed: unknown exception");
			ValueList args(Value::NewString("Unknown exception during read"));

			if (!this->onError.isNull())
				RunOnMainThread(this->onError, args, false);
		}
	}

	void TCPSocketBinding::ReadyForWrite(
		const Poco::AutoPtr<Poco::Net::WritableNotification>& n)
	{
		if (sendData.empty())
			return;

		BytesRef buffer(0);
		{
			Poco::Mutex::ScopedLock lock(sendDataMutex);
			buffer = sendData.front();
		}

		const char* data = buffer->Get() + currentSendDataOffset;
		size_t length = buffer->Length() - currentSendDataOffset;
		size_t count = this->socket.sendBytes(data, length);
		currentSendDataOffset += count;

		if (currentSendDataOffset == (size_t) buffer->Length())
		{
			// Only send the onWrite message when we've exhausted a Bytes.
			if (!this->onWrite.isNull())
			{
				ValueList args(Value::NewInt(buffer->Length()));
				RunOnMainThread(this->onWrite, args, false);
			}

			Poco::Mutex::ScopedLock lock(sendDataMutex);
			sendData.pop();
			currentSendDataOffset = 0;

			// Uninstall the ReadyForWrite reactor handler, because it will push
			// the CPU to 100% usage if there is nothing to write.
			if (sendData.size() == 0)
			{
				this->reactor.removeEventHandler(this->socket, writeObserver);
				writeReadyHandlerInstalled = false;
			}
		}
	}

	void TCPSocketBinding::OnTimeout(
		const Poco::AutoPtr<Poco::Net::TimeoutNotification>& n)
	{
		if (this->onTimeout.isNull())
		{
			return;
		}
		RunOnMainThread(this->onTimeout, ValueList(), false);
	}

	void TCPSocketBinding::OnError(
		const Poco::AutoPtr<Poco::Net::ErrorNotification>& n)
	{
		if (this->onError.isNull())
		{
			return;
		}
		ValueList args(Value::NewString(n->name()));
		RunOnMainThread(this->onError, args, false);
	}

	void TCPSocketBinding::Write(const ValueList& args, KValueRef result)
	{
		args.VerifyException("Send", "o|s");

		static std::string eprefix("TCPSocketBinding::Write: ");
		if (!this->opened && !this->connectThread.isRunning())
			throw ValueException::FromString(eprefix +  "Socket is not open");

		BytesRef data(0);
		if (args.at(0)->IsString())
		{
			std::string sendString(args.GetString(0));
			data = new Bytes(sendString.c_str(), sendString.size());
		}
		else if (args.at(0)->IsObject())
		{
			KObjectRef dataObject(args.GetObject(0));
			data = dataObject.cast<Bytes>();
		}

		if (data.isNull())
			throw ValueException::FromString("Cannot send non-Bytes object");

		{
			Poco::Mutex::ScopedLock lock(sendDataMutex);
			sendData.push(data);

			// Only install the ReadyForWrite handler when there is actually data
			// to write, because otherwise the CPU usage will spike to 100%
			if (!writeReadyHandlerInstalled)
			{
				this->reactor.addEventHandler(this->socket, writeObserver);
				writeReadyHandlerInstalled = true;
			}
		}

		result->SetBool(true);
	}

	void TCPSocketBinding::Close(const ValueList& args, KValueRef result)
	{
		if (this->opened)
		{
			this->opened = false;
			this->reactor.stop();
			this->socket.close();
			result->SetBool(true);
		}
		else
		{
			result->SetBool(false);
		}
	}
}

<|endoftext|>


<commit_before>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

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

#ifndef FAIL_REP_HPP
#define FAIL_REP_HPP

#include "SignalData.hpp"

/**
 *
 */
class FailRep {
  /**
   * Sender(s) & Reciver(s)
   */
  friend class Qmgr;
  friend class Ndbcntr;

  /**
   * For printing
   */
  friend bool printFAIL_REP(FILE *, const Uint32 *, Uint32, Uint16);

public:
  STATIC_CONST( SignalLength = 2 );
  STATIC_CONST( ExtraLength = 1 + NdbNodeBitmask::Size );

  enum FailCause {
    ZOWN_FAILURE=0,
    ZOTHER_NODE_WHEN_WE_START=1,
    ZIN_PREP_FAIL_REQ=2,
    ZSTART_IN_REGREQ=3,
    ZHEARTBEAT_FAILURE=4,
    ZLINK_FAILURE=5,
    ZOTHERNODE_FAILED_DURING_START=6,
    ZMULTI_NODE_SHUTDOWN = 7,
    ZPARTITIONED_CLUSTER = 8
  };

private:

  Uint32 failNodeId;
  Uint32 failCause;
  /**
   * Used when failCause == ZPARTITIONED_CLUSTER
   */
  Uint32 president;
  Uint32 partition[NdbNodeBitmask::Size];
};

#endif
<commit_msg>ndb -   Fix compile error...when compiling debug<commit_after>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

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

#ifndef FAIL_REP_HPP
#define FAIL_REP_HPP

#include "SignalData.hpp"
#include <NodeBitmask.hpp>

/**
 *
 */
class FailRep {
  /**
   * Sender(s) & Reciver(s)
   */
  friend class Qmgr;
  friend class Ndbcntr;

  /**
   * For printing
   */
  friend bool printFAIL_REP(FILE *, const Uint32 *, Uint32, Uint16);

public:
  STATIC_CONST( SignalLength = 2 );
  STATIC_CONST( ExtraLength = 1 + NdbNodeBitmask::Size );

  enum FailCause {
    ZOWN_FAILURE=0,
    ZOTHER_NODE_WHEN_WE_START=1,
    ZIN_PREP_FAIL_REQ=2,
    ZSTART_IN_REGREQ=3,
    ZHEARTBEAT_FAILURE=4,
    ZLINK_FAILURE=5,
    ZOTHERNODE_FAILED_DURING_START=6,
    ZMULTI_NODE_SHUTDOWN = 7,
    ZPARTITIONED_CLUSTER = 8
  };

private:

  Uint32 failNodeId;
  Uint32 failCause;
  /**
   * Used when failCause == ZPARTITIONED_CLUSTER
   */
  Uint32 president;
  Uint32 partition[NdbNodeBitmask::Size];
};

#endif
<|endoftext|>


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

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (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.commontk.org/LICENSE

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Qt includes
#include <QFile>
#include <QTextStream>
#include <QRegExp>
#include <QStringList>
#include <QDebug>

// CTK includes
#include <ctkDependencyGraph.h>

// STD includes
#include <cstdlib>
#include <iostream>

//----------------------------------------------------------------------------
QString help(const QString& progName)
{
  QString msg = "Usage: %1 <graphfile> [-paths Label | -sort Label]";
  return msg.arg(progName);
}

//----------------------------------------------------------------------------
void displayError(const QString& progName, const QString& msg)
{
  std::cerr << QString("%1\n%2\n%3\n").arg(progName).
                                       arg(msg).
                                       arg(help(progName)).toStdString();
}

//----------------------------------------------------------------------------
int getOrGenerateId(QHash<int, QString>& vertexIdToLabel,
                    QHash<QString, int>& vertexLabelToId,
                    const QString& label)
{
  // If needed, generate vertex id
  int vertexId = -1;
  if (!vertexLabelToId.keys().contains(label))
    {
    vertexId = vertexLabelToId.keys().size() + 1;
    vertexLabelToId[label] = vertexId;
    vertexIdToLabel[vertexId] = label;
    }
  else
    {
    vertexId = vertexLabelToId[label];
    }
  return vertexId;
}

//----------------------------------------------------------------------------
int main(int argc, char** argv)
{
  bool verbose = false;
  bool outputTopologicalOrder = true;

  // a graph file is expected
  if (argc < 2)
    {
    displayError(argv[0], QLatin1String("Missing one argument"));
    return EXIT_FAILURE;
    }

  bool outputPath = false;
  bool outputSort = false;
  QString label;
  if (argc == 3)
    {
    displayError(argv[0], QLatin1String("Wrong argument"));
    return EXIT_FAILURE;
    }
  if (argc == 4)
    {
    QString arg2 = QString::fromLatin1(argv[2]);
    if (arg2.compare("-paths")!=0 && arg2.compare("-sort")!=0)
      {
      displayError(argv[0], QString("Wrong argument: %1").arg(arg2));
      return EXIT_FAILURE;
      }
    label = QLatin1String(argv[3]);
    outputTopologicalOrder = false;
    if (arg2.compare("-paths") == 0)
      {
      outputPath = true;
      }
    else
      {
      outputSort = true;
      }

    if (verbose)
      {
      qDebug() << "label:" << label;
      }
    }

  QString filepath = QString::fromLatin1(argv[1]);
  if (!QFile::exists(filepath))
    {
    displayError(argv[0], QString("File '%1' doesn't exists !").arg(filepath));
    return EXIT_FAILURE;
    }

  QFile data(filepath);
  if (!data.open(QFile::ReadOnly))
    {
    displayError(argv[0], QString("Failed to open file '%1' !").arg(filepath));
    return EXIT_FAILURE;
    }

  QTextStream in(&data);
  QString header = in.readLine();
  if (header.isNull())
    {
    displayError(argv[0], QString("Failed to read Header line in file '%1' !").arg(filepath));
    return EXIT_FAILURE;
    }

  // Regular expression to extract two integers
  QRegExp twoint_re("^([0-9]+)\\s+([0-9]+)");

  // Extract numberOfVertices and numberOfEdges
  int pos = twoint_re.indexIn(header.trimmed());
  if (pos != 0)
    {
    displayError(argv[0], QString("Error in file '%1' - First line should look like: <#Vertices> <#Edges>")
      .arg(filepath));
    return EXIT_FAILURE;
    }
  QStringList list = twoint_re.capturedTexts();
  Q_ASSERT(list.size() == 3);

  int numberOfVertices = list[1].toInt();
  int numberOfEdges = list[2].toInt();

  if (verbose)
    {
    qDebug() << "#Vertices:" << numberOfVertices << "#Edges:" << numberOfEdges;
    }

  // Init
  ctkDependencyGraph mygraph(numberOfVertices);
  mygraph.setVerbose(verbose);

  // Map between vertex label and vertex id
  QHash<int, QString> vertexIdToLabel;
  QHash<QString, int> vertexLabelToId;

  // Regular expression to extract two label
  QRegExp twolabel_re("^(.+)\\s+(.+)");

  // Read vertex connection
  int lineNumber = 2;
  QString line = in.readLine();
  do
    {
    // Skip empty line or commented line
    if (line.isEmpty() || line.startsWith("#"))
      {
      line = in.readLine();
      continue;
      }

    // Extract vertex points

    int pos = twolabel_re.indexIn(line.trimmed());
    if (pos != 0)
      {
      displayError(argv[0], QString("Error in file '%1' - line:%2 - Expected format is: <label> <label>")
        .arg(filepath).arg(lineNumber));
      return EXIT_FAILURE;
      }
    lineNumber++;

    QStringList list = twolabel_re.capturedTexts();
    Q_ASSERT(list.size() == 3);

    int from = getOrGenerateId(vertexIdToLabel, vertexLabelToId, list[1]);
    int to = getOrGenerateId(vertexIdToLabel, vertexLabelToId, list[2]);

    // Insert edge
    mygraph.insertEdge(from, to);

    line = in.readLine();
    }
  while (!line.isNull());

  Q_ASSERT(numberOfEdges == mygraph.numberOfEdges());

  if (verbose)
    {
    mygraph.printGraph();
    qDebug() << "> Check for cycle ...";
    }

  mygraph.checkForCycle();

  if (mygraph.cycleDetected())
    {
    std::cerr << "Cycle detected !" << std::endl;
    QList<int> path;
    mygraph.findPath(mygraph.cycleOrigin(), mygraph.cycleEnd(), path);

    for(int i = 0; i < path.size(); ++i)
      {
      std::cerr << vertexIdToLabel[path[i]].toStdString();
      if (i != path.size() - 1)
        {
        std::cerr << " -> ";
        }
      }
    std::cerr << std::endl;

    path.clear();
    mygraph.findPath(mygraph.cycleEnd(), mygraph.cycleOrigin(), path);

    for(int i = 0; i < path.size(); ++i)
      {
      std::cerr << vertexIdToLabel[path[i]].toStdString();
      if (i != path.size() - 1)
        {
        std::cerr << " -> ";
        }
      }
    std::cerr << std::endl;

    return EXIT_FAILURE;
    }

  if (outputTopologicalOrder)
    {
    if (verbose)
      {
      qDebug() << "> Topological order ...";
      }
    QList<int> out;
    if (mygraph.topologicalSort(out))
      {
      for(int i=out.size() - 1; i >= 0; --i)
        {
        std::cout << vertexIdToLabel[out[i]].toStdString();
        if (i != 0)
          {
          std::cout << " ";
          }
        }
      std::cout << std::endl;
      }
    }

  if (verbose)
    {
    QList<int> sources;
    mygraph.sourceVertices(sources);
    qDebug() << "Source vertices: " << sources;
    }

  if (outputPath)
    {
    // TODO Make sure label is valid
    QList<int> out;
    if (mygraph.topologicalSort(out))
      {
      for(int i=0; i < out.size(); i++)
        {
        // Assume all targets depend on the first lib
        // We could get all sinks and find all paths
        // from the rootId to the sink vertices.
        int rootId = out.last();
        int labelId = vertexLabelToId[label];
        QList<QList<int>*> paths;
        mygraph.findPaths(labelId, rootId, paths);
        for(int i=0; i < paths.size(); i++)
          {
          QList<int>* p = paths[i];
          Q_ASSERT(p);
          for(int j=0; j < p->size(); j++)
            {
            int id = p->at(j);
            std::cout << vertexIdToLabel[id].toStdString();
            if (j != p->size() - 1)
              {
              std::cout << " ";
              }
            }
          if (i != paths.size() - 1)
            {
            std::cout << ";";
            }
          }
        }
      }
    }

  if (outputSort)
    {
    // TODO Make sure label is valid
    QList<int> out;
    int labelId = vertexLabelToId[label];
    if (mygraph.topologicalSort(out, labelId))
      {
      for(int i=0; i < out.size(); i++)
        {
        int id = out.at(i);
        std::cout << vertexIdToLabel[id].toStdString();

        if (i != out.size() - 1)
          {
          std::cout << " ";
          }
        }
      }
    }

  return EXIT_SUCCESS;
}
<commit_msg>DGraph: Fix dll boundary prob using qPrintable() instead of toStdString()<commit_after>/*=========================================================================

  Library:   CTK

  Copyright (c) Kitware Inc.

  Licensed under the Apache License, Version 2.0 (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.commontk.org/LICENSE

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

=========================================================================*/

// Qt includes
#include <QFile>
#include <QTextStream>
#include <QRegExp>
#include <QStringList>
#include <QDebug>

// CTK includes
#include <ctkDependencyGraph.h>

// STD includes
#include <cstdlib>
#include <iostream>

//----------------------------------------------------------------------------
QString help(const QString& progName)
{
  QString msg = "Usage: %1 <graphfile> [-paths Label | -sort Label]";
  return msg.arg(progName);
}

//----------------------------------------------------------------------------
void displayError(const QString& progName, const QString& msg)
{
  std::cerr << qPrintable(QString("%1\n%2\n%3\n").arg(progName).
                                                 arg(msg).
                                                 arg(help(progName)));
}

//----------------------------------------------------------------------------
int getOrGenerateId(QHash<int, QString>& vertexIdToLabel,
                    QHash<QString, int>& vertexLabelToId,
                    const QString& label)
{
  // If needed, generate vertex id
  int vertexId = -1;
  if (!vertexLabelToId.keys().contains(label))
    {
    vertexId = vertexLabelToId.keys().size() + 1;
    vertexLabelToId[label] = vertexId;
    vertexIdToLabel[vertexId] = label;
    }
  else
    {
    vertexId = vertexLabelToId[label];
    }
  return vertexId;
}

//----------------------------------------------------------------------------
int main(int argc, char** argv)
{
  bool verbose = false;
  bool outputTopologicalOrder = true;

  // a graph file is expected
  if (argc < 2)
    {
    displayError(argv[0], QLatin1String("Missing one argument"));
    return EXIT_FAILURE;
    }

  bool outputPath = false;
  bool outputSort = false;
  QString label;
  if (argc == 3)
    {
    displayError(argv[0], QLatin1String("Wrong argument"));
    return EXIT_FAILURE;
    }
  if (argc == 4)
    {
    QString arg2 = QString::fromLatin1(argv[2]);
    if (arg2.compare("-paths")!=0 && arg2.compare("-sort")!=0)
      {
      displayError(argv[0], QString("Wrong argument: %1").arg(arg2));
      return EXIT_FAILURE;
      }
    label = QLatin1String(argv[3]);
    outputTopologicalOrder = false;
    if (arg2.compare("-paths") == 0)
      {
      outputPath = true;
      }
    else
      {
      outputSort = true;
      }

    if (verbose)
      {
      qDebug() << "label:" << label;
      }
    }

  QString filepath = QString::fromLatin1(argv[1]);
  if (!QFile::exists(filepath))
    {
    displayError(argv[0], QString("File '%1' doesn't exists !").arg(filepath));
    return EXIT_FAILURE;
    }

  QFile data(filepath);
  if (!data.open(QFile::ReadOnly))
    {
    displayError(argv[0], QString("Failed to open file '%1' !").arg(filepath));
    return EXIT_FAILURE;
    }

  QTextStream in(&data);
  QString header = in.readLine();
  if (header.isNull())
    {
    displayError(argv[0], QString("Failed to read Header line in file '%1' !").arg(filepath));
    return EXIT_FAILURE;
    }

  // Regular expression to extract two integers
  QRegExp twoint_re("^([0-9]+)\\s+([0-9]+)");

  // Extract numberOfVertices and numberOfEdges
  int pos = twoint_re.indexIn(header.trimmed());
  if (pos != 0)
    {
    displayError(argv[0], QString("Error in file '%1' - First line should look like: <#Vertices> <#Edges>")
      .arg(filepath));
    return EXIT_FAILURE;
    }
  QStringList list = twoint_re.capturedTexts();
  Q_ASSERT(list.size() == 3);

  int numberOfVertices = list[1].toInt();
  int numberOfEdges = list[2].toInt();

  if (verbose)
    {
    qDebug() << "#Vertices:" << numberOfVertices << "#Edges:" << numberOfEdges;
    }

  // Init
  ctkDependencyGraph mygraph(numberOfVertices);
  mygraph.setVerbose(verbose);

  // Map between vertex label and vertex id
  QHash<int, QString> vertexIdToLabel;
  QHash<QString, int> vertexLabelToId;

  // Regular expression to extract two label
  QRegExp twolabel_re("^(.+)\\s+(.+)");

  // Read vertex connection
  int lineNumber = 2;
  QString line = in.readLine();
  do
    {
    // Skip empty line or commented line
    if (line.isEmpty() || line.startsWith("#"))
      {
      line = in.readLine();
      continue;
      }

    // Extract vertex points

    int pos = twolabel_re.indexIn(line.trimmed());
    if (pos != 0)
      {
      displayError(argv[0], QString("Error in file '%1' - line:%2 - Expected format is: <label> <label>")
        .arg(filepath).arg(lineNumber));
      return EXIT_FAILURE;
      }
    lineNumber++;

    QStringList list = twolabel_re.capturedTexts();
    Q_ASSERT(list.size() == 3);

    int from = getOrGenerateId(vertexIdToLabel, vertexLabelToId, list[1]);
    int to = getOrGenerateId(vertexIdToLabel, vertexLabelToId, list[2]);

    // Insert edge
    mygraph.insertEdge(from, to);

    line = in.readLine();
    }
  while (!line.isNull());

  Q_ASSERT(numberOfEdges == mygraph.numberOfEdges());

  if (verbose)
    {
    mygraph.printGraph();
    qDebug() << "> Check for cycle ...";
    }

  mygraph.checkForCycle();

  if (mygraph.cycleDetected())
    {
    std::cerr << "Cycle detected !" << std::endl;
    QList<int> path;
    mygraph.findPath(mygraph.cycleOrigin(), mygraph.cycleEnd(), path);

    for(int i = 0; i < path.size(); ++i)
      {
      std::cerr << qPrintable(vertexIdToLabel[path[i]]);
      if (i != path.size() - 1)
        {
        std::cerr << " -> ";
        }
      }
    std::cerr << std::endl;

    path.clear();
    mygraph.findPath(mygraph.cycleEnd(), mygraph.cycleOrigin(), path);

    for(int i = 0; i < path.size(); ++i)
      {
      std::cerr << qPrintable(vertexIdToLabel[path[i]]);
      if (i != path.size() - 1)
        {
        std::cerr << " -> ";
        }
      }
    std::cerr << std::endl;

    return EXIT_FAILURE;
    }

  if (outputTopologicalOrder)
    {
    if (verbose)
      {
      qDebug() << "> Topological order ...";
      }
    QList<int> out;
    if (mygraph.topologicalSort(out))
      {
      for(int i=out.size() - 1; i >= 0; --i)
        {
        std::cout << vertexIdToLabel[out[i]].toStdString();
        if (i != 0)
          {
          std::cout << " ";
          }
        }
      std::cout << std::endl;
      }
    }

  if (verbose)
    {
    QList<int> sources;
    mygraph.sourceVertices(sources);
    qDebug() << "Source vertices: " << sources;
    }

  if (outputPath)
    {
    // TODO Make sure label is valid
    QList<int> out;
    if (mygraph.topologicalSort(out))
      {
      for(int i=0; i < out.size(); i++)
        {
        // Assume all targets depend on the first lib
        // We could get all sinks and find all paths
        // from the rootId to the sink vertices.
        int rootId = out.last();
        int labelId = vertexLabelToId[label];
        QList<QList<int>*> paths;
        mygraph.findPaths(labelId, rootId, paths);
        for(int i=0; i < paths.size(); i++)
          {
          QList<int>* p = paths[i];
          Q_ASSERT(p);
          for(int j=0; j < p->size(); j++)
            {
            int id = p->at(j);
            std::cout << qPrintable(vertexIdToLabel[id]);
            if (j != p->size() - 1)
              {
              std::cout << " ";
              }
            }
          if (i != paths.size() - 1)
            {
            std::cout << ";";
            }
          }
        }
      }
    }

  if (outputSort)
    {
    // TODO Make sure label is valid
    QList<int> out;
    int labelId = vertexLabelToId[label];
    if (mygraph.topologicalSort(out, labelId))
      {
      for(int i=0; i < out.size(); i++)
        {
        int id = out.at(i);
        std::cout << qPrintable(vertexIdToLabel[id]);

        if (i != out.size() - 1)
          {
          std::cout << " ";
          }
        }
      }
    }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "server_drv.h"

#include "Arduino.h"
#include "spi_drv.h"

#define _DEBUG_

extern "C" {
#include "wl_types.h"
#include "debug.h"
}

// Start server TCP on port specified
void ServerDrv::StartServer(uint16_t port, uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(START_SERVER_TCP_CMD, PARAM_NUMS_2);
    SpiDrv::sendParam(port);
    SpiDrv::sendParam(&sock, 1, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(START_SERVER_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
}

// Start server TCP on port specified
void ServerDrv::StartClient(uint32_t ipAddress, uint16_t port, uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
	INFO2(ipAddress,port);
    // Send Command
    SpiDrv::sendCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_3);
    SpiDrv::sendParam((uint8_t*)&ipAddress, sizeof(ipAddress));
    SpiDrv::sendParam(port);
    SpiDrv::sendParam(&sock, 1, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
}

uint8_t ServerDrv::getState(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
   return _data;
}

uint8_t ServerDrv::availData(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();

    if (_dataLen!=0)
    {
        return (_data == 1);
    }
    return false;
}

bool ServerDrv::getData(uint8_t sock, uint8_t *data)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_DATA_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseData8(GET_DATA_TCP_CMD, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (_dataLen!=0)
    {
        *data = _data;
        return true;
    }
    return false;
}

bool ServerDrv::getDataBuf(uint8_t sock, uint8_t *_data, uint16_t *_dataLen)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_DATABUF_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendBuffer(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    if (!SpiDrv::waitResponseData16(GET_DATABUF_TCP_CMD, _data, _dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (*_dataLen!=0)
    {
        return true;
    }
    return false;
}

bool ServerDrv::sendData(uint8_t sock, const uint8_t *data, uint16_t len)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(SEND_DATA_TCP_CMD, PARAM_NUMS_2);
    SpiDrv::sendBuffer(&sock, sizeof(sock));
    SpiDrv::sendBuffer((uint8_t *)data, len, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseData8(SEND_DATA_TCP_CMD, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (_dataLen!=0)
    {
        return (_data == 1);
    }
    return false;
}

uint8_t ServerDrv::isDataSent(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(DATA_SENT_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(DATA_SENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse isDataSent");
    }
    SpiDrv::spiSlaveDeselect();

    return _data;
}

ServerDrv serverDrv;
<commit_msg>delete some debug print<commit_after>#include "server_drv.h"

#include "Arduino.h"
#include "spi_drv.h"

#define _DEBUG_

extern "C" {
#include "wl_types.h"
#include "debug.h"
}

// Start server TCP on port specified
void ServerDrv::StartServer(uint16_t port, uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(START_SERVER_TCP_CMD, PARAM_NUMS_2);
    SpiDrv::sendParam(port);
    SpiDrv::sendParam(&sock, 1, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(START_SERVER_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
}

// Start server TCP on port specified
void ServerDrv::StartClient(uint32_t ipAddress, uint16_t port, uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_3);
    SpiDrv::sendParam((uint8_t*)&ipAddress, sizeof(ipAddress));
    SpiDrv::sendParam(port);
    SpiDrv::sendParam(&sock, 1, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
}

uint8_t ServerDrv::getState(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(GET_STATE_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
   return _data;
}

uint8_t ServerDrv::availData(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(AVAIL_DATA_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();

    if (_dataLen!=0)
    {
        return (_data == 1);
    }
    return false;
}

bool ServerDrv::getData(uint8_t sock, uint8_t *data)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_DATA_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseData8(GET_DATA_TCP_CMD, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (_dataLen!=0)
    {
        *data = _data;
        return true;
    }
    return false;
}

bool ServerDrv::getDataBuf(uint8_t sock, uint8_t *_data, uint16_t *_dataLen)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(GET_DATABUF_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendBuffer(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    if (!SpiDrv::waitResponseData16(GET_DATABUF_TCP_CMD, _data, _dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (*_dataLen!=0)
    {
        return true;
    }
    return false;
}

bool ServerDrv::sendData(uint8_t sock, const uint8_t *data, uint16_t len)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(SEND_DATA_TCP_CMD, PARAM_NUMS_2);
    SpiDrv::sendBuffer(&sock, sizeof(sock));
    SpiDrv::sendBuffer((uint8_t *)data, len, LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseData8(SEND_DATA_TCP_CMD, &_data, &_dataLen))
    {
        WARN("error waitResponse");
    }
    SpiDrv::spiSlaveDeselect();
    if (_dataLen!=0)
    {
        return (_data == 1);
    }
    return false;
}

uint8_t ServerDrv::isDataSent(uint8_t sock)
{
	WAIT_FOR_SLAVE_SELECT();
    // Send Command
    SpiDrv::sendCmd(DATA_SENT_TCP_CMD, PARAM_NUMS_1);
    SpiDrv::sendParam(&sock, sizeof(sock), LAST_PARAM);

    //Wait the reply elaboration
    SpiDrv::waitForSlaveReady();

    // Wait for reply
    uint8_t _data = 0;
    uint8_t _dataLen = 0;
    if (!SpiDrv::waitResponseCmd(DATA_SENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
    {
        WARN("error waitResponse isDataSent");
    }
    SpiDrv::spiSlaveDeselect();

    return _data;
}

ServerDrv serverDrv;
<|endoftext|>