From d2da52b215a5b0942f96eafbe9347317c3b9f456 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Mon, 27 Dec 2010 22:59:52 -0300 Subject: [PATCH] Patches to enhance KiCad, mainly for non-interactive use - README: description of the build process - series: control file for quilt - eeschema-plot-only-mode.patch, erc-exceptions.patch, fix-pinedit-collision.patch, streamline-erc.patch: patches carried over from svn.openmoko.org/trunk/gta02-core/kicad-patches/ - eeschema-bom-only-mode.patch: adds support for eeschema --bom mode to only create a bom .lst file (by Wolfgang Spraul) - pcbnew-scripted.patch: adds several command line parameters to pcbnew (by Wolfgang Spraul) --- kicad-patches/README | 5 + kicad-patches/eeschema-bom-only-mode.patch | 164 +++++ kicad-patches/eeschema-plot-only-mode.patch | 110 +++ kicad-patches/erc-exceptions.patch | 275 +++++++ kicad-patches/fix-pinedit-collision.patch | 28 + kicad-patches/pcbnew-scripted.patch | 747 ++++++++++++++++++++ kicad-patches/series | 21 + kicad-patches/streamline-erc.patch | 52 ++ 8 files changed, 1402 insertions(+) create mode 100644 kicad-patches/README create mode 100644 kicad-patches/eeschema-bom-only-mode.patch create mode 100644 kicad-patches/eeschema-plot-only-mode.patch create mode 100644 kicad-patches/erc-exceptions.patch create mode 100644 kicad-patches/fix-pinedit-collision.patch create mode 100644 kicad-patches/pcbnew-scripted.patch create mode 100644 kicad-patches/series create mode 100644 kicad-patches/streamline-erc.patch diff --git a/kicad-patches/README b/kicad-patches/README new file mode 100644 index 0000000..5e7a86c --- /dev/null +++ b/kicad-patches/README @@ -0,0 +1,5 @@ +bzr checkout -r 2448 lp:kicad kicad.bzr +cd kicad.bzr +cmake . +make -j 5 +make install diff --git a/kicad-patches/eeschema-bom-only-mode.patch b/kicad-patches/eeschema-bom-only-mode.patch new file mode 100644 index 0000000..ea85f93 --- /dev/null +++ b/kicad-patches/eeschema-bom-only-mode.patch @@ -0,0 +1,164 @@ +This patch adds support for eeschema --bom mode to only create +a bom .lst file. + +Index: kicad/eeschema/cmdline.h +=================================================================== +--- kicad.orig/eeschema/cmdline.h 1970-01-01 00:00:00.000000000 +0000 ++++ kicad/eeschema/cmdline.h 2010-12-21 22:09:57.225291237 +0000 +@@ -0,0 +1,26 @@ ++///////////////////////////////////////////////////////////////////////////// ++// Name: cmdline.h ++// Copyright: Wolfgang Spraul ++// Licence: GPL v3 or higher ++///////////////////////////////////////////////////////////////////////////// ++ ++#include "fctsys.h" ++#include "appl_wxstruct.h" ++#include "common.h" ++ ++#include "program.h" ++#include "general.h" ++#include "netlist.h" ++ ++#include "wx/valgen.h" ++ ++#include "dialog_build_BOM.h" ++ ++class cmdline_bom : public DIALOG_BUILD_BOM ++{ ++public: ++ cmdline_bom( WinEDA_DrawFrame* parent ) : DIALOG_BUILD_BOM( parent ) {} ++ void write_bom(); ++}; ++ ++void BomOnly( WinEDA_App* app ); + +Index: kicad/eeschema/cmdline.cpp +=================================================================== +--- kicad.orig/eeschema/cmdline.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ kicad/eeschema/cmdline.cpp 2010-12-21 22:09:57.225291237 +0000 +@@ -0,0 +1,75 @@ ++///////////////////////////////////////////////////////////////////////////// ++// Name: cmdline.cpp ++// Copyright: Wolfgang Spraul ++// Licence: GPL v3 or higher ++///////////////////////////////////////////////////////////////////////////// ++ ++#include "fctsys.h" ++#include "appl_wxstruct.h" ++#include "common.h" ++ ++#include "program.h" ++#include "general.h" ++#include "netlist.h" ++#include "protos.h" ++ ++#include "wx/valgen.h" ++ ++#include "dialog_build_BOM.h" ++#include "cmdline.h" ++ ++void cmdline_bom::write_bom() ++{ ++ wxFileName fn2 = g_RootSheet->m_AssociatedScreen->m_FileName; ++ fn2.SetExt( wxT( "lst" ) ); ++ m_ListCmpbyRefItems->SetValue( true ); ++ m_AddFootprintField->SetValue( true ); ++ m_AddAllFields->SetValue( true ); ++ GenereListeOfItems( fn2.GetFullPath(), false /* aIncludeSubComponents */ ); ++} ++ ++void BomOnly( WinEDA_App* app ) ++{ ++ WinEDA_SchematicFrame* frame; ++ wxFileName fn; ++ ++ if( app->argc < 3 ) ++ { ++ fprintf( stderr, "usage: %ls [[--bom] filename]\n", *app->argv ); ++ exit( 1 ); ++ } ++ ++ fn = app->argv[2]; ++ if( !fn.IsOk() ) ++ { ++ fprintf( stderr, "%ls: bad name\n", app->argv[2] ); ++ exit(1); ++ } ++ ++ /* init EESCHEMA */ ++ SeedLayers(); ++ app->GetSettings( FALSE ); ++ ++ // Create main frame (schematic frame) : ++ frame = new WinEDA_SchematicFrame( NULL, wxT( "EESchema" ), ++ wxPoint( 0, 0 ), wxSize( 600, 400 ) ); ++ ++ app->SetTopWindow( frame ); ++ frame->Show( FALSE ); ++ ++ ActiveScreen = frame->GetScreen(); ++ ++ /* Load file specified in the command line. */ ++ if( fn.GetExt() != SchematicFileExtension ) ++ fn.SetExt( SchematicFileExtension ); ++ wxSetWorkingDirectory( fn.GetPath() ); ++ if( !frame->LoadOneEEProject( fn.GetFullPath(), false ) ) ++ { ++ fprintf( stderr, "%ls: can't load\n", app->argv[2] ); ++ exit( 1 ); ++ } ++ ++ cmdline_bom* bom_dlg = new cmdline_bom( frame ); ++ bom_dlg->write_bom(); ++ exit( 0 ); ++} + +Index: kicad/eeschema/CMakeLists.txt +=================================================================== +--- kicad.orig/eeschema/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 ++++ kicad/eeschema/CMakeLists.txt 2010-12-21 20:54:28.525291236 +0000 +@@ -32,6 +32,7 @@ + class_text-label.cpp + classes_body_items.cpp + cleanup.cpp ++ cmdline.cpp + cmp_library_keywords.cpp + cmp_library_lexer.cpp + controle.cpp + +Index: kicad/eeschema/dialog_build_BOM.h +=================================================================== +--- kicad.orig/eeschema/dialog_build_BOM.h 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/eeschema/dialog_build_BOM.h 2010-12-21 21:34:33.645291246 +0000 +@@ -17,7 +17,7 @@ + wxConfig* m_Config; + wxString m_ListFileName; + +-private: ++protected: + void OnRadioboxSelectFormatSelected( wxCommandEvent& event ); + void OnOkClick( wxCommandEvent& event ); + void OnCancelClick( wxCommandEvent& event ); + +Index: kicad/eeschema/eeschema.cpp +=================================================================== +--- kicad.orig/eeschema/eeschema.cpp 2010-10-20 07:17:19.418103045 +0000 ++++ kicad/eeschema/eeschema.cpp 2010-12-21 20:46:41.857291236 +0000 +@@ -17,6 +17,7 @@ + #include "program.h" + #include "general.h" + #include "protos.h" ++#include "cmdline.h" + + #include + +@@ -197,6 +198,8 @@ + + if( argc > 1 && !wxStrcmp( argv[1], wxT( "--plot" ) ) ) + PlotOnly( this ); ++ if( argc > 1 && !wxStrcmp( argv[1], wxT( "--bom" ) ) ) ++ BomOnly( this ); + + if( m_Checker && m_Checker->IsAnotherRunning() ) + { diff --git a/kicad-patches/eeschema-plot-only-mode.patch b/kicad-patches/eeschema-plot-only-mode.patch new file mode 100644 index 0000000..cd94bd3 --- /dev/null +++ b/kicad-patches/eeschema-plot-only-mode.patch @@ -0,0 +1,110 @@ +This patch adds a command-line option --plot to eeschema that makes it +run File -> Plot -> Plot PostScript -> Plot ALL on the specified file. +It also prevents eeschema from opening a window and from checking for +concurrent instances. + +This lets shell scripts generate plots, i.e., of schematics that have +been processed by these scripts. + +Known issue: if there is an error or a warning, eeschema will bring up +a dialog instead of just exiting. + +This patch is for KiCad SVN revision 1771. + +- Werner + +--- + +Index: kicad/eeschema/eeschema.cpp +=================================================================== +--- kicad.orig/eeschema/eeschema.cpp 2010-04-28 04:34:54.000000000 -0300 ++++ kicad/eeschema/eeschema.cpp 2010-04-28 05:32:37.000000000 -0300 +@@ -10,6 +10,8 @@ + #include "gestfich.h" + #include "bitmaps.h" + #include "eda_dde.h" ++#include "program.h" ++#include "plotps.h" + #include "id.h" + + #include "program.h" +@@ -85,6 +87,69 @@ + int DefaultTransformMatrix[2][2] = { { 1, 0 }, { 0, -1 } }; + + ++/* ++ * "PlotOnly" is a quick and dirty implementation of a non-interactive plot ++ * mode. ++ * ++ * This is neither a nice nor a complete implementation of this concept. E.g., ++ * if there are any errors, KiCad may bring up a dialog instead of just ++ * exiting. ++ * ++ * However, this is the best we can do without making considerably intrusive ++ * changes to the internals of KiCad. ++ */ ++ ++ ++static void PlotOnly( WinEDA_App* app ) ++{ ++ WinEDA_SchematicFrame* frame; ++ wxFileName fn; ++ ++ if( app->argc < 3 ) ++ { ++ fprintf( stderr, "usage: %ls [[--plot] filename]\n", *app->argv ); ++ exit( 1 ); ++ } ++ ++ fn = app->argv[2]; ++ if( !fn.IsOk() ) ++ { ++ fprintf( stderr, "%ls: bad name\n", app->argv[2] ); ++ exit(1); ++ } ++ ++ /* init EESCHEMA */ ++ SeedLayers(); ++ app->GetSettings( FALSE ); ++ ++ // Create main frame (schematic frame) : ++ frame = new WinEDA_SchematicFrame( NULL, wxT( "EESchema" ), ++ wxPoint( 0, 0 ), wxSize( 600, 400 ) ); ++ ++ app->SetTopWindow( frame ); ++ frame->Show( FALSE ); ++ ++ ActiveScreen = frame->GetScreen(); ++ ++ /* Load file specified in the command line. */ ++ if( fn.GetExt() != SchematicFileExtension ) ++ fn.SetExt( SchematicFileExtension ); ++ wxSetWorkingDirectory( fn.GetPath() ); ++ if( !frame->LoadOneEEProject( fn.GetFullPath(), false ) ) ++ { ++ fprintf( stderr, "%ls: can't load\n", app->argv[2] ); ++ exit( 1 ); ++ } ++ ++ WinEDA_PlotPSFrame* Ps_frame = new WinEDA_PlotPSFrame( frame ); ++ wxCommandEvent dummy; ++ ++ Ps_frame->OnPlotPsAllExecuteClick( dummy ); ++ ++ exit( 0 ); ++} ++ ++ + /************************************/ + /* Called to initialize the program */ + /************************************/ +@@ -127,6 +192,9 @@ + + InitEDA_Appl( wxT( "EESchema" ), APP_TYPE_EESCHEMA ); + ++ if( argc > 1 && !wxStrcmp( argv[1], wxT( "--plot" ) ) ) ++ PlotOnly( this ); ++ + if( m_Checker && m_Checker->IsAnotherRunning() ) + { + if( !IsOK( NULL, _( "Eeschema is already running, Continue?" ) ) ) diff --git a/kicad-patches/erc-exceptions.patch b/kicad-patches/erc-exceptions.patch new file mode 100644 index 0000000..a52a2ff --- /dev/null +++ b/kicad-patches/erc-exceptions.patch @@ -0,0 +1,275 @@ +This patch adds a mechanism to suppress ERC errors and warnings that +are caused by pins incompatibilities. It works by loading a file with +ERC exceptions each time an ERC is performed and then looking for an +entry before issuing a warning or error. + +The file has the same path and name as the .sch file, but ends in .erx +(Electric Rule eXceptions). Each line contains the following four +whitespace-separated fields: + +- component reference of the first component +- pin number of the first component +- component reference of the second component +- pin number of the second component + +# is used as a comment character. Note that the file is reloaded +each time ERC is invoked, so one can edit it in parallel to +running eeschema. + +Known bug: ERC dialog window needs reformatting for displaying the +exception count. + +The patch needs to be applied on top of the TestOthersItems +streamlining patch. + +- Werner + +Updated to rev 1923 + +- Nathael + +--- + +Index: kicad/eeschema/erc.cpp +=================================================================== +--- kicad.orig/eeschema/erc.cpp 2010-04-28 05:40:38.000000000 -0300 ++++ kicad/eeschema/erc.cpp 2010-04-28 05:49:35.000000000 -0300 +@@ -4,6 +4,7 @@ + + #include "fctsys.h" + #include "common.h" ++#include "confirm.h" + #include "class_drawpanel.h" + #include "kicad_string.h" + #include "gestfich.h" +@@ -224,6 +225,173 @@ + } + + ++static struct exception ++{ ++ char* a_ref; ++ char* a_pin; ++ char* b_ref; ++ char* b_pin; ++ char* line; /* pointer to the memory object we've allocated */ ++ struct exception* next; ++}* exceptions; ++ ++ ++ ++static void FreeExceptions( void ) ++{ ++ struct exception* next; ++ ++ while( exceptions ) ++ { ++ next = exceptions->next; ++ MyFree( exceptions->line ); ++ MyFree( exceptions ); ++ exceptions = next; ++ } ++} ++ ++ ++static bool ParseField( char **s, char **field ) ++{ ++ *field = *s; ++ if( ! **s ) ++ return FALSE; ++ while( **s && ! isspace( **s ) ) ++ (*s)++; ++ if( ! **s ) ++ return TRUE; ++ *(*s)++ = 0; ++ while( **s && isspace( **s ) ) ++ (*s)++; ++ return TRUE; ++} ++ ++ ++static bool ParseException( char *s ) ++{ ++ struct exception tmp; ++ struct exception* e; ++ ++ tmp.line = s; ++ ++ if( ! ParseField( &s, &tmp.a_ref)) ++ return FALSE; ++ if( ! ParseField( &s, &tmp.a_pin )) ++ return FALSE; ++ if( ! ParseField( &s, &tmp.b_ref)) ++ return FALSE; ++ if( ! ParseField( &s, &tmp.b_pin )) ++ return FALSE; ++ ++ e = (struct exception*) MyMalloc( sizeof( *e )); ++ *e = tmp; ++ e->next = exceptions; ++ exceptions = e; ++ ++ return TRUE; ++} ++ ++ ++static bool LoadExceptionsByName( const wxString &file_name ) ++{ ++ FILE* file; ++ char buf[200]; /* enough room for chatty comments */ ++ char* s; ++ char* tmp; ++ char* hash; ++ int n = 0; ++ ++ FreeExceptions(); ++ file = wxFopen( file_name, wxT( "r" ) ); ++ if( ! file ) ++ return FALSE; ++ ++ while( 1 ) ++ { ++ s = fgets( buf, sizeof( buf ), file ); ++ if( ! s ) ++ break; ++ ++ n++; ++ ++ // remove comments ++ hash = strchr( s, '#' ); ++ if( hash ) ++ *hash = 0; ++ ++ // skip leading whitespace ++ while( *s && isspace( *s ) ) ++ s++; ++ if( ! *s ) ++ continue; ++ ++ tmp = (char*) MyMalloc( strlen( s ) + 1 ); ++ strcpy( tmp, s ); ++ ++ if( ! ParseException( tmp ) ) ++ { ++ wxString msg; ++ ++ msg.Printf( wxT( "Parse error at %s:%d" ), CONV_TO_UTF8(file_name), n ); ++ DisplayError( NULL, msg ); ++ MyFree( tmp ); ++ break; ++ } ++ } ++ ++ fclose( file ); ++ ++ return TRUE; ++} ++ ++ ++static void LoadExceptions( void ) ++{ ++ wxFileName fn; ++ ++ fn = g_RootSheet->m_AssociatedScreen->m_FileName; ++ fn.SetExt( wxT( "erx" ) ); ++ if ( LoadExceptionsByName( fn.GetFullPath() ) ) ++ g_EESchemaVar.NbExceptionErc = 0; ++} ++ ++ ++static bool FindException( NETLIST_OBJECT* a, NETLIST_OBJECT* b ) ++{ ++ SCH_COMPONENT* a_comp = (SCH_COMPONENT*) a->m_Link; ++ SCH_COMPONENT* b_comp = (SCH_COMPONENT*) b->m_Link; ++ const char* a_ref = CONV_TO_UTF8( a_comp->GetRef( &a->m_SheetList ) ); ++ const char* b_ref = CONV_TO_UTF8( b_comp->GetRef( &b->m_SheetList ) ); ++ const char* a_pin = (char *) &a->m_PinNum; ++ const char* b_pin = (char *) &b->m_PinNum; ++ struct exception* e = exceptions; ++ ++ for( e = exceptions; e; e = e->next ) ++ { ++#if 0 ++fprintf(stderr, "a) %s %4.4s =? %s %4.4s\n", e->a_ref, e->a_pin, a_ref, a_pin); ++fprintf(stderr, "b) %s %4.4s =? %s %4.4s\n", e->b_ref, e->b_pin, b_ref, b_pin); ++#endif ++ if( strcmp( e->a_ref, a_ref ) ) ++ continue; ++ if( strncmp( e->a_pin, a_pin, 4 ) ) ++ continue; ++ if( strcmp( e->b_ref, b_ref ) ) ++ continue; ++ if( strncmp( e->b_pin, b_pin, 4 ) ) ++ continue; ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++ ++static bool IsException( NETLIST_OBJECT* a, NETLIST_OBJECT* b ) ++{ ++ return FindException( a, b ) || FindException( b, a); ++} ++ ++ + void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) + { + wxFileName fn; +@@ -258,6 +426,7 @@ + + g_EESchemaVar.NbErrorErc = 0; + g_EESchemaVar.NbWarningErc = 0; ++ g_EESchemaVar.NbExceptionErc = -1; /* -1 means "no file" */ + + /* Cleanup the entire hierarchy */ + EDA_ScreenList ScreenList; +@@ -285,6 +454,8 @@ + + m_Parent->BuildNetListBase(); + ++ LoadExceptions(); ++ + /* Reset the flag m_FlagOfConnection, that will be used next, in + * calculations */ + for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) +@@ -354,7 +525,13 @@ + + // Displays global results: + wxString num; +- num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc ); ++ ++ if( g_EESchemaVar.NbExceptionErc >= 0) ++ num.Printf( wxT( "%d (%d exception%s)" ), g_EESchemaVar.NbErrorErc, ++ g_EESchemaVar.NbExceptionErc, ++ g_EESchemaVar.NbExceptionErc == 1 ? wxT( "" ) : wxT( "s" ) ); ++ else ++ num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc ); + m_TotalErrCount->SetLabel( num ); + + num.Printf( wxT( +@@ -657,6 +834,12 @@ + if( g_NetObjectslist[NetItemTst]->m_FlagOfConnection != 0 ) + break; + ++ if( IsException( g_NetObjectslist[NetItemRef], g_NetObjectslist[NetItemTst] ) ) ++ { ++ g_EESchemaVar.NbExceptionErc++; ++ break; ++ } ++ + Diagnose( panel, + g_NetObjectslist[NetItemRef], + g_NetObjectslist[NetItemTst], +Index: kicad/eeschema/general.h +=================================================================== +--- kicad.orig/eeschema/general.h 2010-04-28 04:34:54.000000000 -0300 ++++ kicad/eeschema/general.h 2010-04-28 05:42:13.000000000 -0300 +@@ -117,6 +117,7 @@ + { + int NbErrorErc; + int NbWarningErc; ++ int NbExceptionErc; + }; + + extern struct EESchemaVariables g_EESchemaVar; diff --git a/kicad-patches/fix-pinedit-collision.patch b/kicad-patches/fix-pinedit-collision.patch new file mode 100644 index 0000000..f56c8ca --- /dev/null +++ b/kicad-patches/fix-pinedit-collision.patch @@ -0,0 +1,28 @@ +When working with a component that contains multiple independent units, +KiCad warns about pin locations being occupied even if the conflicting +pin is in a different unit. + +I've attached a patch that suppresses the warning if the pins are in +different units and if we're in pin-by-pin mode, and thus conflicts +can neither occur at the GUI nor in the underlying model. + +- Werner + +--- + +Index: kicad/eeschema/pinedit.cpp +=================================================================== +--- kicad.orig/eeschema/pinedit.cpp 2010-04-28 04:34:54.000000000 -0300 ++++ kicad/eeschema/pinedit.cpp 2010-04-28 05:35:24.000000000 -0300 +@@ -231,6 +231,11 @@ + if( Pin == CurrentPin || newpos != Pin->m_Pos || Pin->m_Flags ) + continue; + ++ if( g_EditPinByPinIsOn && ++ Pin->m_Unit != CurrentPin->m_Unit && ++ Pin->m_Unit && CurrentPin->m_Unit ) ++ continue; ++ + if( ask_for_pin && !g_EditPinByPinIsOn ) + { + DrawPanel->m_IgnoreMouseEvents = true; diff --git a/kicad-patches/pcbnew-scripted.patch b/kicad-patches/pcbnew-scripted.patch new file mode 100644 index 0000000..1ea24e4 --- /dev/null +++ b/kicad-patches/pcbnew-scripted.patch @@ -0,0 +1,747 @@ +This patch adds several command line parameters to pcbnew. + +diff -ruN kicad.orig/common/confirm.cpp kicad/common/confirm.cpp +--- kicad.orig/common/confirm.cpp 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/common/confirm.cpp 2010-12-24 21:01:00.966781920 +0000 +@@ -66,6 +66,7 @@ + * See not above as to why this doesn't work. */ + } + ++bool g_scripted = false; + + /* Display an error or warning message. + * If display time > 0 the dialog disappears after displayTime 0.1 seconds +@@ -75,6 +76,12 @@ + { + wxMessageDialog* dialog; + ++ if (g_scripted) ++ { ++ wxFprintf( stderr, text + _("\n") ); ++ return; ++ } ++ + if( displaytime > 0 ) + dialog = new WinEDA_MessageDialog( parent, text, _( "Warning" ), + wxOK | wxICON_INFORMATION, +@@ -95,6 +102,11 @@ + { + wxMessageDialog* dialog; + ++ if (g_scripted) ++ { ++ wxPrintf( text + _("\n") ); ++ return; ++ } + dialog = new WinEDA_MessageDialog( parent, text, _( "Info:" ), + wxOK | wxICON_INFORMATION, displaytime ); + +diff -ruN kicad.orig/include/common.h kicad/include/common.h +--- kicad.orig/include/common.h 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/include/common.h 2010-12-22 18:47:54.974932729 +0000 +@@ -6,6 +6,8 @@ + #ifndef __INCLUDE__COMMON_H__ + #define __INCLUDE__COMMON_H__ 1 + ++extern bool g_scripted; ++ + #include "wx/confbase.h" + #include "wx/fileconf.h" + +diff -ruN kicad.orig/include/wxPcbStruct.h kicad/include/wxPcbStruct.h +--- kicad.orig/include/wxPcbStruct.h 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/include/wxPcbStruct.h 2010-12-24 11:03:20.674781923 +0000 +@@ -50,6 +50,7 @@ + class WinEDA_PcbFrame : public WinEDA_BasePcbFrame + { + friend class PCB_LAYER_WIDGET; ++ friend bool Pcbnew_Scripted(); + + protected: + +diff -ruN kicad.orig/pcbnew/build_BOM_from_board.cpp kicad/pcbnew/build_BOM_from_board.cpp +--- kicad.orig/pcbnew/build_BOM_from_board.cpp 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/build_BOM_from_board.cpp 2010-12-24 21:05:59.426781921 +0000 +@@ -64,6 +64,7 @@ + fn = GetScreen()->m_FileName; + fn.SetExt( CsvFileExtension ); + ++ if (!g_scripted) { + wxFileDialog dlg( this, _( "Save Bill of Materials" ), wxGetCwd(), + fn.GetFullName(), CsvFileWildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); +@@ -72,6 +73,7 @@ + return; + + fn = dlg.GetPath(); ++ } + + FichBom = wxFopen( fn.GetFullPath(), wxT( "wt" ) ); + +diff -ruN kicad.orig/pcbnew/CMakeLists.txt kicad/pcbnew/CMakeLists.txt +--- kicad.orig/pcbnew/CMakeLists.txt 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/CMakeLists.txt 2010-12-22 02:19:48.597291239 +0000 +@@ -142,6 +142,7 @@ + onrightclick.cpp + pcbnew.cpp + pcbnew_config.cpp ++ pcbnew_scripted.cpp + pcbplot.cpp + plotgerb.cpp + plothpgl.cpp +diff -ruN kicad.orig/pcbnew/dialog_gendrill.h kicad/pcbnew/dialog_gendrill.h +--- kicad.orig/pcbnew/dialog_gendrill.h 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/dialog_gendrill.h 2010-12-22 18:23:00.054932711 +0000 +@@ -12,6 +12,7 @@ + + class DIALOG_GENDRILL: public DIALOG_GENDRILL_BASE + { ++friend bool Pcbnew_Scripted(); + + private: + WinEDA_PcbFrame* m_Parent; +diff -ruN kicad.orig/pcbnew/drc_stuff.h kicad/pcbnew/drc_stuff.h +--- kicad.orig/pcbnew/drc_stuff.h 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/drc_stuff.h 2010-12-24 10:01:41.438781921 +0000 +@@ -136,6 +136,7 @@ + class DRC + { + friend class DIALOG_DRC_CONTROL; ++ friend bool Pcbnew_Scripted(); + + private: + +diff -ruN kicad.orig/pcbnew/gendrill.cpp kicad/pcbnew/gendrill.cpp +--- kicad.orig/pcbnew/gendrill.cpp 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/gendrill.cpp 2010-12-23 13:58:26.526933001 +0000 +@@ -307,6 +307,43 @@ + fn.SetName( fn.GetName() + layer_extend ); + fn.SetExt( DrillFileExtension ); + ++ if (g_scripted) ++ { ++ FILE* excellon_dest = wxFopen( fn.GetFullPath(), wxT( "w" ) ); ++ if( excellon_dest == 0 ) ++ { ++ printf("Unable to create %ls.\n", fn.GetFullPath().c_str()); ++ exit(0); ++ } ++ Create_Drill_File_EXCELLON( excellon_dest, s_HoleListBuffer, ++ s_ToolListBuffer ); ++ ++ switch( m_Choice_Drill_Map->GetSelection() ) ++ { ++ case 0: ++ break; ++ ++ case 1: ++ GenDrillMap( fn.GetPath(), s_HoleListBuffer, s_ToolListBuffer, ++ PLOT_FORMAT_HPGL ); ++ break; ++ ++ case 2: ++ GenDrillMap( fn.GetPath(), s_HoleListBuffer, s_ToolListBuffer, ++ PLOT_FORMAT_POST ); ++ break; ++ ++ case 3: ++ GenDrillMap( fn.GetPath(), s_HoleListBuffer, s_ToolListBuffer, ++ PLOT_FORMAT_GERBER ); ++ break; ++ ++ case 4: ++ GenDrillMap( fn.GetPath(), s_HoleListBuffer, s_ToolListBuffer, ++ PLOT_FORMAT_DXF ); ++ break; ++ } ++ } else { + wxFileDialog dlg( this, _( "Save Drill File" ), fn.GetPath(), + fn.GetFullName(), DrillFileWildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); +@@ -352,6 +389,7 @@ + PLOT_FORMAT_DXF ); + break; + } ++ } // !g_scripted + + if( !ExistsBuriedVias ) + break; +diff -ruN kicad.orig/pcbnew/pcbnew.cpp kicad/pcbnew/pcbnew.cpp +--- kicad.orig/pcbnew/pcbnew.cpp 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/pcbnew.cpp 2010-12-24 14:43:58.522781921 +0000 +@@ -29,6 +29,7 @@ + #include "build_version.h" + + #include "protos.h" ++#include "pcbnew_scripted.h" + + // Colors for layers and items + COLORS_DESIGN_SETTINGS g_ColorsSettings; +@@ -105,6 +106,9 @@ + + InitEDA_Appl( wxT( "PCBnew" ), APP_TYPE_PCBNEW ); + ++ if( Pcbnew_Scripted() ) ++ return true; ++ + if( m_Checker && m_Checker->IsAnotherRunning() ) + { + if( !IsOK( NULL, _( "Pcbnew is already running, Continue?" ) ) ) +diff -ruN kicad.orig/pcbnew/pcbnew_scripted.cpp kicad/pcbnew/pcbnew_scripted.cpp +--- kicad.orig/pcbnew/pcbnew_scripted.cpp 1970-01-01 00:00:00.000000000 +0000 ++++ kicad/pcbnew/pcbnew_scripted.cpp 2010-12-25 07:29:51.582781922 +0000 +@@ -0,0 +1,524 @@ ++///////////////////////////////////////////////////////////////////////////// ++// Name: pcbnew_scripted.cpp ++// Copyright: Wolfgang Spraul ++// Licence: GPL v3 or higher ++///////////////////////////////////////////////////////////////////////////// ++ ++#include "fctsys.h" ++#include "appl_wxstruct.h" ++#include "confirm.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "pcbnew.h" ++#include "wxPcbStruct.h" ++#include "plot_common.h" ++#include "gestfich.h" ++#include "pcbplot.h" ++#include "autorout.h" ++#include "cell.h" ++#include "worksheet.h" ++#include "zones.h" ++#include "drag.h" ++#include "eda_dde.h" ++#include "colors_selection.h" ++#include "class_drawpanel.h" ++ ++#include "id.h" ++ ++#include "build_version.h" ++ ++#include "protos.h" ++#include "pcbnew_scripted.h" ++#include "gendrill.h" ++#include "dialog_gendrill.h" ++#include "dialog_drc.h" ++#include "printout_controler.h" ++ ++extern int g_DrawDefaultLineThickness; ++ ++static const wxCmdLineEntryDesc g_cmdLineDesc [] = ++{ ++ { wxCMD_LINE_SWITCH, wxT("h"), wxT("help"), wxT("displays help on the command line parameters"), ++ wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, ++ { wxCMD_LINE_SWITCH, wxT("d"), wxT("drill"), wxT("generates a .drl drill file") }, ++ { wxCMD_LINE_OPTION, wxT("p"), wxT("plot"), wxT("plots the board [hpgl|gerber|ps|ps_a4|dxf]"), ++ wxCMD_LINE_VAL_STRING }, ++ { wxCMD_LINE_OPTION, wxT("l"), wxT("layers"), wxT("comma separated list of layer names (default: all layers)"), ++ wxCMD_LINE_VAL_STRING }, ++ { wxCMD_LINE_SWITCH, wxT("list-layers"), wxT("list-layers"), wxT("lists the name of all enabled layers in the .brd file") }, ++ { wxCMD_LINE_OPTION, wxT("ps-pads-drill-opt"), wxT("ps-pads-drill-opt"), wxT("Postscript pads drill option [none|small|real] (default:small)"), ++ wxCMD_LINE_VAL_STRING }, ++ { wxCMD_LINE_SWITCH, wxT("mirror"), wxT("mirror"), wxT("mirror plot (HPGL and Postscript only)") }, ++ { wxCMD_LINE_SWITCH, wxT("drc"), wxT("drc"), wxT("generates a design rule check report (.rpt)") }, ++ { wxCMD_LINE_SWITCH, wxT("svg"), wxT("svg"), wxT("plots the board in SVG format") }, ++ { wxCMD_LINE_SWITCH, wxT("svg-merge"), wxT("svg-merge-layers"), wxT("merge layers into one SVG file") }, ++ { wxCMD_LINE_SWITCH, wxT("svg-edge"), wxT("svg-board-edges"), wxT("add board edges to SVG plots") }, ++ { wxCMD_LINE_SWITCH, wxT("pos"), wxT("pos"), wxT("create front and back .pos component position files") }, ++ { wxCMD_LINE_SWITCH, wxT("bom"), wxT("bom"), wxT("create a .csv bom") }, ++ { wxCMD_LINE_SWITCH, wxT("cmp"), wxT("cmp"), wxT("recreate .cmp components file for CvPcb") }, ++ { wxCMD_LINE_SWITCH, wxT("vrml"), wxT("vrml"), wxT("generates a .wrl vrml board representation") }, ++ { wxCMD_LINE_PARAM, 0, 0, wxT(""), ++ wxCMD_LINE_VAL_STRING }, ++ { wxCMD_LINE_NONE } ++}; ++ ++bool Pcbnew_Scripted() ++{ ++ wxFileName fn; ++ wxString str; ++ WinEDA_PcbFrame* frame = NULL; ++ wxCommandEvent dummy; ++ ++ WinEDA_App& app = wxGetApp(); ++ if (app.argc < 2 || app.argv[1][0] != '-') ++ return false; ++ g_scripted = true; ++ ++ wxCmdLineParser parser; ++ parser.SetDesc(g_cmdLineDesc); ++ parser.SetCmdLine(app.argc, app.argv); ++ if (parser.Parse()) ++ exit(0); ++ if ( parser.Found( wxT("ps-pads-drill-opt"), &str ) ++ && str.CmpNoCase( wxT("none") ) ++ && str.CmpNoCase( wxT("small") ) ++ && str.CmpNoCase( wxT("real") )) ++ { ++ parser.Usage(); ++ wxPrintf(wxT("Unexpected pads drill option '%ls'.\n"), str.c_str()); ++ exit(0); ++ } ++ ++ fn = parser.GetParam(); ++ if( fn.GetExt() != PcbFileExtension ) ++ { ++ wxLogDebug( wxT( "PcbNew file <%s> has the wrong extension. Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); ++ fn.SetExt( PcbFileExtension ); ++ } ++ if( !fn.FileExists()) ++ { ++ wxPrintf( wxT("%ls: file '%ls' does not exist.\n" ), app.argv[0], fn.GetFullPath().c_str() ); ++ exit(0); ++ } ++ wxSetWorkingDirectory( fn.GetPath() ); ++ ++ app.InitEDA_Appl( wxT( "PCBnew" ), APP_TYPE_PCBNEW ); ++ ScreenPcb = new PCB_SCREEN(); ++ ActiveScreen = ScreenPcb; ++ app.GetSettings( false /* reopenLastUsedDirectory */ ); ++ ++ g_DrawBgColor = BLACK; ++ frame = new WinEDA_PcbFrame( NULL, wxT( "PcbNew" ), wxPoint( 0, 0 ), wxSize( 600, 400 ) ); ++ ++#if 0 // enable this to see more of the GUI ++ app.SetTopWindow( frame ); ++ frame->Show( true ); ++ frame->Zoom_Automatique( true ); ++#endif ++ ++ frame->LoadOnePcbFile( fn.GetFullPath() ); ++ frame->LoadProjectSettings( fn.GetFullPath() ); ++ ++ if ( parser.Found( wxT("drill") ) ) ++ { ++ DIALOG_GENDRILL* drill_frame = new DIALOG_GENDRILL( frame ); ++ drill_frame->GenDrillFiles( dummy ); ++ } ++ if ( parser.Found( wxT("print-layers") ) ) ++ { ++ for ( int i = 0; i < NB_LAYERS; i++ ) ++ { ++ if( frame->GetBoard()->IsLayerEnabled( i ) ) ++ { ++ str = frame->GetBoard()->GetLayerName( i ); ++ str.Trim( true ); str.Trim( false ); // remove leading and trailing spaces if any ++ wxPrintf(str + _("\n")); ++ } ++ } ++ } ++ if ( parser.Found( wxT("plot"), &str ) ) // see pcbplot.cpp ++ { ++ bool ps_use_a4; ++ int plot_format; ++ wxString ext, layers_str; ++ ++ g_pcb_plot_options.PlotLine_Width = g_DrawDefaultLineThickness; ++ if (!str.CmpNoCase( wxT("ps") ) ) ++ { ++ plot_format = PLOT_FORMAT_POST; ++ ext = wxT( "ps" ); ++ ps_use_a4 = false; ++ } ++ else if ( !str.CmpNoCase( wxT("ps_a4") ) ) ++ { ++ plot_format = PLOT_FORMAT_POST; ++ ext = wxT( "ps" ); ++ ps_use_a4 = true; ++ } ++ else if ( !str.CmpNoCase( wxT("hpgl") ) ) ++ { ++ plot_format = PLOT_FORMAT_HPGL; ++ ext = wxT( "plt" ); ++ } ++ else if ( !str.CmpNoCase( wxT("gerber") ) ) ++ { ++ plot_format = PLOT_FORMAT_GERBER; ++ ext = wxT( "pho" ); ++ } ++ else if ( !str.CmpNoCase( wxT("dxf") ) ) ++ { ++ plot_format = PLOT_FORMAT_DXF; ++ ext = wxT( "dxf" ); ++ } ++ else ++ { ++ parser.Usage(); ++ wxPrintf(wxT("Unexpected plot type '%ls'.\n"), str.c_str()); ++ exit(0); ++ } ++ ++ // --ps-pads-drill-opt ++ if ( plot_format == PLOT_FORMAT_POST && parser.Found( wxT("ps-pads-drill-opt"), &str ) ) ++ { ++ if (!str.CmpNoCase( wxT("none") ) ) ++ g_pcb_plot_options.DrillShapeOpt = PCB_Plot_Options::NO_DRILL_SHAPE; ++ else if ( !str.CmpNoCase( wxT("small") ) ) ++ g_pcb_plot_options.DrillShapeOpt = PCB_Plot_Options::SMALL_DRILL_SHAPE; ++ else if ( !str.CmpNoCase( wxT("real") ) ) ++ g_pcb_plot_options.DrillShapeOpt = PCB_Plot_Options::FULL_DRILL_SHAPE; ++ else ++ { ++ parser.Usage(); ++ wxPrintf(wxT("Unexpected Postscript pads drill option '%ls'.\n"), str.c_str()); ++ exit(0); ++ } ++ } ++ ++ // --mirror ++ if ( parser.Found( wxT("mirror") ) ) ++ g_pcb_plot_options.PlotOrient = PLOT_MIROIR; ++ ++ parser.Found( wxT("layers"), &layers_str ); ++ wxStringTokenizer tokenizer( layers_str, _(",") ); ++ int layer_i = 0; ++ wxString layername; ++ while ( ( layers_str.IsEmpty() && layer_i < NB_LAYERS ) || tokenizer.HasMoreTokens() ) ++ { ++ if ( layers_str.IsEmpty() ) ++ { ++ if( !frame->GetBoard()->IsLayerEnabled( layer_i ) ) ++ { ++ layer_i++; ++ continue; ++ } ++ layername = frame->GetBoard()->GetLayerName( layer_i ); ++ layername.Trim( true ); layername.Trim( false ); // remove leading and trailing spaces if any ++ layer_i++; ++ } ++ else ++ { ++ layername = tokenizer.GetNextToken(); ++ for( layer_i = 0; layer_i < NB_LAYERS; layer_i++ ) ++ { ++ str = frame->GetBoard()->GetLayerName( layer_i ); ++ str.Trim( true ); str.Trim( false ); // remove leading and trailing spaces if any ++ if ( !str.Cmp( layername ) ) ++ break; ++ } ++ if (layer_i >= NB_LAYERS) ++ { ++ wxFprintf( stderr, _( "Unknown layer name '%ls'\n" ), layername.c_str() ); ++ continue; ++ } ++ } ++ fn = ScreenPcb->m_FileName; ++ fn.SetName( fn.GetName() + wxT( "-" ) + layername ); ++ ++ // Use Gerber Extensions based on layer number ++ // (See http://en.wikipedia.org/wiki/Gerber_File) ++ if( (plot_format == PLOT_FORMAT_GERBER) && true /* always use gerber extensions */ ) ++ { ++ switch( layer_i ) ++ { ++ case LAYER_N_FRONT: ++ fn.SetExt( wxT( "gtl" ) ); ++ break; ++ ++ case LAYER_N_2: ++ case LAYER_N_3: ++ case LAYER_N_4: ++ case LAYER_N_5: ++ case LAYER_N_6: ++ case LAYER_N_7: ++ case LAYER_N_8: ++ case LAYER_N_9: ++ case LAYER_N_10: ++ case LAYER_N_11: ++ case LAYER_N_12: ++ case LAYER_N_13: ++ case LAYER_N_14: ++ case LAYER_N_15: ++ ++ // TODO: see if we use .gbr or a layer identifier (gb1 .. gbnn ?) ++ // according to the new internal layers designation ++ // (1 is the first internal layer from the front layer) ++ fn.SetExt( wxT( "gbr" ) ); ++ break; ++ ++ case LAYER_N_BACK: ++ fn.SetExt( wxT( "gbl" ) ); ++ break; ++ ++ case ADHESIVE_N_BACK: ++ fn.SetExt( wxT( "gba" ) ); ++ break; ++ ++ case ADHESIVE_N_FRONT: ++ fn.SetExt( wxT( "gta" ) ); ++ break; ++ ++ case SOLDERPASTE_N_BACK: ++ fn.SetExt( wxT( "gbp" ) ); ++ break; ++ ++ case SOLDERPASTE_N_FRONT: ++ fn.SetExt( wxT( "gtp" ) ); ++ break; ++ ++ case SILKSCREEN_N_BACK: ++ fn.SetExt( wxT( "gbo" ) ); ++ break; ++ ++ case SILKSCREEN_N_FRONT: ++ fn.SetExt( wxT( "gto" ) ); ++ break; ++ ++ case SOLDERMASK_N_BACK: ++ fn.SetExt( wxT( "gbs" ) ); ++ break; ++ ++ case SOLDERMASK_N_FRONT: ++ fn.SetExt( wxT( "gts" ) ); ++ break; ++ ++ case DRAW_N: ++ case COMMENT_N: ++ case ECO1_N: ++ case ECO2_N: ++ case EDGE_N: ++ default: ++ fn.SetExt( wxT( "gbr" ) ); ++ break; ++ } ++ } ++ else ++ { ++ fn.SetExt( ext ); ++ } ++ ++ bool success = false; ++ ++ switch( plot_format ) ++ { ++ case PLOT_FORMAT_POST: ++ success = frame->Genere_PS( fn.GetFullPath(), layer_i, ps_use_a4, ++ FILLED /* trace_mode */ ); ++ break; ++ ++ case PLOT_FORMAT_GERBER: ++ success = frame->Genere_GERBER( fn.GetFullPath(), layer_i, ++ false /* PlotOriginIsAuxAxis */, ++ FILLED /* trace_mode */ ); ++ break; ++ ++ case PLOT_FORMAT_HPGL: ++ success = frame->Genere_HPGL( fn.GetFullPath(), layer_i, ++ FILLED /* trace_mode */ ); ++ break; ++ ++ case PLOT_FORMAT_DXF: ++ success = frame->Genere_DXF( fn.GetFullPath(), layer_i, ++ FILLED /* trace_mode */ ); ++ break; ++ } ++ ++ // Print diags in messages box: ++ wxString msg; ++ if( !success ) ++ wxFprintf( stderr, _( "Unable to create <%s>\n" ), GetChars( fn.GetFullPath() ) ); ++ } ++ } ++ if ( parser.Found( wxT("drc") ) ) // drc_stuff.h drc.cpp dialog_drc.{h,cpp} ++ { ++ fn = ScreenPcb->m_FileName; ++ fn.SetExt( _("rpt") ); ++ ++ // if you get a segfault, try adding frame->m_drc->ShowDialog() to run through the GUI codepath ++ frame->m_drc->updatePointers(); ++ frame->m_drc->SetSettings(true, // Pad to pad DRC test enabled ++ true, // unconnected pdas DRC test enabled ++ true, // DRC test for zones enabled ++ fn.GetFullPath(), // report file name ++ true /* aSaveReport */ ); ++ frame->m_drc->m_pcb->m_Status_Pcb = 0; // Force full connectivity and ratsnest recalculations ++ frame->m_drc->RunTests(); ++ FILE* fp = wxFopen( fn.GetFullPath(), wxT( "w" ) ); ++ { // strings should match dialog_drc.cpp:DIALOG_DRC_CONTROL::writeReport() ++ int count; ++ ++ fprintf( fp, "** Drc report for %s **\n", ++ CONV_TO_UTF8( ScreenPcb->m_FileName ) ); ++ ++ wxDateTime now = wxDateTime::Now(); ++ fprintf( fp, "** Created on %s **\n", CONV_TO_UTF8( now.Format( wxT( "%F %T" ) ) ) ); ++ ++ class DRC_LIST_MARKERS* markers = new DRC_LIST_MARKERS( frame->m_drc->m_pcb ); ++ count = markers->GetCount(); ++ fprintf( fp, "\n** Found %d DRC errors **\n", count ); ++ for (int i = 0; i < count; i++) ++ fprintf( fp, "%s", CONV_TO_UTF8( markers->GetItem( i )->ShowReport()) ); ++ delete markers; ++ ++ class DRC_LIST_UNCONNECTED* unconnected = new DRC_LIST_UNCONNECTED( &frame->m_drc->m_unconnected ); ++ count = unconnected->GetCount(); ++ fprintf( fp, "\n** Found %d unconnected pads **\n", count ); ++ for (int i = 0; i < count; i++) ++ fprintf( fp, "%s", CONV_TO_UTF8( unconnected->GetItem( i )->ShowReport()) ); ++ delete unconnected; ++ ++ fprintf( fp, "\n** End of Report **\n" ); ++ } ++ fclose( fp ); ++ } ++ if ( parser.Found( wxT("svg") ) ) // see dialog_SVG_print.cpp:DIALOG_SVG_PRINT::DrawPage() ++ { ++ BASE_SCREEN* screen = frame->GetBaseScreen(); ++ wxSize SheetSize; // Sheet size in internal units ++ wxString layers_str; ++ PRINT_PARAMETERS print_params; ++ long PrintMaskLayer; ++ int layer_i; ++ wxSVGFileDC* dc; ++ ++ screen->m_DrawOrg.x = screen->m_DrawOrg.y = 0; ++ screen->m_StartVisu.x = screen->m_StartVisu.y = 0; ++ SheetSize = screen->m_CurrentSheetDesc->m_Size; // size in 1/1000 inch ++ SheetSize.x *= frame->m_InternalUnits / 1000; ++ SheetSize.y *= frame->m_InternalUnits / 1000; // size in pixels ++ screen->SetScalingFactor( 1.0 ); ++ screen->m_IsPrinting = true; ++ float dpi = (float)frame->m_InternalUnits; ++ ++ frame->DrawPanel->m_ClipBox.SetX( 0 ); ++ frame->DrawPanel->m_ClipBox.SetY( 0 ); ++ frame->DrawPanel->m_ClipBox.SetWidth( 0x7FFFFF0 ); ++ frame->DrawPanel->m_ClipBox.SetHeight( 0x7FFFFF0 ); ++ ++ print_params.m_DrillShapeOpt = PRINT_PARAMETERS::FULL_DRILL_SHAPE; ++ print_params.m_Print_Sheet_Ref = false; // reference in bottom-right corner ++ ++ SetLocaleTo_C_standard(); // Switch the locale to standard C (needed ++ // to print floating point numbers like 1.3) ++ int bg_color = g_DrawBgColor; ++ g_DrawBgColor = WHITE; ++ ++ PrintMaskLayer = 0; ++ if ( parser.Found( wxT("layers"), &layers_str ) ) ++ { ++ wxStringTokenizer tokenizer( layers_str, _(",") ); ++ layer_i = 0; ++ wxString layername; ++ while ( tokenizer.HasMoreTokens() ) ++ { ++ layername = tokenizer.GetNextToken(); ++ for( layer_i = 0; layer_i < NB_LAYERS; layer_i++ ) ++ { ++ str = frame->GetBoard()->GetLayerName( layer_i ); ++ str.Trim( true ); str.Trim( false ); // remove leading and trailing spaces if any ++ if ( !str.Cmp( layername ) ) ++ break; ++ } ++ if (layer_i >= NB_LAYERS) ++ { ++ wxFprintf( stderr, _( "Unknown layer name '%ls'\n" ), layername.c_str() ); ++ continue; ++ } ++ PrintMaskLayer |= 1 << layer_i; ++ } ++ } ++ else ++ { ++ for ( layer_i = 0; layer_i < NB_LAYERS; layer_i++ ) ++ { ++ if ( frame->GetBoard()->IsLayerEnabled( layer_i ) ) ++ PrintMaskLayer |= 1 << layer_i; ++ } ++ } ++ ++ bool SvgMergeLayers = parser.Found( wxT("svg-merge-layers") ); ++ bool SvgEdgeLayer = parser.Found( wxT("svg-board-edges") ); ++ ++ for ( layer_i = 0; layer_i < NB_LAYERS; layer_i++ ) ++ { ++ long LayerMask; ++ ++ fn = ScreenPcb->m_FileName; ++ fn.SetExt( _("svg") ); ++ if ( SvgMergeLayers ) ++ { ++ fn.SetName( fn.GetName() + wxT( "-brd" ) ); ++ LayerMask = PrintMaskLayer; ++ } ++ else ++ { ++ if ( !(PrintMaskLayer & (1 << layer_i) )) ++ continue; ++ str = frame->GetBoard()->GetLayerName( layer_i ); ++ str.Trim( true ); str.Trim( false ); // remove leading and trailing spaces if any ++ fn.SetName( fn.GetName() + wxT( "-" ) + str ); ++ LayerMask = 1 << layer_i; ++ } ++ if ( SvgEdgeLayer ) ++ LayerMask |= EDGE_LAYER; ++ ++ dc = new wxSVGFileDC( fn.GetFullPath(), SheetSize.x, SheetSize.y, dpi ); ++ GRResetPenAndBrush( dc ); ++ frame->PrintPage( dc, false /* aPrint_Frame_Ref */, LayerMask, false /* aPrintMirrorMode */, &print_params); ++ delete dc; ++ dc = 0; ++ ++ if ( SvgMergeLayers ) ++ break; ++ } ++ g_DrawBgColor = bg_color; ++ SetLocaleTo_Default(); // revert to the current locale ++ screen->m_IsPrinting = false; ++ } ++ ++ if ( parser.Found( wxT("pos") ) ) // see gen_modules_placefile.cpp:WinEDA_PcbFrame::GenModulesPosition() ++ frame->GenModulesPosition( dummy ); ++ ++ if ( parser.Found( wxT("bom") ) ) // see build_BOM_from_board.cpp:WinEDA_PcbFrame::RecreateBOMFileFromBoard() ++ frame->RecreateBOMFileFromBoard( dummy ); ++ ++ if ( parser.Found( wxT("cmp") ) ) // see xchgmod.cpp:WinEDA_PcbFrame::RecreateCmpFileFromBoard() ++ frame->RecreateCmpFileFromBoard( dummy ); ++ ++ if ( parser.Found( wxT("vrml") ) ) // see export_vrml.cpp:WinEDA_PcbFrame::OnExportVRML() ++ { ++ wxString subDirFor3Dshapes( _( "shapes3D" ) ); ++ ++ fn = ScreenPcb->m_FileName; ++ fn.SetExt( _("wrl") ); ++ if( ! wxDirExists( subDirFor3Dshapes ) ) ++ wxMkdir( subDirFor3Dshapes ); ++ frame->ExportVRML_File( fn.GetFullPath(), 1.0 /* aScale */, true /* aExport3DFile */, subDirFor3Dshapes ); ++ } ++ exit(0); ++} +diff -ruN kicad.orig/pcbnew/pcbnew_scripted.h kicad/pcbnew/pcbnew_scripted.h +--- kicad.orig/pcbnew/pcbnew_scripted.h 1970-01-01 00:00:00.000000000 +0000 ++++ kicad/pcbnew/pcbnew_scripted.h 2010-12-22 18:47:58.774932729 +0000 +@@ -0,0 +1,7 @@ ++///////////////////////////////////////////////////////////////////////////// ++// Name: pcbnew_scripted.h ++// Copyright: Wolfgang Spraul ++// Licence: GPL v3 or higher ++///////////////////////////////////////////////////////////////////////////// ++ ++bool Pcbnew_Scripted(); +diff -ruN kicad.orig/pcbnew/xchgmod.cpp kicad/pcbnew/xchgmod.cpp +--- kicad.orig/pcbnew/xchgmod.cpp 2010-10-19 08:48:07.000000000 +0000 ++++ kicad/pcbnew/xchgmod.cpp 2010-12-24 21:11:13.642781922 +0000 +@@ -577,6 +577,7 @@ + wildcard = _( "Component files (." ) + NetCmpExtBuffer + wxT( ")|*." ) + + NetCmpExtBuffer; + ++ if (!g_scripted) { + wxFileDialog dlg( this, _( "Save Component Files" ), wxGetCwd(), + fn.GetFullName(), wildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); +@@ -585,6 +586,7 @@ + return; + + fn = dlg.GetPath(); ++ } + + FichCmp = wxFopen( fn.GetFullPath(), wxT( "wt" ) ); + if( FichCmp == NULL ) diff --git a/kicad-patches/series b/kicad-patches/series new file mode 100644 index 0000000..ea5641a --- /dev/null +++ b/kicad-patches/series @@ -0,0 +1,21 @@ +# Based on BZR revision 2448 + +# eeschema --plot extension, pending +eeschema-plot-only-mode.patch + +# eeschema --bom extension, pending +eeschema-bom-only-mode.patch + +# pcbnew command line support +pcbnew-scripted.patch + +# under discussion +fix-pinedit-collision.patch + +# Work in progress +#drag-override.patch +#pcbnew-plot-only-mode.patch + +# ERC pin exceptions +streamline-erc.patch +erc-exceptions.patch diff --git a/kicad-patches/streamline-erc.patch b/kicad-patches/streamline-erc.patch new file mode 100644 index 0000000..23dd33b --- /dev/null +++ b/kicad-patches/streamline-erc.patch @@ -0,0 +1,52 @@ +streamline TestOthersItems (ERC) + +This patch changes a deeply nested "if" into a series of "breaks", +for better readability and to facilitate future extensions. + +- Werner + +--- + +Index: kicad/eeschema/erc.cpp +=================================================================== +--- kicad.orig/eeschema/erc.cpp 2010-04-28 05:40:28.000000000 -0300 ++++ kicad/eeschema/erc.cpp 2010-04-28 05:40:38.000000000 -0300 +@@ -648,23 +648,22 @@ + break; + + *NetNbItems += 1; ++ if( erc != OK ) ++ break; ++ ++ erc = DiagErc[ref_elect_type][jj]; + if( erc == OK ) +- { +- erc = DiagErc[ref_elect_type][jj]; +- if( erc != OK ) +- { +- if( g_NetObjectslist[NetItemTst]->m_FlagOfConnection == 0 ) +- { +- Diagnose( panel, +- g_NetObjectslist[NetItemRef], +- g_NetObjectslist[NetItemTst], +- 0, +- erc ); +- g_NetObjectslist[NetItemTst]->m_FlagOfConnection = +- NOCONNECT_SYMBOL_PRESENT; +- } +- } +- } ++ break; ++ if( g_NetObjectslist[NetItemTst]->m_FlagOfConnection != 0 ) ++ break; ++ ++ Diagnose( panel, ++ g_NetObjectslist[NetItemRef], ++ g_NetObjectslist[NetItemTst], ++ 0, ++ erc ); ++ g_NetObjectslist[NetItemTst]->m_FlagOfConnection = ++ NOCONNECT_SYMBOL_PRESENT; + break; + } + }