/***********************************************************/
/*                      wxPcbStruct.h:                     */
/*      Classes used in pcbnew, cvpcb and gerbview         */
/***********************************************************/

#ifndef  WXPCB_STRUCT_H
#define  WXPCB_STRUCT_H


#include <vector>

#include "wxstruct.h"
#include "base_struct.h"

#ifndef PCB_INTERNAL_UNIT
#define PCB_INTERNAL_UNIT 10000
#endif


/*  Forward declarations of classes. */
class PCB_SCREEN;
class WinEDA_GerberFrame;       // GERBER viewer main frame
class WinEDA_Toolbar;
class WinEDA_CvpcbFrame;
class WinEDA_PcbFrame;
class WinEDA_ModuleEditFrame;
class BOARD;
class TEXTE_PCB;
class MODULE;
class TRACK;
class SEGZONE;
class SEGVIA;
class D_PAD;
class TEXTE_MODULE;
class MIREPCB;
class COTATION;
class EDGE_MODULE;
class WinEDA3D_DrawFrame;
class DRC;
class ZONE_CONTAINER;
class DRAWSEGMENT;
class GENERAL_COLLECTOR;
class GENERAL_COLLECTORS_GUIDE;


/******************************************************************/
/* class WinEDA_BasePcbFrame: Basic class for pcbnew and gerbview */
/******************************************************************/

class WinEDA_BasePcbFrame : public WinEDA_DrawFrame
{
public:

    bool m_DisplayPadFill;          // How show pads
    bool m_DisplayPadNum;           // show pads numbers

    int  m_DisplayModEdge;          // How show module drawings
    int  m_DisplayModText;          // How show module texts
    bool m_DisplayPcbTrackFill;     /* FALSE : tracks are show in sketch mode, TRUE = filled */
    int m_UserGridUnits;
    wxRealPoint m_UserGridSize;

    WinEDA3D_DrawFrame*     m_Draw3DFrame;
    WinEDA_ModuleEditFrame* m_ModuleEditFrame;

protected:
    BOARD*                  m_Pcb;
    GENERAL_COLLECTOR*      m_Collector;

public:
    WinEDA_BasePcbFrame( wxWindow* father, int idtype,
                         const wxString& title,
                         const wxPoint& pos, const wxSize& size,
                         long style = KICAD_DEFAULT_DRAWFRAME_STYLE );

    ~WinEDA_BasePcbFrame();

    /**
     * Function SetBoard
     * sets the m_Pcb member in such as way as to ensure deleting any previous
     * BOARD.
     * @param aBoard The BOARD to put into the frame.
     */
    void SetBoard( BOARD* aBoard );

    BOARD* GetBoard()
    {
        wxASSERT( m_Pcb );  // phasing out m_Pcb for gerbview
        return m_Pcb;
    }


    // General
    virtual void OnCloseWindow( wxCloseEvent& Event ) = 0;
    virtual void RedrawActiveWindow( wxDC* DC, bool EraseBg ) { }
    virtual void ReCreateHToolbar() = 0;
    virtual void ReCreateVToolbar() = 0;
    virtual void OnLeftClick( wxDC* DC, const wxPoint& MousePos )  = 0;
    virtual void OnLeftDClick( wxDC* DC, const wxPoint& MousePos ) = 0;
    virtual bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu ) = 0;
    virtual void ReCreateMenuBar();
    virtual void SetToolID( int id, int new_cursor_id,
                            const wxString& title );
    virtual void UpdateStatusBar();

    PCB_SCREEN* GetScreen() const { return (PCB_SCREEN*) WinEDA_DrawFrame::GetBaseScreen(); }

    BASE_SCREEN* GetBaseScreen() const;

    int          BestZoom();

    virtual void Show3D_Frame( wxCommandEvent& event );

    virtual void SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
                                     int             flag_type_command = 0 );

private:
    virtual void GetComponentFromUndoList();
    virtual void GetComponentFromRedoList();


public:

    // Read/write fonctions:
    EDA_BaseStruct*          ReadDrawSegmentDescr( FILE* File, int* LineNum );
    int                      ReadListeSegmentDescr( FILE* File,
                                                    TRACK* PtSegm, int StructType,
                                                    int* LineNum, int NumSegm );

    int                      ReadSetup( FILE* File, int* LineNum );
    int                      ReadGeneralDescrPcb( FILE* File, int* LineNum );

    // PCB handling
    bool                     Clear_Pcb( bool query );

    void                     UnDeleteItem( wxDC* DC );
    BOARD_ITEM*              SaveItemEfface( BOARD_ITEM* aItem, int nbitems );


    /**
     * Function PcbGeneralLocateAndDisplay
     * searches for an item under the mouse cursor.
     * Items are searched first on the current working layer.
     * If nothing found, an item will be searched without layer restriction.  If
     * more than one item is found meeting the current working layer criterion, then
     * a popup menu is shown which allows the user to pick which item he/she is
     * interested in.  Once an item is chosen, then it is make the "current item"
     * and the status window is updated to reflect this.
     *
     * @param aHotKeyCode The hotkey which relates to the caller and determines the
     *  type of search to be performed.  If zero, then the mouse tools will be
     *  tested instead.
     */
    BOARD_ITEM*              PcbGeneralLocateAndDisplay( int aHotKeyCode = 0 );

    void                     ProcessItemSelection( wxCommandEvent& event );

    /**
     * Function SetCurItem
     * sets the currently selected item and displays it in the MsgPanel.
     * If the given item is NULL then the MsgPanel is erased and there is no
     * currently selected item. This function is intended to make the process
     * of "selecting" an item more formal, and to indivisibly tie the operation
     * of selecting an item to displaying it using BOARD_ITEM::Display_Infos().
     * @param aItem The BOARD_ITEM to make the selected item or NULL if none.
     */
    void                     SetCurItem( BOARD_ITEM* aItem );
    BOARD_ITEM*              GetCurItem();

    /**
     * Function GetCollectorsGuide
     * @return GENERAL_COLLECTORS_GUIDE - that considers the global configuration options.
     */
    GENERAL_COLLECTORS_GUIDE GetCollectorsGuide();


    /**
     * Function CursorGoto
     * positions the cursor at a given coordinate and reframes the drawing if the
     * requested point is out of view.
     * @param aPos The point to go to.
     */
    void                     CursorGoto(  const wxPoint& aPos );


    /* Place un repere sur l'ecran au point de coordonnees PCB pos */
    void                     place_marqueur( wxDC* DC, const wxPoint& pos, char* pt_bitmap,
                                             int DrawMode, int color, int type );

    // Gestion des modules
    void                     InstallModuleOptionsFrame( MODULE* Module, wxDC * DC );
    MODULE*                  Copie_Module( MODULE* module );
    MODULE*                  Exchange_Module( wxWindow* winaff,
                                              MODULE*   old_module,
                                              MODULE*   new_module );

    /** Function Save_Module_In_Library
     *  Save in an existing library a given footprint
     * @param aLibName = name of the library to use
     * @param aModule = the given footprint
     * @param aOverwrite = true to overwrite an existing footprint, false to abort an existing footprint is found
     * @param aDisplayDialog = true to display a dialog to enter or confirm the footprint name
     * @param aCreateDocFile = true to creates the associated doc file
     * @return : 1 if OK,0 if abort
     */
    int                      Save_Module_In_Library( const wxString& aLibName,
                                                     MODULE* aModule, bool aOverwrite,
                                                     bool aDisplayDialog, bool aCreateDocFile );

    void                     Archive_Modules( const wxString& LibName, bool NewModulesOnly );
    MODULE*                  Select_1_Module_From_BOARD( BOARD* Pcb );
    MODULE*                  GetModuleByName();

    // Modules (footprints)
    MODULE*                  Create_1_Module( wxDC* DC, const wxString& module_name );
    void                     Edit_Module( MODULE* module, wxDC* DC );
    void                     Rotate_Module( wxDC*   DC,
                                            MODULE* module,
                                            int     angle,
                                            bool    incremental );
    void                     Place_Module( MODULE* module, wxDC* DC );
    void                     InstallExchangeModuleFrame( MODULE* ExchangeModuleModule,
                                                         wxDC* DC, const wxPoint& pos );

    // Graphic items edition:
    void                     InstallGraphicItemPropertiesDialog( DRAWSEGMENT* aItem, wxDC* aDC );

    // module texts
    void                     RotateTextModule( TEXTE_MODULE* Text, wxDC* DC );
    void                     DeleteTextModule( TEXTE_MODULE* Text );
    void                     PlaceTexteModule( TEXTE_MODULE* Text, wxDC* DC );
    void                     StartMoveTexteModule( TEXTE_MODULE* Text, wxDC* DC );
    TEXTE_MODULE*            CreateTextModule( MODULE* Module, wxDC* DC );

    void                     InstallPadOptionsFrame( D_PAD* pad, wxDC* DC, const wxPoint& pos );
    void                     InstallTextModOptionsFrame( TEXTE_MODULE* TextMod,
                                                         wxDC* DC, const wxPoint& pos );

    // Pads sur modules
    void                     AddPad( MODULE* Module, bool draw );
    void                     DeletePad( D_PAD* Pad );
    void                     StartMovePad( D_PAD* Pad, wxDC* DC );
    void                     RotatePad( D_PAD* Pad, wxDC* DC );
    void                     PlacePad( D_PAD* Pad, wxDC* DC );
    void                     Export_Pad_Settings( D_PAD* aPad );
    void                     Import_Pad_Settings( D_PAD* aPad, bool aDraw );
    void                     Global_Import_Pad_Settings( D_PAD* aPad, bool aDraw );


    // loading footprints
    /** function Get_Librairie_Module
     *
     *  Read active libraries or one library to find and load a given module
     *  If found the lodule is linked to the tail of linked list of modules
     *  @param aLibrary: the full filename of the library to read. If empty, all active libraries are read
     *  @param aModuleName = module name to load
     *  @param aDisplayMessageError = true to display an error message if any.
     *  @return a MODULE * pointer to the new module, or NULL
     *
     */
    MODULE*                  Get_Librairie_Module( const wxString& aLibraryFullFilename,
                                                   const wxString& aModuleName,
                                                   bool            aDisplayMessageError );

    /** Function Select_1_Module_From_List
     *  Display a list of modules found in active libraries or a given library
     *  @param aLibraryFullFilename = library to list (if aLibraryFullFilename == void, list all modules)
     *  @param aMask = Display filter (wildcart)( Mask = wxEmptyString if not used )
     *  @param aKeyWord = keyword list, to display a filtered list of module having one (or more) of these keyworks in their keywork list
     *    ( aKeyWord = wxEmptyString if not used )
     *
     *  @return wxEmptyString if abort or fails, or the selected module name if Ok
     */
    wxString                 Select_1_Module_From_List(
        WinEDA_DrawFrame* active_window, const wxString& aLibraryFullFilename,
        const wxString& aMask, const wxString& aKeyWord );

    MODULE*                  Load_Module_From_Library( const wxString& library, wxDC* DC );

    //  ratsnest functions
    void                     Compile_Ratsnest( wxDC* DC, bool affiche );    /* Recalcul complet du chevelu */
    int                      Test_1_Net_Ratsnest( wxDC* DC, int net_code );
    void                     build_ratsnest_module( wxDC* DC, MODULE* Module );
    void                     trace_ratsnest_module( wxDC* DC );
    void                     Build_Board_Ratsnest( wxDC* DC );
    void                     DrawGeneralRatsnest( wxDC* DC, int net_code = 0 );
    void                     trace_ratsnest_pad( wxDC* DC );
    void                     build_ratsnest_pad( BOARD_ITEM* ref,
                                                 const wxPoint&  refpos,
                                                 bool            init );

    void                     Tst_Ratsnest( wxDC* DC, int ref_netcode );
    void                     test_connexions( wxDC* DC );
    void                     test_1_net_connexion( wxDC* DC, int net_code );
    void                     RecalculateAllTracksNetcode( );

    // Plotting
    void                     ToPlotter( wxCommandEvent& event );
    void                     Plot_Serigraphie( int format_plot, FILE* File, int masque_layer );
    void                     Genere_GERBER( const wxString& FullFileName, int Layer,
                                            bool PlotOriginIsAuxAxis );
    void                     Genere_HPGL( const wxString& FullFileName, int Layer );
    void                     Genere_PS( const wxString& FullFileName, int Layer, bool useA4 );
    void                     Plot_Layer_HPGL( FILE* File, int masque_layer,
                                              int garde, int tracevia, int modetrace );
    void                     Plot_Layer_GERBER( FILE* File, int masque_layer,
                                                int garde, int tracevia );
    void                     Plot_Layer_PS( FILE* File, int masque_layer,
                                            int garde, int tracevia, int modetrace );

    /* Block operations: */
    /**
     * Function Block_Delete
     * deletes all tracks and segments within the selected block.
     * Defined separately in pcbnew and gerbview
     *
     * @param DC A device context to draw on.
     */
    void                     Block_Delete( wxDC* DC );
    void                     Block_Rotate( wxDC* DC );
    void                     Block_Invert( wxDC* DC );
    /**
     * Function Block_Move
     * moves all tracks and segments within the selected block.
     * New location is determined by the current offset from the selected block's original location.
     * Defined separately in pcbnew and gerbview
     *
     * @param DC A device context to draw on.
     */
    void                     Block_Move( wxDC* DC );
    /**
     * Function Block_Mirror_X
     * mirrors all tracks and segments within the currently selected block in the X axis.
     *
     * @param DC A device context to draw on.
     */
    void                     Block_Mirror_X( wxDC* DC );
    /**
     * Function Block_Duplicate
     * copies-and-moves all tracks and segments within the selected block.
     * New location is determined by the current offset from the selected block's original location.
     * Defined separately in pcbnew and gerbview
     *
     * @param DC A device context to draw on.
     */
     void                     Block_Duplicate( wxDC* DC );


    // layerhandling:
    // (See pcbnew/sel_layer.cpp for description of why null_layer parameter is provided)
    int                      SelectLayer( int default_layer, int min_layer, int max_layer,
                                          bool null_layer = false );
    void                     SelectLayerPair();
    virtual void             SwitchLayer( wxDC* DC, int layer );

    // divers
    void                     AddHistory( int value, KICAD_T type );    // Add value in data list history
    void                     InstallGridFrame( const wxPoint& pos );

    virtual void             LoadSettings();
    virtual void             SaveSettings();

    DECLARE_EVENT_TABLE()
};


/*****************************************************/
/* class WinEDA_PcbFrame: public WinEDA_BasePcbFrame */
/*****************************************************/
class WinEDA_PcbFrame : public WinEDA_BasePcbFrame
{
public:
    WinEDAChoiceBox* m_SelLayerBox;
    WinEDAChoiceBox* m_SelTrackWidthBox;
    WinEDAChoiceBox* m_SelViaSizeBox;

private:
    bool             m_SelTrackWidthBox_Changed;
    bool             m_SelViaSizeBox_Changed;

    DRC*             m_drc;         ///< the DRC controller, see drc.cpp


    // we'll use lower case function names for private member functions.
    void createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* aPopMenu );
    void createPopUpMenuForFootprints( MODULE* aModule, wxMenu* aPopMenu );
    void createPopUpMenuForFpTexts( TEXTE_MODULE* aText, wxMenu* aPopMenu );
    void createPopUpMenuForFpPads( D_PAD* aPad, wxMenu* aPopMenu );
    void createPopupMenuForTracks( TRACK* aTrack, wxMenu* aPopMenu );
    void createPopUpMenuForTexts( TEXTE_PCB* Text, wxMenu* menu );
    void createPopUpBlockMenu( wxMenu* menu );

public:
    WinEDA_PcbFrame( wxWindow* father, const wxString& title,
                     const wxPoint& pos, const wxSize& size,
                     long style = KICAD_DEFAULT_DRAWFRAME_STYLE );

    ~WinEDA_PcbFrame();

    void             GetKicadAbout( wxCommandEvent& event );

    // Configurations:
    void             InstallConfigFrame( const wxPoint& pos );
    void             Process_Config( wxCommandEvent& event );
    void             Update_config( wxWindow* displayframe );
    void             OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
    bool             OnHotkeyDeleteItem( wxDC* DC, EDA_BaseStruct* DrawStruct );

    void             OnCloseWindow( wxCloseEvent& Event );
    void             Process_Special_Functions( wxCommandEvent& event );

    void             ProcessMuWaveFunctions( wxCommandEvent& event );
    void             MuWaveCommand( wxDC* DC, const wxPoint& MousePos );

    void             RedrawActiveWindow( wxDC* DC, bool EraseBg );
    void             ReCreateHToolbar();
    void             ReCreateAuxiliaryToolbar();
    void             ReCreateVToolbar();
    void             ReCreateAuxVToolbar();
    void             ReCreateOptToolbar();
    void             ReCreateMenuBar();
    WinEDAChoiceBox* ReCreateLayerBox( WinEDA_Toolbar* parent );

    void             Show3D_Frame( wxCommandEvent& event );
    void             GeneralControle( wxDC* DC, wxPoint Mouse );

    /**
     * Function UpdateToolbarLayerInfo
     * updates the currently selected layer in the layer listbox and
     * the colored icon in the toolbar.
     */
    void             UpdateToolbarLayerInfo();

    void             PrepareLayerIndicator();
    void             OnLeftClick( wxDC* DC, const wxPoint& MousePos );
    void             OnLeftDClick( wxDC* DC, const wxPoint& MousePos );

    /**
     * Function OnRightClick
     * populates a popup menu with the choices appropriate for the current context.
     * The caller will add the ZOOM menu choices afterwards.
     * @param aMousePos The current mouse position
     * @param aPopMenu The menu to add to.
     */
    bool             OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu );

    void             OnSelectOptionToolbar( wxCommandEvent& event );
    void             ToolOnRightClick( wxCommandEvent& event );

    /* Gestion generale des operations sur block */
    int              ReturnBlockCommand( int key );
    void             HandleBlockPlace( wxDC* DC );
    int              HandleBlockEnd( wxDC* DC );

    void             SetToolbars();
    void             Process_Settings( wxCommandEvent& event );
    void             InstallPcbOptionsFrame( const wxPoint& pos, wxDC* DC, int id );
    void             InstallPcbGlobalDeleteFrame( const wxPoint& pos );

    void             GenModulesPosition( wxCommandEvent& event );
    void             GenModuleReport( wxCommandEvent& event );
    void             InstallDrillFrame( wxCommandEvent& event );
    void             ToPostProcess( wxCommandEvent& event );

    void             OnFileHistory( wxCommandEvent& event );
    void             Files_io( wxCommandEvent& event );
    int              LoadOnePcbFile( const wxString& FileName, bool Append );
    int              ReadPcbFile( FILE* File, bool Append );
    bool             SavePcbFile( const wxString& FileName );
    int              SavePcbFormatAscii( FILE* File );
    bool             WriteGeneralDescrPcb( FILE* File );

    /**
     * Function RecreateBOMFileFromBoard
     * Recreates a .cmp file from the current loaded board
     * this is the same as created by cvpcb.
     * can be used if this file is lost
     */
    void             RecreateCmpFileFromBoard(wxCommandEvent & aEvent);

    /**
     * Function RecreateBOMFileFromBoard
     * Creates a BOM file from the current loaded board
     */
    void             RecreateBOMFileFromBoard(wxCommandEvent & aEvent);

    void             ExportToGenCAD( wxCommandEvent& event );

    /**
     * Function ExporttoSPECCTRA
     * will export the current BOARD to a specctra dsn file.  See
     * See http://www.autotraxeda.com/docs/SPECCTRA/SPECCTRA.pdf for the
     * specification.
     */
    void             ExportToSpecctra( wxCommandEvent& event );

    /**
     * Function ImportSpecctraSession
     * will import a specctra *.ses file and use it to relocate MODULEs and
     * to replace all vias and tracks in an existing and loaded BOARD.
     * See http://www.autotraxeda.com/docs/SPECCTRA/SPECCTRA.pdf for the
     * specification.
     */
    void             ImportSpecctraSession( wxCommandEvent& event );

    /**
     * Function ImportSpecctraDesign
     * will import a specctra *.dsn file and use it to replace an entire BOARD.
     * The new board will not have any graphics, only components, tracks and vias.
     * See http://www.autotraxeda.com/docs/SPECCTRA/SPECCTRA.pdf for the
     * specification.
     */
    void             ImportSpecctraDesign( wxCommandEvent& event );

    /**
     * Function Access_to_External_Tool
     * Run an external tool (like freeroute )
     */
    void             Access_to_External_Tool( wxCommandEvent& event );

    /* Fonctions specifiques */
    MODULE*          ListAndSelectModuleName();

    /** Function ListNetsAndSelect
     * called by a command event
     * displays the sorted list of nets in a dialog frame
     * If a net is selected, it is hightlighted
     */
    void             ListNetsAndSelect( wxCommandEvent& event );

    void             Swap_Layers( wxCommandEvent& event );
    void             Install_Test_DRC_Frame( wxDC* DC );

    // Handling texts on the board
    void             Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );
    TEXTE_PCB*       Create_Texte_Pcb( wxDC* DC );
    void             Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );
    void             StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC );
    void             Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );
    void             InstallTextPCBOptionsFrame( TEXTE_PCB* TextPCB, wxDC* DC );

    // Graphic Segments type DRAWSEGMENT
    void             Start_Move_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC );
    void             Place_DrawItem( DRAWSEGMENT* drawitem, wxDC* DC );

    // Footprint edition (see also WinEDA_BasePcbFrame)
    void             StartMove_Module( MODULE* module, wxDC* DC );
    bool             Delete_Module( MODULE* module, wxDC* DC, bool aAskBeforeDeleting );

    // loading modules: see WinEDA_BasePcbFrame

    // Board handling
    void             Erase_Zones( bool query );
    void             Erase_Segments_Pcb( bool is_edges, bool query );
    void             Erase_Pistes( wxDC* DC, int masque_type, bool query );
    void             Erase_Modules( bool query );
    void             Erase_Textes_Pcb( bool query );
    void             Erase_Marqueurs();
    void             RemoveStruct( BOARD_ITEM* Item, wxDC* DC );
    void             Via_Edit_Control( wxDC* DC, int command_type, SEGVIA* via );

    // Hightlight functions:
    int              Select_High_Light( wxDC* DC );
    void             Hight_Light( wxDC* DC );

    // Track and via edition:
    void             DisplayTrackSettings();

    /**
     * Function Other_Layer_Route
     * operates in one of two ways.  If argument track is NULL, then swap the active
     * layer between m_Route_Layer_TOP and m_Route_Layer_BOTTOM.  If a track is
     * in progress (track is not NULL), and if DRC allows it, place a via on the end
     * of the current track, and then swap the current active layer and start a new
     * segment on the new layer.
     * @param track A TRACK* to append the via to or NULL.
     * @param DC A device context to draw on.
     * @return bool - true if the operation was successful, else false such as
     *   the case where DRC would not allow a via.
     */
    bool             Other_Layer_Route( TRACK* track, wxDC* DC );
    void             Affiche_PadsNoConnect( wxDC* DC );
    void             Affiche_Status_Net( wxDC* DC );
    TRACK*           Delete_Segment( wxDC* DC, TRACK* Track );
    void             Delete_Track( wxDC* DC, TRACK* Track );
    void             Delete_net( wxDC* DC, TRACK* Track );
    void             Remove_One_Track( wxDC* DC, TRACK* pt_segm );
    bool             Resize_Pistes_Vias( wxDC* DC, bool Track, bool Via );
    void             Edit_Net_Width( wxDC* DC, int Netcode );
    void             Edit_Track_Width( wxDC* DC, TRACK* Track );
    int              Edit_TrackSegm_Width( wxDC* DC, TRACK* segm );
    TRACK*           Begin_Route( TRACK* track, wxDC* DC );
    void             End_Route( TRACK* track, wxDC* DC );
    void             ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC );
    void             Attribut_Segment( TRACK* track, wxDC* DC, bool Flag_On );
    void             Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On );
    void             Attribut_net( wxDC* DC, int net_code, bool Flag_On );
    void             Start_MoveOneNodeOrSegment( TRACK* track, wxDC* DC, int command );
    bool             PlaceDraggedTrackSegment( TRACK* Track, wxDC* DC );
    bool             MergeCollinearTracks( TRACK* track, wxDC* DC, int end );
    void             Start_DragTrackSegmentAndKeepSlope( TRACK* track, wxDC* DC );
    void             SwitchLayer( wxDC* DC, int layer );
    bool             Add_45_degrees_Segment( wxDC* DC );
    bool             Genere_Pad_Connexion( wxDC* DC, int layer );

    // zone handling

    /** Function Delete_Zone_Fill
     * Remove the zone filling which include the segment aZone, or the zone which have the given time stamp.
     *  A zone is a group of segments which have the same TimeStamp
     * @param DC = current Device Context (can be NULL)
     * @param aZone = zone segment within the zone to delete. Can be NULL
     * @param aTimestamp = Timestamp for the zone to delete, used if aZone == NULL
     */
    void             Delete_Zone_Fill( wxDC* DC, SEGZONE* Track, long aTimestamp = 0 );


    /** Function Delete_LastCreatedCorner
     * Used only while creating a new zone outline
     * Remove and delete the current outline segment in progress
     * @return 0 if no corner in list, or corner number
     */
    int              Delete_LastCreatedCorner( wxDC* DC );

    /**
     * Function Begin_Zone
     * initiates a zone edge creation process,
     * or terminates the current zone edge and creates a new zone edge stub
     */
    int              Begin_Zone( wxDC* DC );

    /**
     * Function End_Zone
     * terminates (if no DRC error ) the zone edge creation process
     * @param DC = current Device Context
     * @return true if Ok, false if DRC error
     */
    bool             End_Zone( wxDC* DC );

    /** Function Fill_Zone()
     *  Calculate the zone filling for the outline zone_container
     *  The zone outline is a frontier, and can be complex (with holes)
     *  The filling starts from starting points like pads, tracks.
     * If exists the old filling is removed
     * @param DC = current Device Context
     * @param zone_container = zone to fill
     * @param verbose = true to show error messages
     * @return error level (0 = no error)
     */
    int              Fill_Zone( wxDC* DC, ZONE_CONTAINER* zone_container, bool verbose = TRUE );

    /** Function Fill_All_Zones()
     *  Fill all zones on the board
     * The old fillings are removed
     * @param verbose = true to show error messages
     * @return error level (0 = no error)
     */
    int              Fill_All_Zones( bool verbose = TRUE );


    /**
     * Function Add_Zone_Cutout
     * Add a cutout zone to a given zone outline
     * @param DC = current Device Context
     * @param zone_container = parent zone outline
     */
    void             Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* zone_container );

    /**
     * Function Add_Similar_Zone
     * Add a zone to a given zone outline.
     * if the zones are overlappeing they will be merged
     * @param DC = current Device Context
     * @param zone_container = parent zone outline
     */
    void             Add_Similar_Zone( wxDC* DC, ZONE_CONTAINER* zone_container );

    /**
     * Function Edit_Zone_Params
     * Edit params (layer, clearance, ...) for a zone outline
     */
    void             Edit_Zone_Params( wxDC* DC, ZONE_CONTAINER* zone_container );

    /**
     * Function Start_Move_Zone_Corner
     * Prepares a move corner in a zone outline,
     * called from a move corner command (IsNewCorner = false),
     * or a create new cornet command (IsNewCorner = true )
     */
    void             Start_Move_Zone_Corner( wxDC*           DC,
                                             ZONE_CONTAINER* zone_container,
                                             int             corner_id,
                                             bool            IsNewCorner );

    /**
     * Function Start_Move_Zone_Corner
     * Prepares a drag edge in an existing zone outline,
     */
    void         Start_Move_Zone_Drag_Outline_Edge( wxDC*           DC,
                                                    ZONE_CONTAINER* zone_container,
                                                    int             corner_id );

    /**
     * Function End_Move_Zone_Corner_Or_Outlines
     * Terminates a move corner in a zone outline, or a move zone outlines
     * @param DC = current Device Context (can be NULL)
     * @param zone_container: the given zone
     */
    void         End_Move_Zone_Corner_Or_Outlines( wxDC* DC, ZONE_CONTAINER* zone_container );

    /**
     * Function End_Move_Zone_Corner_Or_Outlines
     * Remove the currently selected corner in a zone outline
     * the .m_CornerSelection is used as corner selection
     */
    void         Remove_Zone_Corner( wxDC* DC, ZONE_CONTAINER* zone_container );

    /** Function Delete_Zone
     * Remove the zone which include the segment aZone, or the zone which have the given time stamp.
     *  A zone is a group of segments which have the same TimeStamp
     * @param DC = current Device Context (can be NULL)
     * @param zone_container = zone to modify
     *  the member .m_CornerSelection is used to find the outline to remove.
     * if the outline is the main outline, all the zone is removed
     * otherwise, the hole is deleted
     */
    void         Delete_Zone_Contour( wxDC* DC, ZONE_CONTAINER* zone_container );

    /**
     * Function Start_Move_Zone_Outlines
     * Initialise parametres to move an existing zone outlines.
     * @param DC = current Device Context (can be NULL)
     * @param zone_container: the given zone to move
     */
    void         Start_Move_Zone_Outlines( wxDC* DC, ZONE_CONTAINER* zone_container );

    // Target handling
    MIREPCB*     Create_Mire( wxDC* DC );
    void         Delete_Mire( MIREPCB* MirePcb, wxDC* DC );
    void         StartMove_Mire( MIREPCB* MirePcb, wxDC* DC );
    void         Place_Mire( MIREPCB* MirePcb, wxDC* DC );
    void         InstallMireOptionsFrame( MIREPCB* MirePcb, wxDC* DC, const wxPoint& pos );

    // Graphic segments type DRAWSEGMENT handling:
    DRAWSEGMENT* Begin_DrawSegment( DRAWSEGMENT* Segment, int shape, wxDC* DC );
    void         End_Edge( DRAWSEGMENT* Segment, wxDC* DC );
    void         Delete_Segment_Edge( DRAWSEGMENT* Segment, wxDC* DC );
    void         Delete_Drawings_All_Layer( DRAWSEGMENT* Segment, wxDC* DC );

    // Dimension handling:
    void         Install_Edit_Cotation( COTATION* Cotation, wxDC* DC, const wxPoint& pos );
    COTATION*    Begin_Cotation( COTATION* Cotation, wxDC* DC );
    void         Delete_Cotation( COTATION* Cotation, wxDC* DC );


    // netlist  handling:
    void         InstallNetlistFrame( wxDC* DC, const wxPoint& pos );

    // Autoplacement:
    void         AutoPlace( wxCommandEvent& event );

    /** function OnOrientFootprints
     * install the dialog box for the comman Orient Footprints
     */
    void         OnOrientFootprints( void );

    /** function ReOrientModules
     * Set the orientation of footprints
     * @param ModuleMask = mask (wildcard allowed) selection
     * @param Orient = new orientation
     * @param include_fixe = true to orient locked footprints
     */
    void         ReOrientModules( const wxString& ModuleMask, int Orient,
                                  bool include_fixe );
    void         FixeModule( MODULE* Module, bool Fixe );
    void         AutoMoveModulesOnPcb( wxDC* DC, bool PlaceModulesHorsPcb );
    bool         SetBoardBoundaryBoxFromEdgesOnly();
    void         AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC );
    int          RecherchePlacementModule( MODULE* Module, wxDC* DC );
    void         GenModuleOnBoard( MODULE* Module );
    float        Compute_Ratsnest_PlaceModule( wxDC* DC );
    int          GenPlaceBoard();
    void         DrawInfoPlace( wxDC* DC );

    // Autorouting:
    int          Solve( wxDC* DC, int two_sides );
    void         Reset_Noroutable( wxDC* DC );
    void         Autoroute( wxDC* DC, int mode );
    void         ReadAutoroutedTracks( wxDC* DC );
    void         GlobalRoute( wxDC* DC );

    // divers
    void         Show_1_Ratsnest( EDA_BaseStruct* item, wxDC* DC );
    void         Ratsnest_On_Off( wxDC* DC );
    void         Clean_Pcb( wxDC* DC );

    void         InstallFindFrame( const wxPoint& pos, wxDC* DC );

    /**
     * Function SendMessageToEESCHEMA
     * sends a message to the schematic editor so that it may move its cursor
     * to a part with the same reference as the objectToSync
     * @param objectToSync The object whose reference is used to syncronize eeschema.
     */
    void         SendMessageToEESCHEMA( BOARD_ITEM* objectToSync );

    /* Micro waves functions */
    void         Edit_Gap( wxDC* DC, MODULE* Module );
    MODULE*      Create_MuWaveBasicShape( const wxString& name, int pad_count );
    MODULE*      Create_MuWaveComponent( int shape_type );
    MODULE*      Create_MuWavePolygonShape();
    void         Begin_Self( wxDC* DC );
    MODULE*      Genere_Self( wxDC* DC );

    DECLARE_EVENT_TABLE()
};


/****************************************************/
/* class WinEDA_GerberFrame: public WinEDA_PcbFrame */
/****************************************************/

class WinEDA_GerberFrame : public WinEDA_BasePcbFrame
{
public:
    WinEDAChoiceBox* m_SelLayerBox;
    WinEDAChoiceBox* m_SelLayerTool;

public:
    WinEDA_GerberFrame( wxWindow* father, const wxString& title,
                        const wxPoint& pos, const wxSize& size,
                        long style = KICAD_DEFAULT_DRAWFRAME_STYLE );

    ~WinEDA_GerberFrame();

    void         Update_config();
    void         OnCloseWindow( wxCloseEvent& Event );
    void         Process_Special_Functions( wxCommandEvent& event );
    void         RedrawActiveWindow( wxDC* DC, bool EraseBg );
    void         ReCreateHToolbar();
    void         ReCreateVToolbar();
    void         ReCreateOptToolbar();
    void         ReCreateMenuBar();
    void         OnLeftClick( wxDC* DC, const wxPoint& MousePos );
    void         OnLeftDClick( wxDC* DC, const wxPoint& MousePos );
    bool         OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
    int          BestZoom();    // Retourne le meilleur zoom
    void         OnSelectOptionToolbar( wxCommandEvent& event );
    void         OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );

    BOARD_ITEM*  GerberGeneralLocateAndDisplay();
    BOARD_ITEM*  Locate( int typeloc );


    void         SetToolbars();
    void         Process_Settings( wxCommandEvent& event );
    void         Process_Config( wxCommandEvent& event );
    void         InstallConfigFrame( const wxPoint& pos );
    void         InstallPcbOptionsFrame( const wxPoint& pos, int id );
    void         InstallPcbGlobalDeleteFrame( const wxPoint& pos );

    /* handlers for block commands */
    int          ReturnBlockCommand( int key );
    virtual void HandleBlockPlace( wxDC* DC );
    virtual int  HandleBlockEnd( wxDC* DC );

    void         InstallDrillFrame( wxCommandEvent& event );
    void         ToPostProcess( wxCommandEvent& event );
    void         Genere_HPGL( const wxString& FullFileName, int Layers );
    void         Genere_GERBER( const wxString& FullFileName, int Layers );
    void         Genere_PS( const wxString& FullFileName, int Layers );
    void         Plot_Layer_HPGL( FILE* File, int masque_layer,
                                  int garde, int tracevia, int modetrace );
    void         Plot_Layer_GERBER( FILE* File, int masque_layer,
                                    int garde, int tracevia );
    int          Gen_D_CODE_File( const wxString& Name_File );
    void         Plot_Layer_PS( FILE* File, int masque_layer,
                                int garde, int tracevia, int modetrace );

    void         Files_io( wxCommandEvent& event );
    void         OnFileHistory( wxCommandEvent& event );
    bool         LoadOneGerberFile( const wxString& FileName, wxDC* DC, int mode );
    int          ReadGerberFile( wxDC* DC, FILE* File, bool Append );
    bool         Read_GERBER_File( wxDC*           DC,
                                   const wxString& GERBER_FullFileName,
                                   const wxString& D_Code_FullFileName );
    bool         SaveGerberFile( const wxString& FileName, wxDC* DC );

    void         GeneralControle( wxDC* DC, wxPoint Mouse );


    /**
     * Function Read_D_Code_File
     * reads in a dcode file assuming ALSPCB file format with ';' indicating comments.
     * <p>
     * Format is like CSV but with optional ';' delineated comments:<br>
     * tool,	 Horiz,		  Vert,	  drill, vitesse, acc. ,Type ; [DCODE (commentaire)]<br>
     * ex:	   1,		  12,		12,		0,		  0,	 0,	  3 ; D10
     * <p>
     * Format:<br>
     * Ver,  Hor, Type, Tool [,Drill]<br>
     * example:	0.012, 0.012,  L   , D10<br>
     *
     * Categorize all found dcodes into a table of D_CODE instantiations.
     * @param D_CodeFullFileName The name of the file to read from.
     * @return int - <br>
     *                 -1 = file not found<br>
     *                 -2 = parsing problem<br>
     *                  0 = the \a D_Code_FullFileName is empty, no reading is done but an empty GERBER is put into g_GERBER_List[]<br>
     *                  1 = read OK<br>
     */
    int          Read_D_Code_File( const wxString& D_Code_FullFileName );
    void         CopyDCodesSizeToItems();
    void         Liste_D_Codes( wxDC* DC );

    /* Fonctions specifiques */
    void         Trace_Gerber( wxDC* DC, int draw_mode, int printmasklayer );

    // Copper texts
    void         Rotate_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );
    TEXTE_PCB*   Create_Texte_Pcb( wxDC* DC );
    void         Delete_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );
    void         StartMoveTextePcb( TEXTE_PCB* TextePcb, wxDC* DC );
    void         Place_Texte_Pcb( TEXTE_PCB* TextePcb, wxDC* DC );

    // PCB handling
    bool         Clear_Pcb( bool query );
    void         Erase_Current_Layer( bool query );
    void         Erase_Zones( bool query );
    void         Erase_Segments_Pcb( bool is_edges, bool query );
    void         Erase_Pistes( int masque_type, bool query );
    void         Erase_Textes_Pcb( bool query );
    void         Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number );

    TRACK*       Begin_Route( TRACK* track, wxDC* DC );
    void         End_Route( TRACK* track, wxDC* DC );
    TRACK*       Delete_Segment( wxDC* DC, TRACK* Track );
    int          Edit_TrackSegm_Width( wxDC* DC, TRACK* segm );

    // Conversion function
    void         ExportDataInPcbnewFormat( wxCommandEvent& event );

    DECLARE_EVENT_TABLE()
};


/*********************************************************/
/* class WinEDA_ModuleEditFrame: public WinEDA_DrawFrame */
/* Class for the footprint editor                        */
/*********************************************************/

class WinEDA_ModuleEditFrame : public WinEDA_BasePcbFrame
{
public:
    MODULE*  CurrentModule;
    wxString m_CurrentLib;

public:
    WinEDA_ModuleEditFrame( wxWindow* father,
                            const wxString& title,
                            const wxPoint& pos, const wxSize& size,
                            long style = KICAD_DEFAULT_DRAWFRAME_STYLE );

    ~WinEDA_ModuleEditFrame();

    void         InstallOptionsFrame( const wxPoint& pos );

    void         OnCloseWindow( wxCloseEvent& Event );
    void         Process_Special_Functions( wxCommandEvent& event );
    void         RedrawActiveWindow( wxDC* DC, bool EraseBg );
    void         ReCreateHToolbar();
    void         ReCreateVToolbar();
    void         ReCreateOptToolbar();
    void         ReCreateAuxiliaryToolbar();
    void         OnLeftClick( wxDC* DC, const wxPoint& MousePos );
    void         OnLeftDClick( wxDC* DC, const wxPoint& MousePos );
    bool         OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
    void         SetToolbars();
    void         ReCreateMenuBar();
    void         ToolOnRightClick( wxCommandEvent& event );
    void         OnSelectOptionToolbar( wxCommandEvent& event );
    void         OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
    void         Show3D_Frame( wxCommandEvent& event );
    void         GeneralControle( wxDC* DC, wxPoint Mouse );
    virtual void OnSelectGrid( wxCommandEvent& event );
    void         LoadModuleFromBoard( wxCommandEvent& event );

    /* handlers for block commands */
    int          ReturnBlockCommand( int key );
    virtual void HandleBlockPlace( wxDC* DC );
    virtual int  HandleBlockEnd( wxDC* DC );

    BOARD_ITEM*  ModeditLocateAndDisplay( int aHotKeyCode = 0 );

    /* Undo and redo functions */
public:
    void         SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, int flag_type_command = 0 );

private:
    void         GetComponentFromUndoList();
    void         GetComponentFromRedoList();

public:

    // Footprint edition
    void         Place_Ancre( MODULE* module );
    void         RemoveStruct( EDA_BaseStruct* Item );
    void         Transform( MODULE* module, int transform );

    // loading Footprint
    MODULE*      Import_Module( wxDC* DC );
    void         Export_Module( MODULE* ptmod, bool createlib );
    void         Load_Module_From_BOARD( MODULE* Module );

    // functions to edit footprint edges
    void         Edit_Edge_Width( EDGE_MODULE* Edge );
    void         Edit_Edge_Layer( EDGE_MODULE* Edge );
    void         Delete_Edge_Module( EDGE_MODULE* Edge );
    EDGE_MODULE* Begin_Edge_Module( EDGE_MODULE* Edge, wxDC* DC, int type_edge );
    void         End_Edge_Module( EDGE_MODULE* Edge, wxDC* DC );
    void         Enter_Edge_Width( EDGE_MODULE* Edge, wxDC* DC );
    void         Start_Move_EdgeMod( EDGE_MODULE* drawitem, wxDC* DC );
    void         Place_EdgeMod( EDGE_MODULE* drawitem, wxDC* DC );

    // handlers for libraries:
    void         Delete_Module_In_Library( const wxString& libname );
    int          Create_Librairie( const wxString& LibName );
    void         Select_Active_Library();

    DECLARE_EVENT_TABLE()
};

#endif  /* WXPCB_STRUCT_H */
