From aa35045840b78d3f48212db45da59a2e5c69b223 Mon Sep 17 00:00:00 2001
From: saurabhb17
Date: Wed, 26 Feb 2020 15:57:49 +0530
Subject: Added main execs
---
eeschema/CMakeLists.txt | 383 ++
eeschema/Info.plist | 35 +
eeschema/annotate.cpp | 200 +
eeschema/backanno.cpp | 264 ++
eeschema/block.cpp | 538 +++
eeschema/block_libedit.cpp | 355 ++
eeschema/bus-wire-junction.cpp | 505 +++
eeschema/busentry.cpp | 83 +
eeschema/class_drc_erc_item.cpp | 68 +
eeschema/class_libentry.cpp | 1898 ++++++++
eeschema/class_libentry.h | 773 ++++
eeschema/class_library.cpp | 1208 +++++
eeschema/class_library.h | 670 +++
eeschema/class_netlist_object.cpp | 423 ++
eeschema/class_netlist_object.h | 483 ++
eeschema/class_sch_screen.h | 599 +++
eeschema/cmp_library.keywords | 33 +
eeschema/cmp_library_lexer.cpp | 6 +
eeschema/component_references_lister.cpp | 788 ++++
eeschema/component_tree_search_container.cpp | 443 ++
eeschema/component_tree_search_container.h | 145 +
eeschema/controle.cpp | 326 ++
eeschema/cross-probing.cpp | 214 +
eeschema/dialog_erc_listbox.h | 120 +
eeschema/dialogs/dialog_annotate.cpp | 320 ++
eeschema/dialogs/dialog_annotate_base.cpp | 245 ++
eeschema/dialogs/dialog_annotate_base.fbp | 2636 +++++++++++
eeschema/dialogs/dialog_annotate_base.h | 94 +
eeschema/dialogs/dialog_bom.cpp | 621 +++
eeschema/dialogs/dialog_bom_base.cpp | 118 +
eeschema/dialogs/dialog_bom_base.fbp | 1445 ++++++
eeschema/dialogs/dialog_bom_base.h | 98 +
eeschema/dialogs/dialog_bom_cfg.keywords | 4 +
eeschema/dialogs/dialog_bom_help.html | 282 ++
eeschema/dialogs/dialog_choose_component.cpp | 409 ++
eeschema/dialogs/dialog_choose_component.h | 92 +
eeschema/dialogs/dialog_choose_component_base.cpp | 93 +
eeschema/dialogs/dialog_choose_component_base.fbp | 594 +++
eeschema/dialogs/dialog_choose_component_base.h | 69 +
eeschema/dialogs/dialog_color_config.cpp | 296 ++
eeschema/dialogs/dialog_color_config.h | 58 +
eeschema/dialogs/dialog_color_config_base.cpp | 48 +
eeschema/dialogs/dialog_color_config_base.fbp | 217 +
eeschema/dialogs/dialog_color_config_base.h | 52 +
eeschema/dialogs/dialog_edit_component_in_lib.cpp | 579 +++
eeschema/dialogs/dialog_edit_component_in_lib.h | 70 +
.../dialogs/dialog_edit_component_in_lib_base.cpp | 294 ++
.../dialogs/dialog_edit_component_in_lib_base.fbp | 3354 ++++++++++++++
.../dialogs/dialog_edit_component_in_lib_base.h | 119 +
.../dialogs/dialog_edit_component_in_schematic.cpp | 1107 +++++
.../dialog_edit_component_in_schematic_fbp.cpp | 324 ++
.../dialog_edit_component_in_schematic_fbp.fbp | 3532 +++++++++++++++
.../dialog_edit_component_in_schematic_fbp.h | 109 +
eeschema/dialogs/dialog_edit_label.cpp | 326 ++
eeschema/dialogs/dialog_edit_label_base.cpp | 118 +
eeschema/dialogs/dialog_edit_label_base.fbp | 968 ++++
eeschema/dialogs/dialog_edit_label_base.h | 75 +
.../dialogs/dialog_edit_libentry_fields_in_lib.cpp | 796 ++++
.../dialog_edit_libentry_fields_in_lib_base.cpp | 229 +
.../dialog_edit_libentry_fields_in_lib_base.fbp | 2326 ++++++++++
.../dialog_edit_libentry_fields_in_lib_base.h | 92 +
eeschema/dialogs/dialog_edit_one_field.cpp | 278 ++
eeschema/dialogs/dialog_edit_one_field.h | 159 +
eeschema/dialogs/dialog_eeschema_config.cpp | 490 +++
eeschema/dialogs/dialog_eeschema_config_fbp.cpp | 175 +
eeschema/dialogs/dialog_eeschema_config_fbp.fbp | 1588 +++++++
eeschema/dialogs/dialog_eeschema_config_fbp.h | 89 +
eeschema/dialogs/dialog_eeschema_options.cpp | 371 ++
eeschema/dialogs/dialog_eeschema_options.h | 479 ++
eeschema/dialogs/dialog_eeschema_options_base.cpp | 303 ++
eeschema/dialogs/dialog_eeschema_options_base.fbp | 4612 ++++++++++++++++++++
eeschema/dialogs/dialog_eeschema_options_base.h | 145 +
eeschema/dialogs/dialog_erc.cpp | 579 +++
eeschema/dialogs/dialog_erc.h | 92 +
eeschema/dialogs/dialog_erc_base.cpp | 152 +
eeschema/dialogs/dialog_erc_base.fbp | 1799 ++++++++
eeschema/dialogs/dialog_erc_base.h | 88 +
eeschema/dialogs/dialog_lib_edit_draw_item.cpp | 131 +
eeschema/dialogs/dialog_lib_edit_draw_item.fbp | 1205 +++++
eeschema/dialogs/dialog_lib_edit_draw_item.h | 67 +
.../dialogs/dialog_lib_edit_draw_item_base.cpp | 140 +
eeschema/dialogs/dialog_lib_edit_draw_item_base.h | 67 +
eeschema/dialogs/dialog_lib_edit_pin.cpp | 193 +
eeschema/dialogs/dialog_lib_edit_pin.h | 146 +
eeschema/dialogs/dialog_lib_edit_pin_base.cpp | 224 +
eeschema/dialogs/dialog_lib_edit_pin_base.fbp | 2299 ++++++++++
eeschema/dialogs/dialog_lib_edit_pin_base.h | 104 +
eeschema/dialogs/dialog_lib_edit_pin_table.cpp | 584 +++
eeschema/dialogs/dialog_lib_edit_pin_table.h | 18 +
.../dialogs/dialog_lib_edit_pin_table_base.cpp | 46 +
.../dialogs/dialog_lib_edit_pin_table_base.fbp | 193 +
eeschema/dialogs/dialog_lib_edit_pin_table_base.h | 53 +
eeschema/dialogs/dialog_lib_edit_text.cpp | 222 +
eeschema/dialogs/dialog_lib_edit_text.h | 54 +
eeschema/dialogs/dialog_lib_edit_text_base.cpp | 150 +
eeschema/dialogs/dialog_lib_edit_text_base.fbp | 1427 ++++++
eeschema/dialogs/dialog_lib_edit_text_base.h | 74 +
eeschema/dialogs/dialog_lib_new_component.cpp | 45 +
eeschema/dialogs/dialog_lib_new_component.fbp | 1597 +++++++
eeschema/dialogs/dialog_lib_new_component.h | 97 +
eeschema/dialogs/dialog_lib_new_component_base.cpp | 146 +
eeschema/dialogs/dialog_lib_new_component_base.h | 67 +
eeschema/dialogs/dialog_libedit_options.cpp | 69 +
eeschema/dialogs/dialog_libedit_options.h | 93 +
eeschema/dialogs/dialog_libedit_options_base.cpp | 195 +
eeschema/dialogs/dialog_libedit_options_base.fbp | 2904 ++++++++++++
eeschema/dialogs/dialog_libedit_options_base.h | 85 +
eeschema/dialogs/dialog_netlist.cpp | 886 ++++
eeschema/dialogs/dialog_netlist_base.cpp | 151 +
eeschema/dialogs/dialog_netlist_base.fbp | 1624 +++++++
eeschema/dialogs/dialog_netlist_base.h | 124 +
eeschema/dialogs/dialog_plot_schematic.cpp | 357 ++
eeschema/dialogs/dialog_plot_schematic.h | 157 +
eeschema/dialogs/dialog_plot_schematic_base.cpp | 184 +
eeschema/dialogs/dialog_plot_schematic_base.fbp | 1852 ++++++++
eeschema/dialogs/dialog_plot_schematic_base.h | 91 +
eeschema/dialogs/dialog_print_using_printer.cpp | 487 +++
.../dialogs/dialog_print_using_printer_base.cpp | 80 +
.../dialogs/dialog_print_using_printer_base.fbp | 732 ++++
eeschema/dialogs/dialog_print_using_printer_base.h | 61 +
eeschema/dialogs/dialog_rescue_each.cpp | 316 ++
eeschema/dialogs/dialog_rescue_each_base.cpp | 127 +
eeschema/dialogs/dialog_rescue_each_base.fbp | 978 +++++
eeschema/dialogs/dialog_rescue_each_base.h | 70 +
eeschema/dialogs/dialog_sch_edit_sheet_pin.cpp | 60 +
eeschema/dialogs/dialog_sch_edit_sheet_pin.h | 59 +
.../dialogs/dialog_sch_edit_sheet_pin_base.cpp | 102 +
.../dialogs/dialog_sch_edit_sheet_pin_base.fbp | 1043 +++++
eeschema/dialogs/dialog_sch_edit_sheet_pin_base.h | 61 +
eeschema/dialogs/dialog_sch_sheet_props.cpp | 61 +
eeschema/dialogs/dialog_sch_sheet_props.fbp | 1503 +++++++
eeschema/dialogs/dialog_sch_sheet_props.h | 80 +
eeschema/dialogs/dialog_sch_sheet_props_base.cpp | 131 +
eeschema/dialogs/dialog_sch_sheet_props_base.h | 65 +
eeschema/dialogs/dialog_schematic_find.cpp | 284 ++
eeschema/dialogs/dialog_schematic_find.h | 201 +
eeschema/dialogs/dialog_schematic_find_base.cpp | 169 +
eeschema/dialogs/dialog_schematic_find_base.fbp | 1901 ++++++++
eeschema/dialogs/dialog_schematic_find_base.h | 81 +
eeschema/edit_bitmap.cpp | 199 +
eeschema/edit_component_in_schematic.cpp | 117 +
eeschema/edit_label.cpp | 320 ++
eeschema/eeredraw.cpp | 86 +
eeschema/eeschema.cpp | 242 +
eeschema/eeschema.icns | Bin 0 -> 178654 bytes
eeschema/eeschema.rc | 3 +
eeschema/eeschema_config.cpp | 810 ++++
eeschema/eeschema_config.h | 13 +
eeschema/eeschema_doc.icns | Bin 0 -> 144703 bytes
eeschema/eeschema_id.h | 252 ++
eeschema/erc.cpp | 617 +++
eeschema/erc.h | 127 +
eeschema/events_called_functions_for_edit.cpp | 79 +
eeschema/files-io.cpp | 547 +++
eeschema/find.cpp | 515 +++
eeschema/general.h | 150 +
eeschema/getpart.cpp | 402 ++
eeschema/help_common_strings.h | 90 +
eeschema/hierarch.cpp | 313 ++
eeschema/hotkeys.cpp | 876 ++++
eeschema/hotkeys.h | 96 +
eeschema/invoke_sch_dialog.h | 97 +
eeschema/lib_arc.cpp | 825 ++++
eeschema/lib_arc.h | 161 +
eeschema/lib_bezier.cpp | 421 ++
eeschema/lib_bezier.h | 119 +
eeschema/lib_circle.cpp | 356 ++
eeschema/lib_circle.h | 121 +
eeschema/lib_collectors.cpp | 131 +
eeschema/lib_collectors.h | 135 +
eeschema/lib_draw_item.cpp | 160 +
eeschema/lib_draw_item.h | 448 ++
eeschema/lib_export.cpp | 191 +
eeschema/lib_field.cpp | 771 ++++
eeschema/lib_field.h | 277 ++
eeschema/lib_pin.cpp | 2314 ++++++++++
eeschema/lib_pin.h | 561 +++
eeschema/lib_polyline.cpp | 562 +++
eeschema/lib_polyline.h | 133 +
eeschema/lib_rectangle.cpp | 434 ++
eeschema/lib_rectangle.h | 126 +
eeschema/lib_text.cpp | 559 +++
eeschema/lib_text.h | 152 +
eeschema/libarch.cpp | 119 +
eeschema/libedit.cpp | 742 ++++
eeschema/libedit_onleftclick.cpp | 213 +
eeschema/libedit_onrightclick.cpp | 348 ++
eeschema/libedit_plot_component.cpp | 214 +
eeschema/libedit_undo_redo.cpp | 137 +
eeschema/libeditframe.cpp | 1375 ++++++
eeschema/libeditframe.h | 678 +++
eeschema/libfield.cpp | 161 +
eeschema/load_one_schematic_file.cpp | 413 ++
eeschema/menubar.cpp | 521 +++
eeschema/menubar_libedit.cpp | 297 ++
eeschema/netform.cpp | 149 +
eeschema/netlist.cpp | 971 +++++
eeschema/netlist.h | 62 +
eeschema/netlist_exporters/netlist_exporter.cpp | 364 ++
eeschema/netlist_exporters/netlist_exporter.h | 235 +
.../netlist_exporters/netlist_exporter_cadstar.cpp | 204 +
.../netlist_exporters/netlist_exporter_cadstar.h | 62 +
.../netlist_exporters/netlist_exporter_generic.cpp | 580 +++
.../netlist_exporters/netlist_exporter_generic.h | 135 +
.../netlist_exporters/netlist_exporter_kicad.cpp | 77 +
.../netlist_exporters/netlist_exporter_kicad.h | 63 +
.../netlist_exporter_orcadpcb2.cpp | 145 +
.../netlist_exporters/netlist_exporter_orcadpcb2.h | 46 +
.../netlist_exporters/netlist_exporter_pspice.cpp | 358 ++
.../netlist_exporters/netlist_exporter_pspice.h | 50 +
eeschema/onleftclick.cpp | 407 ++
eeschema/onrightclick.cpp | 927 ++++
eeschema/operations_on_items_lists.cpp | 264 ++
eeschema/pinedit.cpp | 786 ++++
eeschema/plot_schematic_DXF.cpp | 166 +
eeschema/plot_schematic_HPGL.cpp | 260 ++
eeschema/plot_schematic_PDF.cpp | 209 +
eeschema/plot_schematic_PS.cpp | 191 +
eeschema/plot_schematic_SVG.cpp | 205 +
eeschema/plugins/CMakeLists.txt | 30 +
eeschema/plugins/python_scripts/README-bom.txt | 38 +
.../python_scripts/bom_csv_grouped_by_value.py | 167 +
.../bom_csv_grouped_by_value_with_fp.py | 65 +
.../python_scripts/bom_csv_sorted_by_ref.py | 62 +
.../python_scripts/bom_html_grouped_by_value.py | 98 +
.../bom_html_with_advanced_grouping.py | 132 +
.../plugins/python_scripts/bom_sorted_by_ref.py | 61 +
.../plugins/python_scripts/kicad_netlist_reader.py | 764 ++++
eeschema/plugins/python_scripts/round_robin.py | 28 +
.../plugins/python_scripts/round_value_robin.py | 74 +
eeschema/plugins/xsl_scripts/bom2csv.xsl | 99 +
eeschema/plugins/xsl_scripts/bom2grouped_csv.xsl | 104 +
.../xsl_scripts/bom_with_title_block_2_csv.xsl | 167 +
.../plugins/xsl_scripts/netlist_form_OrcadPcb2.xsl | 210 +
.../xsl_scripts/netlist_form_cadstar-RINF.xsl | 131 +
.../plugins/xsl_scripts/netlist_form_cadstar.xsl | 123 +
.../plugins/xsl_scripts/netlist_form_pads-pcb.xsl | 69 +
eeschema/project_rescue.cpp | 569 +++
eeschema/project_rescue.h | 198 +
eeschema/protos.h | 58 +
eeschema/sch_base_frame.cpp | 203 +
eeschema/sch_base_frame.h | 213 +
eeschema/sch_bitmap.cpp | 309 ++
eeschema/sch_bitmap.h | 149 +
eeschema/sch_bus_entry.cpp | 403 ++
eeschema/sch_bus_entry.h | 185 +
eeschema/sch_collectors.cpp | 571 +++
eeschema/sch_collectors.h | 408 ++
eeschema/sch_component.cpp | 2048 +++++++++
eeschema/sch_component.h | 496 +++
eeschema/sch_field.cpp | 589 +++
eeschema/sch_field.h | 202 +
eeschema/sch_item_struct.cpp | 151 +
eeschema/sch_item_struct.h | 432 ++
eeschema/sch_junction.cpp | 235 +
eeschema/sch_junction.h | 113 +
eeschema/sch_line.cpp | 611 +++
eeschema/sch_line.h | 157 +
eeschema/sch_marker.cpp | 186 +
eeschema/sch_marker.h | 117 +
eeschema/sch_no_connect.cpp | 252 ++
eeschema/sch_no_connect.h | 115 +
eeschema/sch_reference_list.h | 469 ++
eeschema/sch_screen.cpp | 1563 +++++++
eeschema/sch_sheet.cpp | 1236 ++++++
eeschema/sch_sheet.h | 600 +++
eeschema/sch_sheet_path.cpp | 924 ++++
eeschema/sch_sheet_path.h | 571 +++
eeschema/sch_sheet_pin.cpp | 526 +++
eeschema/sch_text.cpp | 1777 ++++++++
eeschema/sch_text.h | 366 ++
eeschema/sch_validators.cpp | 141 +
eeschema/sch_validators.h | 72 +
eeschema/schedit.cpp | 1163 +++++
eeschema/schematic_undo_redo.cpp | 382 ++
eeschema/schframe.cpp | 1320 ++++++
eeschema/schframe.h | 1351 ++++++
eeschema/selpart.cpp | 163 +
eeschema/sheet.cpp | 452 ++
eeschema/sheetlab.cpp | 179 +
eeschema/symbdraw.cpp | 370 ++
eeschema/symbedit.cpp | 269 ++
eeschema/template_fieldnames.cpp | 211 +
eeschema/template_fieldnames.h | 190 +
eeschema/template_fieldnames.keywords | 5 +
eeschema/tool_lib.cpp | 243 ++
eeschema/tool_sch.cpp | 325 ++
eeschema/tool_viewlib.cpp | 279 ++
eeschema/transform.cpp | 148 +
eeschema/transform.h | 106 +
eeschema/viewlib_frame.cpp | 595 +++
eeschema/viewlib_frame.h | 188 +
eeschema/viewlibs.cpp | 310 ++
293 files changed, 125869 insertions(+)
create mode 100644 eeschema/CMakeLists.txt
create mode 100644 eeschema/Info.plist
create mode 100644 eeschema/annotate.cpp
create mode 100644 eeschema/backanno.cpp
create mode 100644 eeschema/block.cpp
create mode 100644 eeschema/block_libedit.cpp
create mode 100644 eeschema/bus-wire-junction.cpp
create mode 100644 eeschema/busentry.cpp
create mode 100644 eeschema/class_drc_erc_item.cpp
create mode 100644 eeschema/class_libentry.cpp
create mode 100644 eeschema/class_libentry.h
create mode 100644 eeschema/class_library.cpp
create mode 100644 eeschema/class_library.h
create mode 100644 eeschema/class_netlist_object.cpp
create mode 100644 eeschema/class_netlist_object.h
create mode 100644 eeschema/class_sch_screen.h
create mode 100644 eeschema/cmp_library.keywords
create mode 100644 eeschema/cmp_library_lexer.cpp
create mode 100644 eeschema/component_references_lister.cpp
create mode 100644 eeschema/component_tree_search_container.cpp
create mode 100644 eeschema/component_tree_search_container.h
create mode 100644 eeschema/controle.cpp
create mode 100644 eeschema/cross-probing.cpp
create mode 100644 eeschema/dialog_erc_listbox.h
create mode 100644 eeschema/dialogs/dialog_annotate.cpp
create mode 100644 eeschema/dialogs/dialog_annotate_base.cpp
create mode 100644 eeschema/dialogs/dialog_annotate_base.fbp
create mode 100644 eeschema/dialogs/dialog_annotate_base.h
create mode 100644 eeschema/dialogs/dialog_bom.cpp
create mode 100644 eeschema/dialogs/dialog_bom_base.cpp
create mode 100644 eeschema/dialogs/dialog_bom_base.fbp
create mode 100644 eeschema/dialogs/dialog_bom_base.h
create mode 100644 eeschema/dialogs/dialog_bom_cfg.keywords
create mode 100644 eeschema/dialogs/dialog_bom_help.html
create mode 100644 eeschema/dialogs/dialog_choose_component.cpp
create mode 100644 eeschema/dialogs/dialog_choose_component.h
create mode 100644 eeschema/dialogs/dialog_choose_component_base.cpp
create mode 100644 eeschema/dialogs/dialog_choose_component_base.fbp
create mode 100644 eeschema/dialogs/dialog_choose_component_base.h
create mode 100644 eeschema/dialogs/dialog_color_config.cpp
create mode 100644 eeschema/dialogs/dialog_color_config.h
create mode 100644 eeschema/dialogs/dialog_color_config_base.cpp
create mode 100644 eeschema/dialogs/dialog_color_config_base.fbp
create mode 100644 eeschema/dialogs/dialog_color_config_base.h
create mode 100644 eeschema/dialogs/dialog_edit_component_in_lib.cpp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_lib.h
create mode 100644 eeschema/dialogs/dialog_edit_component_in_lib_base.cpp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_lib_base.fbp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_lib_base.h
create mode 100644 eeschema/dialogs/dialog_edit_component_in_schematic.cpp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_schematic_fbp.cpp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_schematic_fbp.fbp
create mode 100644 eeschema/dialogs/dialog_edit_component_in_schematic_fbp.h
create mode 100644 eeschema/dialogs/dialog_edit_label.cpp
create mode 100644 eeschema/dialogs/dialog_edit_label_base.cpp
create mode 100644 eeschema/dialogs/dialog_edit_label_base.fbp
create mode 100644 eeschema/dialogs/dialog_edit_label_base.h
create mode 100644 eeschema/dialogs/dialog_edit_libentry_fields_in_lib.cpp
create mode 100644 eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.cpp
create mode 100644 eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.fbp
create mode 100644 eeschema/dialogs/dialog_edit_libentry_fields_in_lib_base.h
create mode 100644 eeschema/dialogs/dialog_edit_one_field.cpp
create mode 100644 eeschema/dialogs/dialog_edit_one_field.h
create mode 100644 eeschema/dialogs/dialog_eeschema_config.cpp
create mode 100644 eeschema/dialogs/dialog_eeschema_config_fbp.cpp
create mode 100644 eeschema/dialogs/dialog_eeschema_config_fbp.fbp
create mode 100644 eeschema/dialogs/dialog_eeschema_config_fbp.h
create mode 100644 eeschema/dialogs/dialog_eeschema_options.cpp
create mode 100644 eeschema/dialogs/dialog_eeschema_options.h
create mode 100644 eeschema/dialogs/dialog_eeschema_options_base.cpp
create mode 100644 eeschema/dialogs/dialog_eeschema_options_base.fbp
create mode 100644 eeschema/dialogs/dialog_eeschema_options_base.h
create mode 100644 eeschema/dialogs/dialog_erc.cpp
create mode 100644 eeschema/dialogs/dialog_erc.h
create mode 100644 eeschema/dialogs/dialog_erc_base.cpp
create mode 100644 eeschema/dialogs/dialog_erc_base.fbp
create mode 100644 eeschema/dialogs/dialog_erc_base.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_draw_item.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_draw_item.fbp
create mode 100644 eeschema/dialogs/dialog_lib_edit_draw_item.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_draw_item_base.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_draw_item_base.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_base.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_base.fbp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_base.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.fbp
create mode 100644 eeschema/dialogs/dialog_lib_edit_pin_table_base.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_text.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_text.h
create mode 100644 eeschema/dialogs/dialog_lib_edit_text_base.cpp
create mode 100644 eeschema/dialogs/dialog_lib_edit_text_base.fbp
create mode 100644 eeschema/dialogs/dialog_lib_edit_text_base.h
create mode 100644 eeschema/dialogs/dialog_lib_new_component.cpp
create mode 100644 eeschema/dialogs/dialog_lib_new_component.fbp
create mode 100644 eeschema/dialogs/dialog_lib_new_component.h
create mode 100644 eeschema/dialogs/dialog_lib_new_component_base.cpp
create mode 100644 eeschema/dialogs/dialog_lib_new_component_base.h
create mode 100644 eeschema/dialogs/dialog_libedit_options.cpp
create mode 100644 eeschema/dialogs/dialog_libedit_options.h
create mode 100644 eeschema/dialogs/dialog_libedit_options_base.cpp
create mode 100644 eeschema/dialogs/dialog_libedit_options_base.fbp
create mode 100644 eeschema/dialogs/dialog_libedit_options_base.h
create mode 100644 eeschema/dialogs/dialog_netlist.cpp
create mode 100644 eeschema/dialogs/dialog_netlist_base.cpp
create mode 100644 eeschema/dialogs/dialog_netlist_base.fbp
create mode 100644 eeschema/dialogs/dialog_netlist_base.h
create mode 100644 eeschema/dialogs/dialog_plot_schematic.cpp
create mode 100644 eeschema/dialogs/dialog_plot_schematic.h
create mode 100644 eeschema/dialogs/dialog_plot_schematic_base.cpp
create mode 100644 eeschema/dialogs/dialog_plot_schematic_base.fbp
create mode 100644 eeschema/dialogs/dialog_plot_schematic_base.h
create mode 100644 eeschema/dialogs/dialog_print_using_printer.cpp
create mode 100644 eeschema/dialogs/dialog_print_using_printer_base.cpp
create mode 100644 eeschema/dialogs/dialog_print_using_printer_base.fbp
create mode 100644 eeschema/dialogs/dialog_print_using_printer_base.h
create mode 100644 eeschema/dialogs/dialog_rescue_each.cpp
create mode 100644 eeschema/dialogs/dialog_rescue_each_base.cpp
create mode 100644 eeschema/dialogs/dialog_rescue_each_base.fbp
create mode 100644 eeschema/dialogs/dialog_rescue_each_base.h
create mode 100644 eeschema/dialogs/dialog_sch_edit_sheet_pin.cpp
create mode 100644 eeschema/dialogs/dialog_sch_edit_sheet_pin.h
create mode 100644 eeschema/dialogs/dialog_sch_edit_sheet_pin_base.cpp
create mode 100644 eeschema/dialogs/dialog_sch_edit_sheet_pin_base.fbp
create mode 100644 eeschema/dialogs/dialog_sch_edit_sheet_pin_base.h
create mode 100644 eeschema/dialogs/dialog_sch_sheet_props.cpp
create mode 100644 eeschema/dialogs/dialog_sch_sheet_props.fbp
create mode 100644 eeschema/dialogs/dialog_sch_sheet_props.h
create mode 100644 eeschema/dialogs/dialog_sch_sheet_props_base.cpp
create mode 100644 eeschema/dialogs/dialog_sch_sheet_props_base.h
create mode 100644 eeschema/dialogs/dialog_schematic_find.cpp
create mode 100644 eeschema/dialogs/dialog_schematic_find.h
create mode 100644 eeschema/dialogs/dialog_schematic_find_base.cpp
create mode 100644 eeschema/dialogs/dialog_schematic_find_base.fbp
create mode 100644 eeschema/dialogs/dialog_schematic_find_base.h
create mode 100644 eeschema/edit_bitmap.cpp
create mode 100644 eeschema/edit_component_in_schematic.cpp
create mode 100644 eeschema/edit_label.cpp
create mode 100644 eeschema/eeredraw.cpp
create mode 100644 eeschema/eeschema.cpp
create mode 100644 eeschema/eeschema.icns
create mode 100644 eeschema/eeschema.rc
create mode 100644 eeschema/eeschema_config.cpp
create mode 100644 eeschema/eeschema_config.h
create mode 100644 eeschema/eeschema_doc.icns
create mode 100644 eeschema/eeschema_id.h
create mode 100644 eeschema/erc.cpp
create mode 100644 eeschema/erc.h
create mode 100644 eeschema/events_called_functions_for_edit.cpp
create mode 100644 eeschema/files-io.cpp
create mode 100644 eeschema/find.cpp
create mode 100644 eeschema/general.h
create mode 100644 eeschema/getpart.cpp
create mode 100644 eeschema/help_common_strings.h
create mode 100644 eeschema/hierarch.cpp
create mode 100644 eeschema/hotkeys.cpp
create mode 100644 eeschema/hotkeys.h
create mode 100644 eeschema/invoke_sch_dialog.h
create mode 100644 eeschema/lib_arc.cpp
create mode 100644 eeschema/lib_arc.h
create mode 100644 eeschema/lib_bezier.cpp
create mode 100644 eeschema/lib_bezier.h
create mode 100644 eeschema/lib_circle.cpp
create mode 100644 eeschema/lib_circle.h
create mode 100644 eeschema/lib_collectors.cpp
create mode 100644 eeschema/lib_collectors.h
create mode 100644 eeschema/lib_draw_item.cpp
create mode 100644 eeschema/lib_draw_item.h
create mode 100644 eeschema/lib_export.cpp
create mode 100644 eeschema/lib_field.cpp
create mode 100644 eeschema/lib_field.h
create mode 100644 eeschema/lib_pin.cpp
create mode 100644 eeschema/lib_pin.h
create mode 100644 eeschema/lib_polyline.cpp
create mode 100644 eeschema/lib_polyline.h
create mode 100644 eeschema/lib_rectangle.cpp
create mode 100644 eeschema/lib_rectangle.h
create mode 100644 eeschema/lib_text.cpp
create mode 100644 eeschema/lib_text.h
create mode 100644 eeschema/libarch.cpp
create mode 100644 eeschema/libedit.cpp
create mode 100644 eeschema/libedit_onleftclick.cpp
create mode 100644 eeschema/libedit_onrightclick.cpp
create mode 100644 eeschema/libedit_plot_component.cpp
create mode 100644 eeschema/libedit_undo_redo.cpp
create mode 100644 eeschema/libeditframe.cpp
create mode 100644 eeschema/libeditframe.h
create mode 100644 eeschema/libfield.cpp
create mode 100644 eeschema/load_one_schematic_file.cpp
create mode 100644 eeschema/menubar.cpp
create mode 100644 eeschema/menubar_libedit.cpp
create mode 100644 eeschema/netform.cpp
create mode 100644 eeschema/netlist.cpp
create mode 100644 eeschema/netlist.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter_cadstar.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter_cadstar.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter_generic.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter_generic.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter_kicad.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter_kicad.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter_orcadpcb2.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter_orcadpcb2.h
create mode 100644 eeschema/netlist_exporters/netlist_exporter_pspice.cpp
create mode 100644 eeschema/netlist_exporters/netlist_exporter_pspice.h
create mode 100644 eeschema/onleftclick.cpp
create mode 100644 eeschema/onrightclick.cpp
create mode 100644 eeschema/operations_on_items_lists.cpp
create mode 100644 eeschema/pinedit.cpp
create mode 100644 eeschema/plot_schematic_DXF.cpp
create mode 100644 eeschema/plot_schematic_HPGL.cpp
create mode 100644 eeschema/plot_schematic_PDF.cpp
create mode 100644 eeschema/plot_schematic_PS.cpp
create mode 100644 eeschema/plot_schematic_SVG.cpp
create mode 100644 eeschema/plugins/CMakeLists.txt
create mode 100644 eeschema/plugins/python_scripts/README-bom.txt
create mode 100644 eeschema/plugins/python_scripts/bom_csv_grouped_by_value.py
create mode 100644 eeschema/plugins/python_scripts/bom_csv_grouped_by_value_with_fp.py
create mode 100644 eeschema/plugins/python_scripts/bom_csv_sorted_by_ref.py
create mode 100644 eeschema/plugins/python_scripts/bom_html_grouped_by_value.py
create mode 100644 eeschema/plugins/python_scripts/bom_html_with_advanced_grouping.py
create mode 100644 eeschema/plugins/python_scripts/bom_sorted_by_ref.py
create mode 100644 eeschema/plugins/python_scripts/kicad_netlist_reader.py
create mode 100644 eeschema/plugins/python_scripts/round_robin.py
create mode 100644 eeschema/plugins/python_scripts/round_value_robin.py
create mode 100644 eeschema/plugins/xsl_scripts/bom2csv.xsl
create mode 100644 eeschema/plugins/xsl_scripts/bom2grouped_csv.xsl
create mode 100644 eeschema/plugins/xsl_scripts/bom_with_title_block_2_csv.xsl
create mode 100644 eeschema/plugins/xsl_scripts/netlist_form_OrcadPcb2.xsl
create mode 100644 eeschema/plugins/xsl_scripts/netlist_form_cadstar-RINF.xsl
create mode 100644 eeschema/plugins/xsl_scripts/netlist_form_cadstar.xsl
create mode 100644 eeschema/plugins/xsl_scripts/netlist_form_pads-pcb.xsl
create mode 100644 eeschema/project_rescue.cpp
create mode 100644 eeschema/project_rescue.h
create mode 100644 eeschema/protos.h
create mode 100644 eeschema/sch_base_frame.cpp
create mode 100644 eeschema/sch_base_frame.h
create mode 100644 eeschema/sch_bitmap.cpp
create mode 100644 eeschema/sch_bitmap.h
create mode 100644 eeschema/sch_bus_entry.cpp
create mode 100644 eeschema/sch_bus_entry.h
create mode 100644 eeschema/sch_collectors.cpp
create mode 100644 eeschema/sch_collectors.h
create mode 100644 eeschema/sch_component.cpp
create mode 100644 eeschema/sch_component.h
create mode 100644 eeschema/sch_field.cpp
create mode 100644 eeschema/sch_field.h
create mode 100644 eeschema/sch_item_struct.cpp
create mode 100644 eeschema/sch_item_struct.h
create mode 100644 eeschema/sch_junction.cpp
create mode 100644 eeschema/sch_junction.h
create mode 100644 eeschema/sch_line.cpp
create mode 100644 eeschema/sch_line.h
create mode 100644 eeschema/sch_marker.cpp
create mode 100644 eeschema/sch_marker.h
create mode 100644 eeschema/sch_no_connect.cpp
create mode 100644 eeschema/sch_no_connect.h
create mode 100644 eeschema/sch_reference_list.h
create mode 100644 eeschema/sch_screen.cpp
create mode 100644 eeschema/sch_sheet.cpp
create mode 100644 eeschema/sch_sheet.h
create mode 100644 eeschema/sch_sheet_path.cpp
create mode 100644 eeschema/sch_sheet_path.h
create mode 100644 eeschema/sch_sheet_pin.cpp
create mode 100644 eeschema/sch_text.cpp
create mode 100644 eeschema/sch_text.h
create mode 100644 eeschema/sch_validators.cpp
create mode 100644 eeschema/sch_validators.h
create mode 100644 eeschema/schedit.cpp
create mode 100644 eeschema/schematic_undo_redo.cpp
create mode 100644 eeschema/schframe.cpp
create mode 100644 eeschema/schframe.h
create mode 100644 eeschema/selpart.cpp
create mode 100644 eeschema/sheet.cpp
create mode 100644 eeschema/sheetlab.cpp
create mode 100644 eeschema/symbdraw.cpp
create mode 100644 eeschema/symbedit.cpp
create mode 100644 eeschema/template_fieldnames.cpp
create mode 100644 eeschema/template_fieldnames.h
create mode 100644 eeschema/template_fieldnames.keywords
create mode 100644 eeschema/tool_lib.cpp
create mode 100644 eeschema/tool_sch.cpp
create mode 100644 eeschema/tool_viewlib.cpp
create mode 100644 eeschema/transform.cpp
create mode 100644 eeschema/transform.h
create mode 100644 eeschema/viewlib_frame.cpp
create mode 100644 eeschema/viewlib_frame.h
create mode 100644 eeschema/viewlibs.cpp
(limited to 'eeschema')
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
new file mode 100644
index 00000000..eb06147a
--- /dev/null
+++ b/eeschema/CMakeLists.txt
@@ -0,0 +1,383 @@
+# the map generation creates on Windows/gcc a lot of useless warnings
+# so disable it on windows
+if( WIN32 AND NOT CMAKE_CROSSCOMPILING )
+ set( MAKE_LINK_MAPS false )
+else()
+ set( MAKE_LINK_MAPS true )
+endif()
+
+add_definitions( -DEESCHEMA )
+
+
+include_directories( BEFORE ${INC_BEFORE} )
+include_directories(
+ ./dialogs
+ ./netlist_exporters
+ ../common
+ ../common/dialogs
+ ${INC_AFTER}
+ )
+
+
+set( EESCHEMA_DLGS
+ dialogs/dialog_annotate.cpp
+ dialogs/dialog_annotate_base.cpp
+ dialogs/dialog_bom.cpp
+ dialogs/dialog_bom_base.cpp
+ dialogs/dialog_bom_cfg_keywords.cpp
+ dialogs/dialog_color_config.cpp
+ dialogs/dialog_color_config_base.cpp
+ dialogs/dialog_choose_component.cpp
+ dialogs/dialog_choose_component_base.cpp
+ dialogs/dialog_lib_edit_text.cpp
+ dialogs/dialog_lib_edit_text_base.cpp
+ dialogs/dialog_edit_component_in_lib.cpp
+ dialogs/dialog_edit_component_in_lib_base.cpp
+ dialogs/dialog_edit_component_in_schematic_fbp.cpp
+ dialogs/dialog_edit_component_in_schematic.cpp
+ dialogs/dialog_edit_label.cpp
+ dialogs/dialog_edit_label_base.cpp
+ dialogs/dialog_edit_libentry_fields_in_lib.cpp
+ dialogs/dialog_edit_libentry_fields_in_lib_base.cpp
+ dialogs/dialog_edit_one_field.cpp
+ dialogs/dialog_eeschema_config.cpp
+ dialogs/dialog_eeschema_config_fbp.cpp
+ dialogs/dialog_eeschema_options_base.cpp
+ dialogs/dialog_eeschema_options.cpp
+ dialogs/dialog_erc.cpp
+ dialogs/dialog_erc_base.cpp
+ dialogs/dialog_lib_edit_draw_item.cpp
+ dialogs/dialog_lib_edit_draw_item_base.cpp
+ dialogs/dialog_libedit_options_base.cpp
+ dialogs/dialog_libedit_options.cpp
+ dialogs/dialog_lib_edit_pin.cpp
+ dialogs/dialog_lib_edit_pin_base.cpp
+ dialogs/dialog_lib_edit_pin_table.cpp
+ dialogs/dialog_lib_edit_pin_table_base.cpp
+ dialogs/dialog_lib_new_component.cpp
+ dialogs/dialog_lib_new_component_base.cpp
+ dialogs/dialog_netlist.cpp
+ dialogs/dialog_netlist_base.cpp
+ dialogs/dialog_plot_schematic_base.cpp
+ dialogs/dialog_plot_schematic.cpp
+ dialogs/dialog_print_using_printer_base.cpp
+ dialogs/dialog_print_using_printer.cpp
+ dialogs/dialog_rescue_each.cpp
+ dialogs/dialog_rescue_each_base.cpp
+ dialogs/dialog_sch_edit_sheet_pin.cpp
+ dialogs/dialog_sch_edit_sheet_pin_base.cpp
+ dialogs/dialog_sch_sheet_props.cpp
+ dialogs/dialog_sch_sheet_props_base.cpp
+ dialogs/dialog_schematic_find.cpp
+ dialogs/dialog_schematic_find_base.cpp
+ )
+
+set( EESCHEMA_SRCS
+ annotate.cpp
+ backanno.cpp
+ block.cpp
+ block_libedit.cpp
+ busentry.cpp
+ bus-wire-junction.cpp
+ class_drc_erc_item.cpp
+ class_libentry.cpp
+ class_library.cpp
+ class_netlist_object.cpp
+ cmp_library_keywords.cpp
+ cmp_library_lexer.cpp
+ component_references_lister.cpp
+ controle.cpp
+ cross-probing.cpp
+ ${EESCHEMA_DLGS}
+ edit_component_in_schematic.cpp
+ edit_bitmap.cpp
+ edit_label.cpp
+ eeredraw.cpp
+ eeschema.cpp
+ eeschema_config.cpp
+ erc.cpp
+ events_called_functions_for_edit.cpp
+ files-io.cpp
+ find.cpp
+ getpart.cpp
+ component_tree_search_container.cpp
+ hierarch.cpp
+ hotkeys.cpp
+ libarch.cpp
+ libedit.cpp
+ libeditframe.cpp
+ libedit_onleftclick.cpp
+ libedit_onrightclick.cpp
+ libedit_plot_component.cpp
+ libedit_undo_redo.cpp
+ lib_arc.cpp
+ lib_bezier.cpp
+ lib_circle.cpp
+ lib_collectors.cpp
+ lib_draw_item.cpp
+ lib_export.cpp
+ lib_field.cpp
+ lib_pin.cpp
+ lib_polyline.cpp
+ lib_rectangle.cpp
+ lib_text.cpp
+ libfield.cpp
+ load_one_schematic_file.cpp
+ menubar.cpp
+ menubar_libedit.cpp
+ netform.cpp
+ netlist.cpp
+ onleftclick.cpp
+ onrightclick.cpp
+ operations_on_items_lists.cpp
+ pinedit.cpp
+ plot_schematic_DXF.cpp
+ plot_schematic_HPGL.cpp
+ plot_schematic_PS.cpp
+ plot_schematic_PDF.cpp
+ plot_schematic_SVG.cpp
+ project_rescue.cpp
+ sch_base_frame.cpp
+ sch_bitmap.cpp
+ sch_bus_entry.cpp
+ sch_collectors.cpp
+ sch_component.cpp
+ sch_field.cpp
+ sch_item_struct.cpp
+ sch_junction.cpp
+ sch_line.cpp
+ sch_marker.cpp
+ sch_no_connect.cpp
+ sch_screen.cpp
+ sch_sheet.cpp
+ sch_sheet_path.cpp
+ sch_sheet_pin.cpp
+ sch_text.cpp
+ sch_validators.cpp
+ schedit.cpp
+ schematic_undo_redo.cpp
+ schframe.cpp
+ selpart.cpp
+ sheet.cpp
+ sheetlab.cpp
+ symbdraw.cpp
+ symbedit.cpp
+ template_fieldnames_keywords.cpp
+ template_fieldnames.cpp
+ tool_lib.cpp
+ tool_sch.cpp
+ tool_viewlib.cpp
+ transform.cpp
+ viewlib_frame.cpp
+ viewlibs.cpp
+
+ netlist_exporters/netlist_exporter.cpp
+ netlist_exporters/netlist_exporter_cadstar.cpp
+ netlist_exporters/netlist_exporter_generic.cpp
+ netlist_exporters/netlist_exporter_kicad.cpp
+ netlist_exporters/netlist_exporter_orcadpcb2.cpp
+ netlist_exporters/netlist_exporter_pspice.cpp
+ )
+
+
+set( EESCHEMA_COMMON_SRCS
+ ../common/dialogs/dialog_page_settings.cpp
+ ../common/base_screen.cpp
+ ../common/eda_text.cpp
+ ../common/class_page_info.cpp
+ ../common/base_units.cpp
+ )
+
+
+if( MINGW )
+ # EESCHEMA_RESOURCES variable is set by the macro.
+ mingw_resource_compiler( eeschema )
+else()
+ set( EESCHEMA_RESOURCES eeschema.rc )
+endif()
+
+# Create a C++ compilable string initializer containing html text into a *.h file:
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help_html.h
+ COMMAND ${CMAKE_COMMAND}
+ -DinputFile=${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help.html
+ -DoutputFile=${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help_html.h
+ -P ${CMAKE_MODULE_PATH}/Html2C.cmake
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help.html
+ COMMENT "creating ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help_html.h
+ from ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help.html"
+ )
+
+set_source_files_properties( dialogs/dialog_bom.cpp
+ PROPERTIES
+ OBJECT_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_help_html.h
+ )
+
+if( APPLE )
+ # setup bundle
+ set( EESCHEMA_RESOURCES eeschema.icns eeschema_doc.icns )
+ set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/eeschema.icns" PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources
+ )
+ set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/eeschema_doc.icns" PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources
+ )
+ set( MACOSX_BUNDLE_ICON_FILE eeschema.icns )
+ set( MACOSX_BUNDLE_GUI_IDENTIFIER org.kicad-pcb.kicad )
+ set( MACOSX_BUNDLE_NAME eeschema )
+endif()
+
+
+add_executable( eeschema WIN32 MACOSX_BUNDLE
+ ../common/single_top.cpp
+ ../common/pgm_base.cpp
+ ${EESCHEMA_RESOURCES}
+ )
+set_source_files_properties( ../common/single_top.cpp PROPERTIES
+ COMPILE_DEFINITIONS "TOP_FRAME=FRAME_SCH;PGM_DATA_FILE_EXT=\"sch\";BUILD_KIWAY_DLL"
+ )
+target_link_libraries( eeschema
+ #singletop # replaces common, giving us restrictive control and link warnings.
+ # There's way too much crap coming in from common yet.
+ common
+ bitmaps
+ ${wxWidgets_LIBRARIES}
+ )
+
+# the DSO (KIFACE) housing the main eeschema code:
+add_library( eeschema_kiface MODULE
+ ${EESCHEMA_SRCS}
+ ${EESCHEMA_COMMON_SRCS}
+ )
+target_link_libraries( eeschema_kiface
+ common
+ bitmaps
+ polygon
+ gal
+ ${wxWidgets_LIBRARIES}
+ ${GDI_PLUS_LIBRARIES}
+ )
+set_target_properties( eeschema_kiface PROPERTIES
+ # Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like
+ # _eeschema.so, _eeschema.dll, or _eeschema.kiface
+ OUTPUT_NAME eeschema
+ PREFIX ${KIFACE_PREFIX}
+ SUFFIX ${KIFACE_SUFFIX}
+ )
+
+# The KIFACE is in eeschema.cpp, export it:
+set_source_files_properties( eeschema.cpp PROPERTIES
+ COMPILE_DEFINITIONS "BUILD_KIWAY_DLL;COMPILING_DLL"
+ )
+
+# if building eeschema, then also build eeschema_kiface if out of date.
+add_dependencies( eeschema eeschema_kiface )
+
+if( MAKE_LINK_MAPS )
+ # generate link map with cross reference
+ set_target_properties( eeschema_kiface PROPERTIES
+ LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=${KIFACE_PREFIX}eeschema${KIFACE_SUFFIX}.map"
+ )
+ set_target_properties( eeschema PROPERTIES
+ LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=eeschema.map"
+ )
+endif()
+
+# these 2 binaries are a matched set, keep them together:
+if( APPLE )
+ set_target_properties( eeschema PROPERTIES
+ MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
+ )
+
+ # puts binaries into the *.app bundle while linking
+ set_target_properties( eeschema_kiface PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${OSX_BUNDLE_BUILD_KIFACE_DIR}
+ )
+ # put individual bundle outside of main bundle as a first step
+ # will be pulled into the main bundle when creating main bundle
+ install( TARGETS eeschema
+ DESTINATION ${KICAD_BIN}
+ COMPONENT binary
+ )
+ install( CODE "
+ # override default embedded path settings
+ ${OSX_BUNDLE_OVERRIDE_PATHS}
+
+ # do all the work
+ include( BundleUtilities )
+ fixup_bundle( ${KICAD_BIN}/eeschema.app/Contents/MacOS/eeschema
+ \"\"
+ \"\"
+ )
+ " COMPONENT Runtime
+ )
+else()
+ install( TARGETS eeschema
+ DESTINATION ${KICAD_BIN}
+ COMPONENT binary
+ )
+ install( TARGETS eeschema_kiface
+ # actual filename subject to change at milestone C)
+ # modular-kicad blueprint.
+ DESTINATION ${KICAD_BIN}
+ COMPONENT binary
+ )
+endif()
+
+# auto-generate cmp_library_lexer.h and cmp_library_keywords.cpp for the component
+# library format.
+make_lexer(
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library.keywords
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp
+ TLIB_T
+ )
+
+add_custom_target(
+ cmp_library_lexer_source_files ALL
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp_library_keywords.cpp
+ )
+
+add_dependencies( eeschema_kiface cmp_library_lexer_source_files )
+
+make_lexer(
+ ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames.keywords
+ ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp
+ TFIELD_T
+
+ # Pass header file with dependency on *_lexer.h as extra_arg
+ template_fieldnames.h
+ )
+
+add_custom_target(
+ field_template_lexer_source_files ALL
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/template_fieldnames_keywords.cpp
+ )
+
+add_dependencies( eeschema_kiface field_template_lexer_source_files )
+
+make_lexer(
+ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg.keywords
+ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp
+ T_BOMCFG_T
+
+ # Pass header file with dependency on *_lexer.h as extra_arg
+ dialogs/dialog_bom_cfg.h
+ )
+
+add_custom_target(
+ dialog_bom_cfg_lexer_source_files ALL
+ DEPENDS
+ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_lexer.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/dialog_bom_cfg_keywords.cpp
+ )
+
+add_dependencies( eeschema_kiface dialog_bom_cfg_lexer_source_files )
+
+add_subdirectory( plugins )
diff --git a/eeschema/Info.plist b/eeschema/Info.plist
new file mode 100644
index 00000000..7d8663d2
--- /dev/null
+++ b/eeschema/Info.plist
@@ -0,0 +1,35 @@
+
+
+
+
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeRoleEditor
+ CFBundleTypeExtensions
+
+ sch
+
+ CFBundleTypeIconFileeeschema_doc.icns
+ CFBundleTypeNameeeschema document
+ LSHandlerRankOwner
+
+
+ CFBundleDevelopmentRegionEnglish
+ CFBundleExecutableeeschema
+ CFBundleGetInfoString
+ CFBundleIconFileeeschema.icns
+ CFBundleIdentifierorg.kicad-pcb.eeschema
+ CFBundleInfoDictionaryVersion6.0
+ CFBundleLongVersionString
+ CFBundleNameEESchema
+ CFBundlePackageTypeAPPL
+ CFBundleShortVersionString
+ CFBundleSignature????
+ CFBundleVersion
+ CSResourcesFileMapped
+ LSRequiresCarbon
+ NSHumanReadableCopyright
+ NSHighResolutionCapableTrue
+
+
diff --git a/eeschema/annotate.cpp b/eeschema/annotate.cpp
new file mode 100644
index 00000000..1b2a27d2
--- /dev/null
+++ b/eeschema/annotate.cpp
@@ -0,0 +1,200 @@
+/**
+ * @file annotate.cpp
+ * @brief Component annotation.
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004-2013 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+void SCH_EDIT_FRAME::DeleteAnnotation( bool aCurrentSheetOnly )
+{
+ if( aCurrentSheetOnly )
+ {
+ SCH_SCREEN* screen = GetScreen();
+ wxCHECK_RET( screen != NULL, wxT( "Attempt to clear annotation of a NULL screen." ) );
+ screen->ClearAnnotation( m_CurrentSheet );
+ }
+ else
+ {
+ SCH_SCREENS ScreenList;
+ ScreenList.ClearAnnotation();
+ }
+
+ // Update the references for the sheet that is currently being displayed.
+ m_CurrentSheet->UpdateAllScreenReferences();
+ GetCanvas()->Refresh();
+ OnModify();
+}
+
+
+void SCH_EDIT_FRAME::AnnotateComponents( bool aAnnotateSchematic,
+ ANNOTATE_ORDER_T aSortOption,
+ ANNOTATE_OPTION_T aAlgoOption,
+ bool aResetAnnotation,
+ bool aRepairTimestamps,
+ bool aLockUnits )
+{
+ SCH_REFERENCE_LIST references;
+
+ SCH_SCREENS screens;
+
+ // Build the sheet list.
+ SCH_SHEET_LIST sheets;
+
+ // Map of locked components
+ SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;
+
+ // Test for and replace duplicate time stamps in components and sheets. Duplicate
+ // time stamps can happen with old schematics, schematic conversions, or manual
+ // editing of files.
+ if( aRepairTimestamps )
+ {
+ int count = screens.ReplaceDuplicateTimeStamps();
+
+ if( count )
+ {
+ wxString msg;
+ msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
+ DisplayInfoMessage( NULL, msg, 2 );
+ }
+ }
+
+ // If units must be locked, collect all the sets that must be annotated together.
+ if( aLockUnits )
+ {
+ if( aAnnotateSchematic )
+ {
+ sheets.GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
+ }
+ else
+ {
+ m_CurrentSheet->GetMultiUnitComponents( Prj().SchLibs(), lockedComponents );
+ }
+ }
+
+ // If it is an annotation for all the components, reset previous annotation.
+ if( aResetAnnotation )
+ DeleteAnnotation( !aAnnotateSchematic );
+
+ // Set sheet number and number of sheets.
+ SetSheetNumberAndCount();
+
+ // Build component list
+ if( aAnnotateSchematic )
+ {
+ sheets.GetComponents( Prj().SchLibs(), references );
+ }
+ else
+ {
+ m_CurrentSheet->GetComponents( Prj().SchLibs(), references );
+ }
+
+ // Break full components reference in name (prefix) and number:
+ // example: IC1 become IC, and 1
+ references.SplitReferences();
+
+ switch( aSortOption )
+ {
+ default:
+ case SORT_BY_X_POSITION:
+ references.SortByXCoordinate();
+ break;
+
+ case SORT_BY_Y_POSITION:
+ references.SortByYCoordinate();
+ break;
+ }
+
+ bool useSheetNum = false;
+ int idStep = 100;
+
+ switch( aAlgoOption )
+ {
+ default:
+ case INCREMENTAL_BY_REF:
+ break;
+
+ case SHEET_NUMBER_X_100:
+ useSheetNum = true;
+ break;
+
+ case SHEET_NUMBER_X_1000:
+ useSheetNum = true;
+ idStep = 1000;
+ break;
+ }
+
+ // Recalculate and update reference numbers in schematic
+ references.Annotate( useSheetNum, idStep, lockedComponents );
+ references.UpdateAnnotation();
+
+ wxArrayString errors;
+
+ // Final control (just in case ... ).
+ if( CheckAnnotate( &errors, !aAnnotateSchematic ) )
+ {
+ wxString msg;
+
+ for( size_t i = 0; i < errors.GetCount(); i++ )
+ msg += errors[i];
+
+ // wxLogWarning is a cheap and dirty way to dump a potentially long list of
+ // strings to a dialog that can be saved to a file. This should be replaced
+ // by a more elegant solution.
+ wxLogWarning( msg );
+ }
+
+ OnModify();
+
+ // Update on screen references, that can be modified by previous calculations:
+ m_CurrentSheet->UpdateAllScreenReferences();
+ SetSheetNumberAndCount();
+
+ m_canvas->Refresh( true );
+}
+
+
+int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly )
+{
+ // build the screen list
+ SCH_SHEET_LIST SheetList;
+ SCH_REFERENCE_LIST ComponentsList;
+
+ // Build the list of components
+ if( !aOneSheetOnly )
+ SheetList.GetComponents( Prj().SchLibs(), ComponentsList );
+ else
+ m_CurrentSheet->GetComponents( Prj().SchLibs(), ComponentsList );
+
+ return ComponentsList.CheckAnnotation( aMessageList );
+}
diff --git a/eeschema/backanno.cpp b/eeschema/backanno.cpp
new file mode 100644
index 00000000..671f727b
--- /dev/null
+++ b/eeschema/backanno.cpp
@@ -0,0 +1,264 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2013 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file backanno.cpp
+ * @brief Functions for backannotating footprint information.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+void SCH_EDIT_FRAME::backAnnotateFootprints( const std::string& aChangedSetOfReferences )
+ throw( IO_ERROR, boost::bad_pointer )
+{
+ // Build a flat list of components in schematic:
+ SCH_REFERENCE_LIST refs;
+ SCH_SHEET_LIST sheets;
+ bool isChanged = false;
+
+ sheets.GetComponents( Prj().SchLibs(), refs, false );
+
+ DSNLEXER lexer( aChangedSetOfReferences, FROM_UTF8( __func__ ) );
+ PTREE doc;
+
+ try
+ {
+ Scan( &doc, &lexer );
+
+#if defined(DEBUG) && 0
+ STRING_FORMATTER sf;
+ Format( &sf, 0, 0, doc );
+ printf( "%s: '%s'\n", __func__, sf.GetString().c_str() );
+#endif
+
+ CPTREE& back_anno = doc.get_child( "back_annotation" );
+ wxString footprint;
+
+ for( PTREE::const_iterator ref = back_anno.begin(); ref != back_anno.end(); ++ref )
+ {
+ wxASSERT( ref->first == "ref" );
+
+ wxString reference = (UTF8&) ref->second.front().first;
+
+ // Ensure the "fpid" node contains a footprint name,
+ // and get it if exists
+ if( ref->second.get_child( "fpid" ).size() )
+ {
+ wxString tmp = (UTF8&) ref->second.get_child( "fpid" ).front().first;
+ footprint = tmp;
+ }
+ else
+ footprint.Empty();
+
+ // DBG( printf( "%s: ref:%s fpid:%s\n", __func__, TO_UTF8( reference ), TO_UTF8( footprint ) ); )
+
+ // Search the component in the flat list
+ for( unsigned ii = 0; ii < refs.GetCount(); ++ii )
+ {
+ if( Cmp_KEEPCASE( reference, refs[ii].GetRef() ) == 0 )
+ {
+ // We have found a candidate.
+ // Note: it can be not unique (multiple parts per package)
+ // So we *do not* stop the search here
+ SCH_COMPONENT* component = refs[ii].GetComp();
+ SCH_FIELD* fpfield = component->GetField( FOOTPRINT );
+ const wxString& oldfp = fpfield->GetText();
+
+ if( !oldfp && fpfield->IsVisible() )
+ {
+ fpfield->SetVisible( false );
+ }
+
+ // DBG( printf("%s: ref:%s fpid:%s\n", __func__, TO_UTF8( refs[ii].GetRef() ), TO_UTF8( footprint ) );)
+ if( oldfp != footprint )
+ isChanged = true;
+
+ fpfield->SetText( footprint );
+ }
+ }
+ }
+ }
+ catch( const PTREE_ERROR& ex )
+ {
+ // remap the exception to something the caller is likely to understand.
+ THROW_IO_ERROR( ex.what() );
+ }
+
+ if( isChanged )
+ OnModify();
+}
+
+
+bool SCH_EDIT_FRAME::ProcessCmpToFootprintLinkFile( const wxString& aFullFilename,
+ bool aForceVisibilityState,
+ bool aVisibilityState )
+{
+ // Build a flat list of components in schematic:
+ SCH_REFERENCE_LIST referencesList;
+ SCH_SHEET_LIST sheetList;
+
+ sheetList.GetComponents( Prj().SchLibs(), referencesList, false );
+
+ FILE* cmpFile = wxFopen( aFullFilename, wxT( "rt" ) );
+
+ if( cmpFile == NULL )
+ return false;
+
+ // cmpFileReader dtor will close cmpFile
+ FILE_LINE_READER cmpFileReader( cmpFile, aFullFilename );
+
+ // Now, for each component found in file,
+ // replace footprint field value by the new value:
+ wxString reference;
+ wxString footprint;
+ wxString buffer;
+ wxString value;
+
+ while( cmpFileReader.ReadLine() )
+ {
+ buffer = FROM_UTF8( cmpFileReader.Line() );
+
+ if( !buffer.StartsWith( wxT( "BeginCmp" ) ) )
+ continue;
+
+ // Begin component description.
+ reference.Empty();
+ footprint.Empty();
+
+ while( cmpFileReader.ReadLine() )
+ {
+ buffer = FROM_UTF8( cmpFileReader.Line() );
+
+ if( buffer.StartsWith( wxT( "EndCmp" ) ) )
+ break;
+
+ // store string value, stored between '=' and ';' delimiters.
+ value = buffer.AfterFirst( '=' );
+ value = value.BeforeLast( ';' );
+ value.Trim(true);
+ value.Trim(false);
+
+ if( buffer.StartsWith( wxT( "Reference" ) ) )
+ {
+ reference = value;
+ }
+ else if( buffer.StartsWith( wxT( "IdModule" ) ) )
+ {
+ footprint = value;
+ }
+ }
+
+ // A block is read: initialize the footprint field of the corresponding component
+ // if the footprint name is not empty
+ if( reference.IsEmpty() )
+ continue;
+
+ // Search the component in the flat list
+ for( unsigned ii = 0; ii < referencesList.GetCount(); ii++ )
+ {
+ if( Cmp_KEEPCASE( reference, referencesList[ii].GetRef() ) == 0 )
+ {
+ // We have found a candidate.
+ // Note: it can be not unique (multiple units per part)
+ // So we *do not* stop the search here
+ SCH_COMPONENT* component = referencesList[ii].GetComp();
+ SCH_FIELD* fpfield = component->GetField( FOOTPRINT );
+
+ fpfield->SetText( footprint );
+
+ if( aForceVisibilityState )
+ {
+ component->GetField( FOOTPRINT )->SetVisible( aVisibilityState );
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool SCH_EDIT_FRAME::LoadCmpToFootprintLinkFile()
+{
+ wxString path = wxPathOnly( Prj().GetProjectFullName() );
+
+ wxFileDialog dlg( this, _( "Load Component Footprint Link File" ),
+ path, wxEmptyString,
+ ComponentFileExtensionWildcard,
+ wxFD_OPEN | wxFD_FILE_MUST_EXIST );
+
+ if( dlg.ShowModal() == wxID_CANCEL )
+ return false;
+
+ wxString filename = dlg.GetPath();
+ wxString title = wxT( "Eeschema " ) + GetBuildVersion() + wxT( ' ' ) + filename;
+
+ SetTitle( title );
+
+ wxArrayString choices;
+ choices.Add( _( "Keep existing footprint field visibility" ) );
+ choices.Add( _( "Show all footprint fields" ) );
+ choices.Add( _( "Hide all footprint fields" ) );
+
+ wxSingleChoiceDialog choiceDlg( this, _( "Select the footprint field visibility setting." ),
+ _( "Change Visibility" ), choices );
+
+
+ if( choiceDlg.ShowModal() == wxID_CANCEL )
+ return false;
+
+ bool forceVisibility = (choiceDlg.GetSelection() != 0 );
+ bool visibilityState = (choiceDlg.GetSelection() == 1 );
+
+ if( !ProcessCmpToFootprintLinkFile( filename, forceVisibility, visibilityState ) )
+ {
+ wxString msg = wxString::Format( _( "Failed to open component-footprint link file '%s'" ),
+ filename.GetData() );
+
+ DisplayError( this, msg );
+ return false;
+ }
+
+ OnModify();
+ return true;
+}
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
new file mode 100644
index 00000000..e4b38e9f
--- /dev/null
+++ b/eeschema/block.cpp
@@ -0,0 +1,538 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2009-2015 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file eeschema/block.cpp
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Imported functions:
+extern void SetSchItemParent( SCH_ITEM* Struct, SCH_SCREEN* Screen );
+extern void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint aMoveVector );
+extern void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center );
+extern void MirrorX( PICKED_ITEMS_LIST& aItemsList, wxPoint& aMirrorPoint );
+extern void MirrorY( PICKED_ITEMS_LIST& aItemsList, wxPoint& Center );
+extern void DuplicateItemsInList( SCH_SCREEN* screen,
+ PICKED_ITEMS_LIST& aItemsList,
+ const wxPoint aMoveVector );
+
+static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC,
+ const wxPoint& aPosition, bool aErase );
+
+
+int SCH_EDIT_FRAME::BlockCommand( int key )
+{
+ int cmd = BLOCK_IDLE;
+
+ switch( key )
+ {
+ default:
+ cmd = key & 0xFF;
+ break;
+
+ case 0:
+ cmd = BLOCK_MOVE;
+ break;
+
+ case GR_KB_SHIFT:
+ cmd = BLOCK_COPY;
+ break;
+
+ case GR_KB_ALT:
+ cmd = BLOCK_ROTATE;
+ break;
+
+ case GR_KB_CTRL:
+ cmd = BLOCK_DRAG;
+ break;
+
+ case GR_KB_SHIFTCTRL:
+ cmd = BLOCK_DELETE;
+ break;
+
+ case MOUSE_MIDDLE:
+ cmd = BLOCK_ZOOM;
+ break;
+ }
+
+ return cmd;
+}
+
+
+void SCH_EDIT_FRAME::InitBlockPasteInfos()
+{
+ BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate;
+
+ block->GetItems().CopyList( m_blockItems.GetItems() );
+ m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
+}
+
+
+void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
+{
+ BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate;
+
+ if( !m_canvas->IsMouseCaptured() )
+ {
+ DisplayError( this, wxT( "HandleBlockPLace() : m_mouseCaptureCallback = NULL" ) );
+ }
+
+ if( block->GetCount() == 0 )
+ {
+ wxString msg;
+ msg.Printf( wxT( "HandleBlockPLace() error : no items to place (cmd %d, state %d)" ),
+ block->GetCommand(), block->GetState() );
+ DisplayError( this, msg );
+ }
+
+ block->SetState( STATE_BLOCK_STOP );
+
+ switch( block->GetCommand() )
+ {
+ case BLOCK_DRAG: // Drag from mouse
+ case BLOCK_DRAG_ITEM: // Drag from a component selection and drag command
+ case BLOCK_MOVE:
+ if( m_canvas->IsMouseCaptured() )
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+
+ SaveCopyInUndoList( block->GetItems(), UR_MOVED, block->GetMoveVector() );
+ MoveItemsInList( block->GetItems(), block->GetMoveVector() );
+ block->ClearItemsList();
+ break;
+
+ case BLOCK_COPY: /* Copy */
+ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/
+ if( m_canvas->IsMouseCaptured() )
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+
+ DuplicateItemsInList( GetScreen(), block->GetItems(), block->GetMoveVector() );
+
+ SaveCopyInUndoList( block->GetItems(),
+ ( block->GetCommand() == BLOCK_PRESELECT_MOVE ) ? UR_CHANGED : UR_NEW );
+
+ block->ClearItemsList();
+ break;
+
+ case BLOCK_PASTE:
+ if( m_canvas->IsMouseCaptured() )
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+
+ PasteListOfItems( DC );
+ block->ClearItemsList();
+ break;
+
+ default: // others are handled by HandleBlockEnd()
+ break;
+ }
+
+ OnModify();
+
+ // clear dome flags and pointers
+ GetScreen()->ClearDrawingState();
+ GetScreen()->ClearBlockCommand();
+ GetScreen()->SetCurItem( NULL );
+ GetScreen()->TestDanglingEnds( m_canvas, DC );
+
+ if( block->GetCount() )
+ {
+ DisplayError( this, wxT( "HandleBlockPLace() error: some items left in buffer" ) );
+ block->ClearItemsList();
+ }
+
+ m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false );
+ m_canvas->Refresh();
+}
+
+
+bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
+{
+ bool nextcmd = false;
+ bool zoom_command = false;
+ BLOCK_SELECTOR* block = &GetScreen()->m_BlockLocate;
+
+ if( block->GetCount() )
+ {
+ BLOCK_STATE_T state = block->GetState();
+ BLOCK_COMMAND_T command = block->GetCommand();
+
+ m_canvas->CallEndMouseCapture( aDC );
+
+ block->SetState( state );
+ block->SetCommand( command );
+ m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand );
+ SetCrossHairPosition( block->GetEnd() );
+
+ if( block->GetCommand() != BLOCK_ABORT )
+ m_canvas->MoveCursorToCrossHair();
+ }
+
+ if( m_canvas->IsMouseCaptured() )
+ {
+ switch( block->GetCommand() )
+ {
+ case BLOCK_IDLE:
+ DisplayError( this, wxT( "Error in HandleBlockPLace()" ) );
+ break;
+
+ case BLOCK_ROTATE:
+ GetScreen()->UpdatePickList();
+ DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
+
+ if( block->GetCount() )
+ {
+ // Compute the rotation center and put it on grid:
+ wxPoint rotationPoint = block->Centre();
+ rotationPoint = GetNearestGridPosition( rotationPoint );
+ SetCrossHairPosition( rotationPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_ROTATED, rotationPoint );
+ RotateListOfItems( block->GetItems(), rotationPoint );
+ OnModify();
+ }
+
+ block->ClearItemsList();
+ GetScreen()->TestDanglingEnds( m_canvas, aDC );
+ m_canvas->Refresh();
+ break;
+
+ case BLOCK_DRAG:
+ case BLOCK_DRAG_ITEM: // Drag from a drag command
+ GetScreen()->BreakSegmentsOnJunctions();
+ // fall through
+
+ case BLOCK_MOVE:
+ case BLOCK_COPY:
+ if( block->GetCommand() == BLOCK_DRAG_ITEM &&
+ GetScreen()->GetCurItem() != NULL )
+ {
+ // This is a drag command, not a mouse block command
+ // Only this item is put in list
+ ITEM_PICKER picker;
+ picker.SetItem( GetScreen()->GetCurItem() );
+ block->PushItem( picker );
+ }
+ else
+ {
+ // Collect all items in the locate block
+ GetScreen()->UpdatePickList();
+ }
+ // fall through
+
+ case BLOCK_PRESELECT_MOVE: /* Move with preselection list*/
+ if( block->GetCount() )
+ {
+ nextcmd = true;
+ GetScreen()->SelectBlockItems();
+ m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
+ m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
+ m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
+ block->SetState( STATE_BLOCK_MOVE );
+ }
+ else
+ {
+ m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
+ m_canvas->SetMouseCapture( NULL, NULL );
+ }
+ break;
+
+ case BLOCK_DELETE:
+ GetScreen()->UpdatePickList();
+ DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
+
+ if( block->GetCount() )
+ {
+ DeleteItemsInList( m_canvas, block->GetItems() );
+ OnModify();
+ }
+ block->ClearItemsList();
+ GetScreen()->TestDanglingEnds( m_canvas, aDC );
+ m_canvas->Refresh();
+ break;
+
+ case BLOCK_SAVE: // Save a copy of items in paste buffer
+ GetScreen()->UpdatePickList();
+ DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
+
+ if( block->GetCount() )
+ {
+ wxPoint move_vector = -GetScreen()->m_BlockLocate.GetLastCursorPosition();
+ copyBlockItems( block->GetItems() );
+ MoveItemsInList( m_blockItems.GetItems(), move_vector );
+ }
+
+ block->ClearItemsList();
+ break;
+
+ case BLOCK_PASTE:
+ block->SetState( STATE_BLOCK_MOVE );
+ break;
+
+ case BLOCK_ZOOM:
+ zoom_command = true;
+ break;
+
+ case BLOCK_MIRROR_X:
+ GetScreen()->UpdatePickList();
+ DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
+
+ if( block->GetCount() )
+ {
+ // Compute the mirror center and put it on grid.
+ wxPoint mirrorPoint = block->Centre();
+ mirrorPoint = GetNearestGridPosition( mirrorPoint );
+ SetCrossHairPosition( mirrorPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, mirrorPoint );
+ MirrorX( block->GetItems(), mirrorPoint );
+ OnModify();
+ }
+
+ GetScreen()->TestDanglingEnds( m_canvas, aDC );
+ m_canvas->Refresh();
+ break;
+
+ case BLOCK_MIRROR_Y:
+ GetScreen()->UpdatePickList();
+ DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
+
+ if( block->GetCount() )
+ {
+ // Compute the mirror center and put it on grid.
+ wxPoint mirrorPoint = block->Centre();
+ mirrorPoint = GetNearestGridPosition( mirrorPoint );
+ SetCrossHairPosition( mirrorPoint );
+ SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, mirrorPoint );
+ MirrorY( block->GetItems(), mirrorPoint );
+ OnModify();
+ }
+
+ GetScreen()->TestDanglingEnds( m_canvas, aDC );
+ m_canvas->Refresh();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if( block->GetCommand() == BLOCK_ABORT )
+ {
+ GetScreen()->ClearDrawingState();
+ m_canvas->Refresh();
+ }
+
+ if( ! nextcmd )
+ {
+ block->SetState( STATE_NO_BLOCK );
+ block->SetCommand( BLOCK_IDLE );
+ GetScreen()->SetCurItem( NULL );
+ m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString,
+ false );
+ }
+
+ if( zoom_command )
+ Window_Zoom( GetScreen()->m_BlockLocate );
+
+ return nextcmd;
+}
+
+
+/* Traces the outline of the search block structures
+ * The entire block follows the cursor
+ */
+static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
+ bool aErase )
+{
+ BASE_SCREEN* screen = aPanel->GetScreen();
+ BLOCK_SELECTOR* block = &screen->m_BlockLocate;
+ SCH_ITEM* schitem;
+
+ /* Erase old block contents. */
+ if( aErase )
+ {
+ block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
+
+ for( unsigned ii = 0; ii < block->GetCount(); ii++ )
+ {
+ schitem = (SCH_ITEM*) block->GetItem( ii );
+
+ if( schitem->Type() == SCH_COMPONENT_T )
+ ((SCH_COMPONENT*)schitem)->Draw( aPanel, aDC, block->GetMoveVector(),
+ g_XorMode, g_GhostColor, false );
+ else
+ schitem->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, g_GhostColor );
+ }
+ }
+
+ /* Repaint new view. */
+ block->SetMoveVector( aPanel->GetParent()->GetCrossHairPosition() - block->GetLastCursorPosition() );
+ block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
+
+ for( unsigned ii = 0; ii < block->GetCount(); ii++ )
+ {
+ schitem = (SCH_ITEM*) block->GetItem( ii );
+
+ if( schitem->Type() == SCH_COMPONENT_T )
+ ((SCH_COMPONENT*)schitem)->Draw( aPanel, aDC, block->GetMoveVector(),
+ g_XorMode, g_GhostColor, false );
+ else
+ schitem->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, g_GhostColor );
+ }
+}
+
+
+void SCH_EDIT_FRAME::copyBlockItems( PICKED_ITEMS_LIST& aItemsList )
+{
+ m_blockItems.ClearListAndDeleteItems(); // delete previous saved list, if exists
+
+ for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
+ {
+ // Clear m_Flag member of selected items:
+ aItemsList.GetPickedItem( ii )->ClearFlags();
+
+ /* Make a copy of the original picked item. */
+ SCH_ITEM* copy = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) );
+ copy->SetParent( NULL );
+
+ // In list the wrapper is owner of the schematic item, we can use the UR_DELETED
+ // status for the picker because pickers with this status are owner of the picked item
+ // (or TODO ?: create a new status like UR_DUPLICATE)
+ ITEM_PICKER item( copy, UR_DELETED );
+
+ m_blockItems.PushItem( item );
+ }
+}
+
+
+void SCH_EDIT_FRAME::PasteListOfItems( wxDC* DC )
+{
+ unsigned i;
+ SCH_ITEM* item;
+ SCH_SHEET_LIST hierarchy; // This is the entire schematic hierarcy.
+
+ if( m_blockItems.GetCount() == 0 )
+ {
+ DisplayError( this, _( "No item to paste." ) );
+ return;
+ }
+
+ wxFileName destFn = m_CurrentSheet->Last()->GetFileName();
+
+ if( destFn.IsRelative() )
+ destFn.MakeAbsolute( Prj().GetProjectPath() );
+
+ // Make sure any sheets in the block to be pasted will not cause recursion in
+ // the destination sheet.
+ for( i = 0; i < m_blockItems.GetCount(); i++ )
+ {
+ item = (SCH_ITEM*) m_blockItems.GetItem( i );
+
+ if( item->Type() == SCH_SHEET_T )
+ {
+ SCH_SHEET* sheet = (SCH_SHEET*)item;
+ wxFileName srcFn = sheet->GetFileName();
+
+ if( srcFn.IsRelative() )
+ srcFn.MakeAbsolute( Prj().GetProjectPath() );
+
+ SCH_SHEET_LIST sheetHierarchy( sheet );
+
+ if( hierarchy.TestForRecursion( sheetHierarchy,
+ destFn.GetFullPath( wxPATH_UNIX ) ) )
+ {
+ wxString msg;
+
+ msg.Printf( _( "The sheet changes cannot be made because the destination "
+ "sheet already has the sheet <%s> or one of it's subsheets "
+ "as a parent somewhere in the schematic hierarchy." ),
+ GetChars( sheet->GetFileName() ) );
+ DisplayError( this, msg );
+ return;
+ }
+
+ // Duplicate sheet names and sheet time stamps are not valid. Use a time stamp
+ // based sheet name and update the time stamp for each sheet in the block.
+ unsigned long timeStamp = (unsigned long)GetNewTimeStamp();
+
+ sheet->SetName( wxString::Format( wxT( "sheet%8.8lX" ), timeStamp ) );
+ sheet->SetTimeStamp( (time_t)timeStamp );
+ }
+ }
+
+ PICKED_ITEMS_LIST picklist;
+
+ for( i = 0; i < m_blockItems.GetCount(); i++ )
+ {
+ item = DuplicateStruct( (SCH_ITEM*) m_blockItems.GetItem( i ) );
+
+ // Creates data, and push it as new data in undo item list buffer
+ ITEM_PICKER picker( item, UR_NEW );
+ picklist.PushItem( picker );
+
+ // Clear annotation and init new time stamp for the new components and sheets:
+ if( item->Type() == SCH_COMPONENT_T )
+ {
+ ( (SCH_COMPONENT*) item )->SetTimeStamp( GetNewTimeStamp() );
+ ( (SCH_COMPONENT*) item )->ClearAnnotation( NULL );
+ }
+ else if( item->Type() == SCH_SHEET_T )
+ {
+ ( (SCH_SHEET*) item )->SetTimeStamp( GetNewTimeStamp() );
+ }
+
+ SetSchItemParent( item, GetScreen() );
+ item->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
+ GetScreen()->Append( item );
+ }
+
+ SaveCopyInUndoList( picklist, UR_NEW );
+
+ MoveItemsInList( picklist, GetScreen()->m_BlockLocate.GetMoveVector() );
+
+ // Clear flags for all items.
+ GetScreen()->ClearDrawingState();
+
+ OnModify();
+
+ return;
+}
diff --git a/eeschema/block_libedit.cpp b/eeschema/block_libedit.cpp
new file mode 100644
index 00000000..5dc235f7
--- /dev/null
+++ b/eeschema/block_libedit.cpp
@@ -0,0 +1,355 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 2008-2011 Wayne Stambaugh
+ * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file block_libedit.cpp
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+
+static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
+ bool aErase );
+
+
+int LIB_EDIT_FRAME::BlockCommand( int key )
+{
+ int cmd = BLOCK_IDLE;
+
+ switch( key )
+ {
+ default:
+ cmd = key & 0xFF;
+ break;
+
+ case -1:
+ cmd = BLOCK_PRESELECT_MOVE;
+ break;
+
+ case 0:
+ cmd = BLOCK_MOVE;
+ break;
+
+ case GR_KB_SHIFT:
+ cmd = BLOCK_COPY;
+ break;
+
+ case GR_KB_ALT:
+ cmd = BLOCK_ROTATE;
+ break;
+
+ case GR_KB_SHIFTCTRL:
+ cmd = BLOCK_DELETE;
+ break;
+
+ case GR_KB_CTRL:
+ cmd = BLOCK_MIRROR_Y;
+ break;
+
+ case MOUSE_MIDDLE:
+ cmd = BLOCK_ZOOM;
+ break;
+ }
+
+ return cmd;
+}
+
+
+bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* DC )
+{
+ int ItemCount = 0;
+ bool nextCmd = false;
+ wxPoint pt;
+
+ if( GetScreen()->m_BlockLocate.GetCount() )
+ {
+ BLOCK_STATE_T state = GetScreen()->m_BlockLocate.GetState();
+ BLOCK_COMMAND_T command = GetScreen()->m_BlockLocate.GetCommand();
+ m_canvas->CallEndMouseCapture( DC );
+ GetScreen()->m_BlockLocate.SetState( state );
+ GetScreen()->m_BlockLocate.SetCommand( command );
+ m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand );
+ SetCrossHairPosition( wxPoint( GetScreen()->m_BlockLocate.GetRight(),
+ GetScreen()->m_BlockLocate.GetBottom() ) );
+ m_canvas->MoveCursorToCrossHair();
+ }
+
+ switch( GetScreen()->m_BlockLocate.GetCommand() )
+ {
+ case BLOCK_IDLE:
+ DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
+ break;
+
+ case BLOCK_DRAG: // Drag
+ case BLOCK_DRAG_ITEM:
+ case BLOCK_MOVE: // Move
+ case BLOCK_COPY: // Copy
+ if( GetCurPart() )
+ ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
+ m_unit, m_convert,
+ m_editPinsPerPartOrConvert );
+ if( ItemCount )
+ {
+ nextCmd = true;
+
+ if( m_canvas->IsMouseCaptured() )
+ {
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+ m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+ }
+
+ GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE );
+ m_canvas->Refresh( true );
+ }
+ break;
+
+ case BLOCK_PRESELECT_MOVE: // Move with preselection list
+ nextCmd = true;
+ m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
+ GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_MOVE );
+ break;
+
+ case BLOCK_DELETE: // Delete
+ if( GetCurPart() )
+ ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
+ m_unit, m_convert,
+ m_editPinsPerPartOrConvert );
+ if( ItemCount )
+ SaveCopyInUndoList( GetCurPart() );
+
+ if( GetCurPart() )
+ {
+ GetCurPart()->DeleteSelectedItems();
+ OnModify();
+ }
+ break;
+
+ case BLOCK_SAVE: // Save
+ case BLOCK_PASTE:
+ case BLOCK_FLIP:
+ break;
+
+ case BLOCK_ROTATE:
+ case BLOCK_MIRROR_X:
+ case BLOCK_MIRROR_Y:
+ if( GetCurPart() )
+ ItemCount = GetCurPart()->SelectItems( GetScreen()->m_BlockLocate,
+ m_unit, m_convert,
+ m_editPinsPerPartOrConvert );
+ if( ItemCount )
+ SaveCopyInUndoList( GetCurPart() );
+
+ pt = GetScreen()->m_BlockLocate.Centre();
+ pt = GetNearestGridPosition( pt );
+ pt.y = -pt.y;
+
+ if( GetCurPart() )
+ {
+ OnModify();
+ int block_cmd = GetScreen()->m_BlockLocate.GetCommand();
+
+ if( block_cmd == BLOCK_MIRROR_Y)
+ GetCurPart()->MirrorSelectedItemsH( pt );
+ else if( block_cmd == BLOCK_MIRROR_X)
+ GetCurPart()->MirrorSelectedItemsV( pt );
+ else if( block_cmd == BLOCK_ROTATE )
+ GetCurPart()->RotateSelectedItems( pt );
+ }
+
+ break;
+
+ case BLOCK_ZOOM: // Window Zoom
+ Window_Zoom( GetScreen()->m_BlockLocate );
+ break;
+
+ case BLOCK_ABORT:
+ break;
+
+ case BLOCK_SELECT_ITEMS_ONLY:
+ break;
+
+ case BLOCK_COPY_AND_INCREMENT: // not used in Eeschema
+ case BLOCK_MOVE_EXACT: // not used in Eeschema
+ break;
+ }
+
+ if( !nextCmd )
+ {
+ if( GetScreen()->m_BlockLocate.GetCommand() != BLOCK_SELECT_ITEMS_ONLY && GetCurPart() )
+ GetCurPart()->ClearSelectedItems();
+
+ GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK );
+ GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
+ GetScreen()->SetCurItem( NULL );
+ m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString,
+ false );
+ m_canvas->Refresh( true );
+ }
+
+ return nextCmd;
+}
+
+
+void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
+{
+ wxPoint pt;
+
+ if( !m_canvas->IsMouseCaptured() )
+ {
+ DisplayError( this, wxT( "HandleBlockPLace : m_mouseCaptureCallback = NULL" ) );
+ }
+
+ GetScreen()->m_BlockLocate.SetState( STATE_BLOCK_STOP );
+
+ switch( GetScreen()->m_BlockLocate.GetCommand() )
+ {
+ case BLOCK_IDLE:
+ break;
+
+ case BLOCK_DRAG: // Drag
+ case BLOCK_DRAG_ITEM:
+ case BLOCK_MOVE: // Move
+ case BLOCK_PRESELECT_MOVE: // Move with preselection list
+ GetScreen()->m_BlockLocate.ClearItemsList();
+
+ if( GetCurPart() )
+ SaveCopyInUndoList( GetCurPart() );
+
+ pt = GetScreen()->m_BlockLocate.GetMoveVector();
+ pt.y *= -1;
+
+ if( GetCurPart() )
+ GetCurPart()->MoveSelectedItems( pt );
+
+ m_canvas->Refresh( true );
+ break;
+
+ case BLOCK_COPY: // Copy
+ GetScreen()->m_BlockLocate.ClearItemsList();
+
+ if( GetCurPart() )
+ SaveCopyInUndoList( GetCurPart() );
+
+ pt = GetScreen()->m_BlockLocate.GetMoveVector();
+ pt.y = -pt.y;
+
+ if( GetCurPart() )
+ GetCurPart()->CopySelectedItems( pt );
+
+ break;
+
+ case BLOCK_PASTE: // Paste (recopy the last block saved)
+ GetScreen()->m_BlockLocate.ClearItemsList();
+ break;
+
+ case BLOCK_ROTATE: // Invert by popup menu, from block move
+ case BLOCK_MIRROR_X: // Invert by popup menu, from block move
+ case BLOCK_MIRROR_Y: // Invert by popup menu, from block move
+ if( GetCurPart() )
+ SaveCopyInUndoList( GetCurPart() );
+
+ pt = GetScreen()->m_BlockLocate.Centre();
+ pt = GetNearestGridPosition( pt );
+ pt.y = -pt.y;
+
+ if( GetCurPart() )
+ {
+ int block_cmd = GetScreen()->m_BlockLocate.GetCommand();
+
+ if( block_cmd == BLOCK_MIRROR_Y)
+ GetCurPart()->MirrorSelectedItemsH( pt );
+ else if( block_cmd == BLOCK_MIRROR_X)
+ GetCurPart()->MirrorSelectedItemsV( pt );
+ else if( block_cmd == BLOCK_ROTATE )
+ GetCurPart()->RotateSelectedItems( pt );
+ }
+
+ break;
+
+ case BLOCK_ZOOM: // Handled by HandleBlockEnd
+ case BLOCK_DELETE:
+ case BLOCK_SAVE:
+ case BLOCK_ABORT:
+ default:
+ break;
+ }
+
+ OnModify();
+
+ GetScreen()->m_BlockLocate.SetState( STATE_NO_BLOCK );
+ GetScreen()->m_BlockLocate.SetCommand( BLOCK_IDLE );
+ GetScreen()->SetCurItem( NULL );
+ m_canvas->EndMouseCapture( GetToolId(), m_canvas->GetCurrentCursor(), wxEmptyString, false );
+ m_canvas->Refresh( true );
+}
+
+
+/*
+ * Traces the outline of the search block structures
+ * The entire block follows the cursor
+ */
+void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
+ bool aErase )
+{
+ BLOCK_SELECTOR* block;
+ BASE_SCREEN* screen = aPanel->GetScreen();
+ block = &screen->m_BlockLocate;
+
+ LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent();
+ wxASSERT( parent != NULL );
+
+ LIB_PART* component = parent->GetCurPart();
+
+ if( component == NULL )
+ return;
+
+ int unit = parent->GetUnit();
+ int convert = parent->GetConvert();
+
+ if( aErase )
+ {
+ block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
+
+ component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert,
+ g_XorMode, UNSPECIFIED_COLOR, DefaultTransform, true, true, true );
+ }
+
+ // Repaint new view
+ block->SetMoveVector( parent->GetCrossHairPosition() - block->GetLastCursorPosition() );
+
+ GRSetDrawMode( aDC, g_XorMode );
+ block->Draw( aPanel, aDC, block->GetMoveVector(), g_XorMode, block->GetColor() );
+
+ component->Draw( aPanel, aDC, block->GetMoveVector(), unit, convert,
+ g_XorMode, UNSPECIFIED_COLOR, DefaultTransform, true, true, true );
+}
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
new file mode 100644
index 00000000..18e3bd13
--- /dev/null
+++ b/eeschema/bus-wire-junction.cpp
@@ -0,0 +1,505 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
+ * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file bus-wire-junction.cpp
+ * @brief Code for editing buses, wires, and junctions.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+static void AbortCreateNewLine( EDA_DRAW_PANEL* aPanel, wxDC* aDC );
+static void ComputeBreakPoint( SCH_LINE* segment, const wxPoint& new_pos );
+
+static DLIST< SCH_ITEM > s_wires; // when creating a new set of wires,
+ // stores here the new wires.
+
+
+/**
+ * In a contiguous list of wires, remove wires that backtrack over the previous
+ * wire. Example:
+ *
+ * Wire is added:
+ * ---------------------------------------->
+ *
+ * A second wire backtracks over it:
+ * -------------------<====================>
+ *
+ * RemoveBacktracks is called:
+ * ------------------->
+ */
+static void RemoveBacktracks( DLIST& aWires )
+{
+ SCH_LINE* last_line = NULL;
+
+ EDA_ITEM* first = aWires.GetFirst();
+ for( EDA_ITEM* p = first; p; )
+ {
+ SCH_LINE *line = dynamic_cast( p );
+ if( !line )
+ {
+ wxFAIL_MSG( "RemoveBacktracks() requires SCH_LINE items" );
+ break;
+ }
+ p = line->Next();
+
+ if( last_line )
+ {
+ wxASSERT_MSG( last_line->GetEndPoint() == line->GetStartPoint(),
+ "RemoveBacktracks() requires contiguous lines" );
+ if( IsPointOnSegment( last_line->GetStartPoint(), line->GetStartPoint(),
+ line->GetEndPoint() ) )
+ {
+ last_line->SetEndPoint( line->GetEndPoint() );
+ delete s_wires.Remove( line );
+ }
+ else
+ last_line = line;
+ }
+ else
+ last_line = line;
+ }
+}
+
+
+/**
+ * Mouse capture callback for drawing line segments.
+ */
+static void DrawSegment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
+ bool aErase )
+{
+ SCH_LINE* segment;
+
+ if( s_wires.GetCount() == 0 )
+ return;
+
+ segment = (SCH_LINE*) s_wires.begin();
+ EDA_COLOR_T color = GetLayerColor( segment->GetLayer() );
+ ColorChangeHighlightFlag( &color, !(color & HIGHLIGHT_FLAG) );
+
+ if( aErase )
+ {
+ while( segment )
+ {
+ if( !segment->IsNull() ) // Redraw if segment length != 0
+ segment->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, color );
+
+ segment = segment->Next();
+ }
+ }
+
+ SCH_EDIT_FRAME* frame = (SCH_EDIT_FRAME*) aPanel->GetParent();
+
+ wxPoint endpos = frame->GetCrossHairPosition();
+
+ if( frame->GetForceHVLines() ) /* Coerce the line to vertical or horizontal one: */
+ ComputeBreakPoint( (SCH_LINE*) s_wires.GetLast()->Back(), endpos );
+ else
+ ( (SCH_LINE*) s_wires.GetLast() )->SetEndPoint( endpos );
+
+ segment = (SCH_LINE*) s_wires.begin();
+
+ while( segment )
+ {
+ if( !segment->IsNull() ) // Redraw if segment length != 0
+ segment->Draw( aPanel, aDC, wxPoint( 0, 0 ), g_XorMode, color );
+
+ segment = segment->Next();
+ }
+}
+
+
+void SCH_EDIT_FRAME::BeginSegment( wxDC* DC, int type )
+{
+ SCH_LINE* segment;
+ SCH_LINE* nextSegment;
+ wxPoint cursorpos = GetCrossHairPosition();
+
+ // We should know if a segment is currently in progress
+ segment = (SCH_LINE*) GetScreen()->GetCurItem();
+ if( segment ) // a current item exists, but not necessary a currently edited item
+ {
+ if( !segment->GetFlags() || ( segment->Type() != SCH_LINE_T ) )
+ {
+ if( segment->GetFlags() )
+ {
+ wxLogDebug( wxT( "BeginSegment: item->GetFlags()== %X" ),
+ segment->GetFlags() );
+ }
+ // no wire, bus or graphic line in progress
+ segment = NULL;
+ }
+ }
+
+ if( !segment ) // first point : Create the first wire or bus segment
+ {
+ switch( type )
+ {
+ default:
+ segment = new SCH_LINE( cursorpos, LAYER_NOTES );
+ break;
+
+ case LAYER_WIRE:
+ segment = new SCH_LINE( cursorpos, LAYER_WIRE );
+
+ /* A junction will be created later, when we'll know the
+ * segment end position, and if the junction is really needed */
+ break;
+
+ case LAYER_BUS:
+ segment = new SCH_LINE( cursorpos, LAYER_BUS );
+ break;
+ }
+
+ segment->SetFlags( IS_NEW );
+ s_wires.PushBack( segment );
+ GetScreen()->SetCurItem( segment );
+
+ // We need 2 segments to go from a given start pin to an end point when the horizontal
+ // and vertical lines only switch is on.
+ if( GetForceHVLines() )
+ {
+ nextSegment = new SCH_LINE( *segment );
+ nextSegment->SetFlags( IS_NEW );
+ s_wires.PushBack( nextSegment );
+ GetScreen()->SetCurItem( nextSegment );
+ }
+
+ m_canvas->SetMouseCapture( DrawSegment, AbortCreateNewLine );
+ SetRepeatItem( NULL );
+ }
+ else // A segment is in progress: terminates the current segment and add a new segment.
+ {
+ SCH_LINE* prevSegment = segment->Back();
+
+ // Be aware prevSegment can be null when the horizontal and vertical lines only switch is off
+ // when we create the first segment.
+
+ if( !GetForceHVLines() )
+ {
+ // If only one segment is needed and it has a zero length, do not create a new one.
+ if( segment->IsNull() )
+ return;
+ }
+ else
+ {
+ wxCHECK_RET( prevSegment != NULL, wxT( "Failed to create second line segment." ) );
+
+ // If two segments are required and they both have zero length, do not
+ // create a new one.
+ if( prevSegment && prevSegment->IsNull() && segment->IsNull() )
+ return;
+ }
+
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+
+ // Terminate the command if the end point is on a pin, junction, or another wire or bus.
+ if( GetScreen()->IsTerminalPoint( cursorpos, segment->GetLayer() ) )
+ {
+ EndSegment( DC );
+ return;
+ }
+
+ // Create a new segment, and chain it after the current new segment.
+ nextSegment = new SCH_LINE( *segment );
+ nextSegment->SetStartPoint( cursorpos );
+ s_wires.PushBack( nextSegment );
+
+ segment->SetEndPoint( cursorpos );
+ segment->ClearFlags( IS_NEW );
+ segment->SetFlags( SELECTED );
+ nextSegment->SetFlags( IS_NEW );
+ GetScreen()->SetCurItem( nextSegment );
+ m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
+ }
+}
+
+
+void SCH_EDIT_FRAME::EndSegment( wxDC* DC )
+{
+ SCH_SCREEN* screen = GetScreen();
+ SCH_LINE* segment = (SCH_LINE*) screen->GetCurItem();
+
+ if( segment == NULL || segment->Type() != SCH_LINE_T || !segment->IsNew() )
+ return;
+
+ // Delete zero length segments and clear item flags.
+ SCH_ITEM* item = s_wires.begin();
+
+ while( item )
+ {
+ item->ClearFlags();
+
+ wxCHECK_RET( item->Type() == SCH_LINE_T, wxT( "Unexpected object type in wire list." ) );
+
+ segment = (SCH_LINE*) item;
+ item = item->Next();
+
+ if( segment->IsNull() )
+ delete s_wires.Remove( segment );
+ }
+
+ if( s_wires.GetCount() == 0 )
+ return;
+
+ // Get the last non-null wire (this is the last created segment).
+ SetRepeatItem( segment = (SCH_LINE*) s_wires.GetLast() );
+
+ screen->SetCurItem( NULL );
+ m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false );
+
+ // store the terminal point of this last segment: a junction could be needed
+ // (the last wire could be merged/deleted/modified, and lost)
+ wxPoint endpoint = segment->GetEndPoint();
+
+ // store the starting point of this first segment: a junction could be needed
+ SCH_LINE* firstsegment = (SCH_LINE*) s_wires.GetFirst();
+ wxPoint startPoint = firstsegment->GetStartPoint();
+
+ // Save the old wires for the undo command
+ DLIST< SCH_ITEM > oldWires; // stores here the old wires
+ GetScreen()->ExtractWires( oldWires, true ); // Save them in oldWires list
+ // Put the snap shot of the previous wire, buses, and junctions in the undo/redo list.
+ PICKED_ITEMS_LIST oldItems;
+ oldItems.m_Status = UR_WIRE_IMAGE;
+
+ while( oldWires.GetCount() != 0 )
+ {
+ ITEM_PICKER picker = ITEM_PICKER( oldWires.PopFront(), UR_WIRE_IMAGE );
+ oldItems.PushItem( picker );
+ }
+
+ SaveCopyInUndoList( oldItems, UR_WIRE_IMAGE );
+
+ // Remove segments backtracking over others
+ RemoveBacktracks( s_wires );
+
+ // Add the new wires
+ screen->Append( s_wires );
+
+ // Correct and remove segments that need to be merged.
+ screen->SchematicCleanUp( NULL, DC );
+
+ // A junction could be needed to connect the end point of the last created segment.
+ if( screen->IsJunctionNeeded( endpoint ) )
+ screen->Append( AddJunction( DC, endpoint ) );
+
+ // A junction could be needed to connect the start point of the set of new created wires
+ if( screen->IsJunctionNeeded( startPoint ) )
+ screen->Append( AddJunction( DC, startPoint ) );
+
+ m_canvas->Refresh();
+
+ OnModify();
+}
+
+
+/**
+ * Function ComputeBreakPoint
+ * computes the middle coordinate for 2 segments from the start point to \a aPosition
+ * with the segments kept in the horizontal or vertical axis only.
+ *
+ * @param aSegment A pointer to a #SCH_LINE object containing the first line break point
+ * to compute.
+ * @param aPosition A reference to a wxPoint object containing the coordinates of the
+ * position used to calculate the line break point.
+ */
+static void ComputeBreakPoint( SCH_LINE* aSegment, const wxPoint& aPosition )
+{
+ wxCHECK_RET( aSegment != NULL, wxT( "Cannot compute break point of NULL line segment." ) );
+
+ SCH_LINE* nextSegment = aSegment->Next();
+ wxPoint midPoint = aPosition;
+
+ wxCHECK_RET( nextSegment != NULL,
+ wxT( "Cannot compute break point of NULL second line segment." ) );
+
+#if 0
+ if( ABS( midPoint.x - aSegment->GetStartPoint().x ) <
+ ABS( midPoint.y - aSegment->GetStartPoint().y ) )
+ midPoint.x = aSegment->GetStartPoint().x;
+ else
+ midPoint.y = aSegment->GetStartPoint().y;
+#else
+ int iDx = aSegment->GetEndPoint().x - aSegment->GetStartPoint().x;
+ int iDy = aSegment->GetEndPoint().y - aSegment->GetStartPoint().y;
+
+ if( iDy != 0 ) // keep the first segment orientation (currently horizontal)
+ {
+ midPoint.x = aSegment->GetStartPoint().x;
+ }
+ else if( iDx != 0 ) // keep the first segment orientation (currently vertical)
+ {
+ midPoint.y = aSegment->GetStartPoint().y;
+ }
+ else
+ {
+ if( std::abs( midPoint.x - aSegment->GetStartPoint().x ) <
+ std::abs( midPoint.y - aSegment->GetStartPoint().y ) )
+ midPoint.x = aSegment->GetStartPoint().x;
+ else
+ midPoint.y = aSegment->GetStartPoint().y;
+ }
+#endif
+
+ aSegment->SetEndPoint( midPoint );
+ nextSegment->SetStartPoint( midPoint );
+ nextSegment->SetEndPoint( aPosition );
+}
+
+
+void SCH_EDIT_FRAME::DeleteCurrentSegment( wxDC* DC )
+{
+ SCH_SCREEN* screen = GetScreen();
+
+ SetRepeatItem( NULL );
+
+ if( ( screen->GetCurItem() == NULL ) || !screen->GetCurItem()->IsNew() )
+ return;
+
+ DrawSegment( m_canvas, DC, wxDefaultPosition, false );
+
+ screen->Remove( screen->GetCurItem() );
+ m_canvas->SetMouseCaptureCallback( NULL );
+ screen->SetCurItem( NULL );
+}
+
+
+SCH_JUNCTION* SCH_EDIT_FRAME::AddJunction( wxDC* aDC, const wxPoint& aPosition,
+ bool aPutInUndoList )
+{
+ SCH_JUNCTION* junction = new SCH_JUNCTION( aPosition );
+
+ SetRepeatItem( junction );
+
+ m_canvas->CrossHairOff( aDC ); // Erase schematic cursor
+ junction->Draw( m_canvas, aDC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
+ m_canvas->CrossHairOn( aDC ); // Display schematic cursor
+
+ if( aPutInUndoList )
+ {
+ GetScreen()->Append( junction );
+ SaveCopyInUndoList( junction, UR_NEW );
+ OnModify();
+ }
+
+ return junction;
+}
+
+
+SCH_NO_CONNECT* SCH_EDIT_FRAME::AddNoConnect( wxDC* aDC, const wxPoint& aPosition )
+{
+ SCH_NO_CONNECT* no_connect = new SCH_NO_CONNECT( aPosition );
+
+ SetRepeatItem( no_connect );
+ GetScreen()->Append( no_connect );
+ GetScreen()->SchematicCleanUp( m_canvas, aDC );
+ OnModify();
+ m_canvas->Refresh();
+ SaveCopyInUndoList( no_connect, UR_NEW );
+ return no_connect;
+}
+
+
+/* Abort function for wire, bus or line creation
+ */
+static void AbortCreateNewLine( EDA_DRAW_PANEL* aPanel, wxDC* aDC )
+{
+ SCH_SCREEN* screen = (SCH_SCREEN*) aPanel->GetScreen();
+
+ if( screen->GetCurItem() )
+ {
+ s_wires.DeleteAll(); // Free the list, for a future usage
+ screen->SetCurItem( NULL );
+ aPanel->Refresh();
+ }
+ else
+ {
+ SCH_EDIT_FRAME* parent = ( SCH_EDIT_FRAME* ) aPanel->GetParent();
+ parent->SetRepeatItem( NULL );
+ }
+
+ // Clear flags used in edit functions.
+ screen->ClearDrawingState();
+}
+
+
+void SCH_EDIT_FRAME::RepeatDrawItem( wxDC* DC )
+{
+ SCH_ITEM* repeater = GetRepeatItem();
+
+ if( !repeater )
+ return;
+
+ //D( repeater>Show( 0, std::cout ); )
+
+ // clone the repeater, move it, insert into display list, then save a copy
+ // via SetRepeatItem();
+
+ SCH_ITEM* my_clone = (SCH_ITEM*) repeater->Clone();
+
+ // If cloning a component then put into 'move' mode.
+ if( my_clone->Type() == SCH_COMPONENT_T )
+ {
+ wxPoint pos = GetCrossHairPosition() -
+ ( (SCH_COMPONENT*) my_clone )->GetPosition();
+
+ my_clone->SetFlags( IS_NEW );
+ ( (SCH_COMPONENT*) my_clone )->SetTimeStamp( GetNewTimeStamp() );
+ my_clone->Move( pos );
+ my_clone->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
+ PrepareMoveItem( my_clone, DC );
+ }
+ else
+ {
+ my_clone->Move( GetRepeatStep() );
+
+ if( my_clone->CanIncrementLabel() )
+ ( (SCH_TEXT*) my_clone )->IncrementLabel( GetRepeatDeltaLabel() );
+
+ GetScreen()->Append( my_clone );
+ GetScreen()->TestDanglingEnds();
+ my_clone->Draw( m_canvas, DC, wxPoint( 0, 0 ), GR_DEFAULT_DRAWMODE );
+ SaveCopyInUndoList( my_clone, UR_NEW );
+ my_clone->ClearFlags();
+ }
+
+ // clone my_clone, now that it has been moved, thus saving new position.
+ SetRepeatItem( my_clone );
+}
diff --git a/eeschema/busentry.cpp b/eeschema/busentry.cpp
new file mode 100644
index 00000000..06c3ba39
--- /dev/null
+++ b/eeschema/busentry.cpp
@@ -0,0 +1,83 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 2008-2011 Wayne Stambaugh
+ * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file busentry.cpp
+ * @brief Code to handle manipulation of bus entry objects.
+ */
+
+#include
+#include
+#include
+#include
+
+#include
+
+
+static int s_LastShape = '\\';
+
+
+SCH_BUS_BUS_ENTRY* SCH_EDIT_FRAME::CreateBusBusEntry()
+{
+ // Create and place a new bus entry at cursor position
+ SCH_BUS_BUS_ENTRY* busEntry = new SCH_BUS_BUS_ENTRY( GetCrossHairPosition(), s_LastShape );
+
+ busEntry->SetFlags( IS_NEW );
+ GetScreen()->SetCurItem( busEntry );
+ addCurrentItemToList();
+ return busEntry;
+}
+
+SCH_BUS_WIRE_ENTRY* SCH_EDIT_FRAME::CreateBusWireEntry()
+{
+ // Create and place a new bus entry at cursor position
+ SCH_BUS_WIRE_ENTRY* busEntry = new SCH_BUS_WIRE_ENTRY( GetCrossHairPosition(), s_LastShape );
+
+ busEntry->SetFlags( IS_NEW );
+ GetScreen()->SetCurItem( busEntry );
+ addCurrentItemToList();
+ return busEntry;
+}
+
+/* set the shape of BusEntry (shape = / or \ )
+ */
+void SCH_EDIT_FRAME::SetBusEntryShape( wxDC* DC, SCH_BUS_ENTRY_BASE* BusEntry, char entry_shape )
+{
+ if( BusEntry == NULL )
+ return;
+
+ /* Put old item in undo list if it is not currently in edit */
+ if( BusEntry->GetFlags() == 0 )
+ SaveCopyInUndoList( BusEntry, UR_CHANGED );
+
+ s_LastShape = entry_shape == '/' ? '/' : '\\';
+
+ BusEntry->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
+ BusEntry->SetBusEntryShape( s_LastShape );
+ GetScreen()->TestDanglingEnds();
+ BusEntry->Draw( m_canvas, DC, wxPoint( 0, 0 ), g_XorMode );
+
+ OnModify( );
+}
diff --git a/eeschema/class_drc_erc_item.cpp b/eeschema/class_drc_erc_item.cpp
new file mode 100644
index 00000000..9071dc89
--- /dev/null
+++ b/eeschema/class_drc_erc_item.cpp
@@ -0,0 +1,68 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+/******************************************************************/
+/* class_drc_erc_item.cpp - DRC_ITEM class functions for eeschema */
+/******************************************************************/
+#include
+#include
+
+#include
+#include
+#include
+
+wxString DRC_ITEM::GetErrorText() const
+{
+ switch( m_ErrorCode )
+ {
+ case ERCE_UNSPECIFIED:
+ return wxString( _("ERC err unspecified") );
+ case ERCE_DUPLICATE_SHEET_NAME:
+ return wxString( _("Duplicate sheet names within a given sheet") );
+ case ERCE_PIN_NOT_CONNECTED:
+ return wxString( _("Pin not connected (and no connect symbol found on this pin)") );
+ case ERCE_PIN_NOT_DRIVEN:
+ return wxString( _("Pin connected to some others pins but no pin to drive it") );
+ case ERCE_PIN_TO_PIN_WARNING:
+ return wxString( _("Conflict problem between pins. Severity: warning") );
+ case ERCE_PIN_TO_PIN_ERROR:
+ return wxString( _("Conflict problem between pins. Severity: error") );
+ case ERCE_HIERACHICAL_LABEL:
+ return wxString( _("Mismatch between hierarchical labels and pins sheets"));
+ case ERCE_NOCONNECT_CONNECTED:
+ return wxString( _("A no connect symbol is connected to more than 1 pin"));
+ case ERCE_GLOBLABEL:
+ return wxString( _("Global label not connected to any other global label") );
+
+ default:
+ return wxString( wxT("Unkown.") );
+ }
+}
+
+wxString DRC_ITEM::ShowCoord( const wxPoint& aPos )
+{
+ wxString ret;
+ ret << aPos;
+ return ret;
+}
diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp
new file mode 100644
index 00000000..cb99d686
--- /dev/null
+++ b/eeschema/class_libentry.cpp
@@ -0,0 +1,1898 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_libentry.cpp
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+// the separator char between the subpart id and the reference
+// 0 (no separator) or '.' or some other character
+int LIB_PART::m_subpartIdSeparator = 0;
+
+// the ascii char value to calculate the subpart symbol id from the part number:
+// 'A' or '1' usually. (to print U1.A or U1.1)
+// if this a a digit, a number is used as id symbol
+int LIB_PART::m_subpartFirstId = 'A';
+
+
+const wxChar traceSchLibMem[] = wxT( "KISCHLIBMEM" ); // public
+
+
+LIB_ALIAS::LIB_ALIAS( const wxString& aName, LIB_PART* aRootPart ):
+ EDA_ITEM( LIB_ALIAS_T ),
+ shared( aRootPart )
+{
+ name = aName;
+}
+
+
+LIB_ALIAS::LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_PART* aRootPart ) :
+ EDA_ITEM( aAlias ),
+ shared( aRootPart )
+{
+ name = aAlias.name;
+
+ description = aAlias.description;
+ keyWords = aAlias.keyWords;
+ docFileName = aAlias.docFileName;
+}
+
+
+LIB_ALIAS::~LIB_ALIAS()
+{
+ wxASSERT_MSG( shared, wxT( "~LIB_ALIAS() without a LIB_PART" ) );
+
+ wxLogTrace( traceSchLibMem,
+ wxT( "%s: destroying alias:'%s' of part:'%s'." ),
+ GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( name ),
+ GetChars( shared->GetName() ) );
+
+ if( shared )
+ shared->RemoveAlias( this );
+}
+
+
+const wxString LIB_ALIAS::GetLibraryName()
+{
+ wxASSERT_MSG( shared, wxT( "LIB_ALIAS without a LIB_PART" ) );
+
+ if( shared )
+ return shared->GetLibraryName();
+
+ return wxString( _( "none" ) );
+}
+
+
+bool LIB_ALIAS::IsRoot() const
+{
+ return Cmp_KEEPCASE( name, shared->GetName() ) == 0;
+}
+
+
+PART_LIB* LIB_ALIAS::GetLib()
+{
+ return shared->GetLib();
+}
+
+
+bool LIB_ALIAS::SaveDoc( OUTPUTFORMATTER& aFormatter )
+{
+ if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
+ return true;
+
+ try
+ {
+ aFormatter.Print( 0, "#\n$CMP %s\n", TO_UTF8( name ) );
+
+ if( !description.IsEmpty() )
+ aFormatter.Print( 0, "D %s\n", TO_UTF8( description ) );
+
+ if( !keyWords.IsEmpty() )
+ aFormatter.Print( 0, "K %s\n", TO_UTF8( keyWords ) );
+
+ if( !docFileName.IsEmpty() )
+ aFormatter.Print( 0, "F %s\n", TO_UTF8( docFileName ) );
+
+ aFormatter.Print( 0, "$ENDCMP\n" );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+
+bool LIB_ALIAS::operator==( const wxChar* aName ) const
+{
+ return Cmp_KEEPCASE( name, aName ) == 0;
+}
+
+
+bool operator<( const LIB_ALIAS& aItem1, const LIB_ALIAS& aItem2 )
+{
+ return Cmp_KEEPCASE( aItem1.GetName(), aItem2.GetName() ) < 0;
+}
+
+
+int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2 )
+{
+ return Cmp_KEEPCASE( aItem1->GetName(), aItem2->GetName() );
+}
+
+
+/// http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
+struct null_deleter
+{
+ void operator()(void const *) const
+ {
+ }
+};
+
+
+LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
+ EDA_ITEM( LIB_PART_T ),
+ m_me( this, null_deleter() )
+{
+ m_name = aName;
+ m_library = aLibrary;
+ m_dateModified = 0;
+ m_unitCount = 1;
+ m_pinNameOffset = 40;
+ m_options = ENTRY_NORMAL;
+ m_unitsLocked = false;
+ m_showPinNumbers = true;
+ m_showPinNames = true;
+
+ // Create the default alias if the name parameter is not empty.
+ if( !aName.IsEmpty() )
+ m_aliases.push_back( new LIB_ALIAS( aName, this ) );
+
+ // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
+ // when the field editors are invoked.
+ LIB_FIELD* value = new LIB_FIELD( this, VALUE );
+ value->SetText( aName );
+ drawings.push_back( value );
+
+ drawings.push_back( new LIB_FIELD( this, REFERENCE ) );
+ drawings.push_back( new LIB_FIELD( this, FOOTPRINT ) );
+ drawings.push_back( new LIB_FIELD( this, DATASHEET ) );
+}
+
+
+LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
+ EDA_ITEM( aPart ),
+ m_me( this, null_deleter() )
+{
+ LIB_ITEM* newItem;
+
+ m_library = aLibrary;
+ m_name = aPart.m_name;
+ m_FootprintList = aPart.m_FootprintList;
+ m_unitCount = aPart.m_unitCount;
+ m_unitsLocked = aPart.m_unitsLocked;
+ m_pinNameOffset = aPart.m_pinNameOffset;
+ m_showPinNumbers = aPart.m_showPinNumbers;
+ m_showPinNames = aPart.m_showPinNames;
+ m_dateModified = aPart.m_dateModified;
+ m_options = aPart.m_options;
+
+ BOOST_FOREACH( LIB_ITEM& oldItem, aPart.GetDrawItemList() )
+ {
+ if( oldItem.IsNew() )
+ continue;
+
+ newItem = (LIB_ITEM*) oldItem.Clone();
+ newItem->SetParent( this );
+ drawings.push_back( newItem );
+ }
+
+ for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
+ {
+ LIB_ALIAS* alias = new LIB_ALIAS( *aPart.m_aliases[i], this );
+ m_aliases.push_back( alias );
+ }
+}
+
+
+LIB_PART::~LIB_PART()
+{
+ wxLogTrace( traceSchLibMem,
+ wxT( "%s: destroying part '%s' with alias list count of %llu." ),
+ GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( GetName() ),
+ (long long unsigned) m_aliases.size() );
+
+ // If the part is being deleted directly rather than through the library,
+ // delete all of the aliases.
+ while( m_aliases.size() )
+ {
+ LIB_ALIAS* alias = m_aliases.back();
+ m_aliases.pop_back();
+ delete alias;
+ }
+}
+
+
+const wxString LIB_PART::GetLibraryName()
+{
+ if( m_library )
+ return m_library->GetName();
+
+ return wxString( _( "none" ) );
+}
+
+
+wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator )
+{
+ wxString subRef;
+
+ if( m_subpartIdSeparator != 0 && aAddSeparator )
+ subRef << wxChar( m_subpartIdSeparator );
+
+ if( m_subpartFirstId >= '0' && m_subpartFirstId <= '9' )
+ subRef << aUnit;
+ else
+ {
+ // use letters as notation. To allow more than 26 units, the sub ref
+ // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
+ // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
+ int u;
+ aUnit -= 1; // Unit number starts to 1. now to 0.
+
+ while( aUnit >= 26 ) // more than one letter are needed
+ {
+ u = aUnit / 26;
+ subRef << wxChar( m_subpartFirstId + u -1 );
+ aUnit %= 26;
+ }
+
+ u = m_subpartFirstId + aUnit;
+ subRef << wxChar( u );
+ }
+
+ return subRef;
+}
+
+
+void LIB_PART::SetName( const wxString& aName )
+{
+ m_name = aName;
+ GetValueField().SetText( aName );
+ m_aliases[0]->SetName( aName );
+}
+
+
+void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset, int aMulti,
+ int aConvert, GR_DRAWMODE aDrawMode, EDA_COLOR_T aColor,
+ const TRANSFORM& aTransform, bool aShowPinText, bool aDrawFields,
+ bool aOnlySelected, const std::vector* aPinsDangling )
+{
+ BASE_SCREEN* screen = aPanel ? aPanel->GetScreen() : NULL;
+
+ GRSetDrawMode( aDc, aDrawMode );
+
+ /* draw background for filled items using background option
+ * Solid lines will be drawn after the background
+ * Note also, background is not drawn when:
+ * printing in black and white
+ * If the color is not the default color (aColor != -1 )
+ */
+ if( ! (screen && screen->m_IsPrinting && GetGRForceBlackPenState())
+ && (aColor == UNSPECIFIED_COLOR) )
+ {
+ BOOST_FOREACH( LIB_ITEM& drawItem, drawings )
+ {
+ if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
+ continue;
+
+ if( aOnlySelected && !drawItem.IsSelected() )
+ continue;
+
+ // Do not draw an item while moving (the cursor handler does that)
+ if( drawItem.m_Flags & IS_MOVED )
+ continue;
+
+ // Do not draw items not attached to the current part
+ if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
+ continue;
+
+ if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
+ continue;
+
+ if( drawItem.Type() == LIB_FIELD_T )
+ continue;
+
+ if( drawItem.Type() == LIB_FIELD_T )
+ {
+ drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) NULL, aTransform );
+ }
+
+ // Now, draw only the background for items with
+ // m_Fill == FILLED_WITH_BG_BODYCOLOR:
+ drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) false, aTransform );
+ }
+ }
+
+ // Track the index into the dangling pins list
+ size_t pin_index = 0;
+
+ BOOST_FOREACH( LIB_ITEM& drawItem, drawings )
+ {
+ if( aOnlySelected && !drawItem.IsSelected() )
+ continue;
+
+ // Do not draw an item while moving (the cursor handler does that)
+ if( drawItem.m_Flags & IS_MOVED )
+ continue;
+
+ // Do not draw items not attached to the current part
+ if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
+ continue;
+
+ if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
+ continue;
+
+ if( !aDrawFields && drawItem.Type() == LIB_FIELD_T )
+ continue;
+
+ if( drawItem.Type() == LIB_PIN_T )
+ {
+ LIB_PIN& pin = dynamic_cast( drawItem );
+
+ uintptr_t flags = 0;
+ if( aShowPinText )
+ flags |= PIN_DRAW_TEXTS;
+
+ if( !aPinsDangling || (aPinsDangling->size() > pin_index && (*aPinsDangling)[pin_index] ) )
+ flags |= PIN_DRAW_DANGLING;
+
+ if( pin.IsPowerConnection() && IsPower() )
+ flags |= PIN_DANGLING_HIDDEN;
+
+ drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) flags, aTransform );
+
+ ++pin_index;
+ }
+ else if( drawItem.Type() == LIB_FIELD_T )
+ {
+ drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) NULL, aTransform );
+ }
+ else
+ {
+ bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
+ drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) forceNoFill,
+ aTransform );
+ }
+
+ }
+
+ // Enable this to draw the anchor of the component.
+#if 0
+ int len = aDc->DeviceToLogicalXRel( 3 );
+ EDA_RECT* const clipbox = aPanel ? aPanel->GetClipBox() : NULL;
+
+ GRLine( clipbox, aDc, aOffset.x, aOffset.y - len, aOffset.x,
+ aOffset.y + len, 0, aColor );
+ GRLine( clipbox, aDc, aOffset.x - len, aOffset.y, aOffset.x + len,
+ aOffset.y, 0, aColor );
+#endif
+
+ /* Enable this to draw the bounding box around the component to validate
+ * the bounding box calculations. */
+#if 0
+ EDA_RECT bBox = GetBoundingBox( aMulti, aConvert );
+ bBox.RevertYAxis();
+ bBox = aTransform.TransformCoordinate( bBox );
+ bBox.Move( aOffset );
+ GRRect( aPanel ? aPanel->GetClipBox() : NULL, aDc, bBox, 0, LIGHTMAGENTA );
+#endif
+}
+
+
+void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
+ const wxPoint& aOffset, const TRANSFORM& aTransform )
+{
+ wxASSERT( aPlotter != NULL );
+
+ aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
+ bool fill = aPlotter->GetColorMode();
+
+ // draw background for filled items using background option
+ // Solid lines will be drawn after the background
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ // Lib Fields are not plotted here, because this plot function
+ // is used to plot schematic items, which have they own fields
+ if( item.Type() == LIB_FIELD_T )
+ continue;
+
+ if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
+ continue;
+
+ if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
+ continue;
+
+ if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
+ item.Plot( aPlotter, aOffset, fill, aTransform );
+ }
+
+ // Not filled items and filled shapes are now plotted
+ // (plot only items which are not already plotted)
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() == LIB_FIELD_T )
+ continue;
+
+ if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
+ continue;
+
+ if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
+ continue;
+
+ if( item.m_Fill != FILLED_WITH_BG_BODYCOLOR )
+ item.Plot( aPlotter, aOffset, fill, aTransform );
+ }
+}
+
+void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
+ const wxPoint& aOffset, const TRANSFORM& aTransform )
+{
+ wxASSERT( aPlotter != NULL );
+
+ aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
+ bool fill = aPlotter->GetColorMode();
+
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() != LIB_FIELD_T )
+ continue;
+
+ if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
+ continue;
+
+ if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
+ continue;
+
+ // The reference is a special case: we should change the basic text
+ // to add '?' and the part id
+ LIB_FIELD& field = (LIB_FIELD&) item;
+ wxString tmp = field.GetShownText();
+ if( field.GetId() == REFERENCE )
+ {
+ wxString text = field.GetFullText( aUnit );
+ field.SetText( text );
+ }
+ item.Plot( aPlotter, aOffset, fill, aTransform );
+ field.SetText( tmp );
+ }
+}
+
+
+void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aDc )
+{
+ wxASSERT( aItem != NULL );
+
+ // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
+ // omitted when saving to disk.
+ if( aItem->Type() == LIB_FIELD_T )
+ {
+ LIB_FIELD* field = (LIB_FIELD*) aItem;
+
+ if( field->GetId() < MANDATORY_FIELDS )
+ {
+ wxLogWarning( _(
+ "An attempt was made to remove the %s field from component %s in library %s." ),
+ GetChars( field->GetName() ), GetChars( GetName() ),
+ GetChars( GetLibraryName() ) );
+ return;
+ }
+ }
+
+ LIB_ITEMS::iterator i;
+
+ for( i = drawings.begin(); i < drawings.end(); i++ )
+ {
+ if( *i == aItem )
+ {
+ if( aDc != NULL )
+ aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), UNSPECIFIED_COLOR,
+ g_XorMode, NULL, DefaultTransform );
+
+ drawings.erase( i );
+ SetModified();
+ break;
+ }
+ }
+}
+
+
+void LIB_PART::AddDrawItem( LIB_ITEM* aItem )
+{
+ wxASSERT( aItem != NULL );
+
+ drawings.push_back( aItem );
+ drawings.sort();
+}
+
+
+LIB_ITEM* LIB_PART::GetNextDrawItem( LIB_ITEM* aItem, KICAD_T aType )
+{
+ /* Return the next draw object pointer.
+ * If item is NULL return the first item of type in the list.
+ */
+ if( drawings.empty() )
+ return NULL;
+
+ if( aItem == NULL && aType == TYPE_NOT_INIT ) // type is unspecified
+ return &drawings[0];
+
+ // Search for last item
+ size_t idx = 0;
+
+ if( aItem )
+ {
+ for( ; idx < drawings.size(); idx++ )
+ {
+ if( aItem == &drawings[idx] )
+ {
+ idx++; // Prepare the next item search
+ break;
+ }
+ }
+ }
+
+ // Search the next item
+ for( ; idx < drawings.size(); idx++ )
+ {
+ if( aType == TYPE_NOT_INIT || drawings[ idx ].Type() == aType )
+ return &drawings[ idx ];
+ }
+
+ return NULL;
+}
+
+
+void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
+{
+ /* Notes:
+ * when aUnit == 0: no unit filtering
+ * when aConvert == 0: no convert (shape selection) filtering
+ * when .m_Unit == 0, the body item is common to units
+ * when .m_Convert == 0, the body item is common to shapes
+ */
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() != LIB_PIN_T ) // we search pins only
+ continue;
+
+ // Unit filtering:
+ if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
+ continue;
+
+ // Shape filtering:
+ if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
+ continue;
+
+ aList.push_back( (LIB_PIN*) &item );
+ }
+}
+
+
+LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert )
+{
+ wxString pNumber;
+ LIB_PINS pinList;
+
+ GetPins( pinList, aUnit, aConvert );
+
+ for( size_t i = 0; i < pinList.size(); i++ )
+ {
+ wxASSERT( pinList[i]->Type() == LIB_PIN_T );
+
+ pinList[i]->PinStringNum( pNumber );
+
+ if( aNumber == pNumber )
+ return pinList[i];
+ }
+
+ return NULL;
+}
+
+
+bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
+ bool aTestType, bool aTestOrientation, bool aTestLength )
+{
+ LIB_PINS thisPinList;
+ GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 );
+
+ BOOST_FOREACH( LIB_PIN* eachThisPin, thisPinList )
+ {
+ wxASSERT( eachThisPin );
+ LIB_PINS otherPinList;
+ aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 );
+ bool foundMatch = false;
+
+ BOOST_FOREACH( LIB_PIN* eachOtherPin, otherPinList )
+ {
+ wxASSERT( eachOtherPin );
+ // Same position?
+ if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
+ continue;
+
+ // Same number?
+ wxString eachThisPinNumber, eachOtherPinNumber;
+ eachThisPin->PinStringNum( eachThisPinNumber );
+ eachOtherPin->PinStringNum( eachOtherPinNumber );
+ if( aTestNums && ( eachThisPinNumber != eachOtherPinNumber ))
+ continue;
+
+ // Same name?
+ if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ))
+ continue;
+
+ // Same electrical type?
+ if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ))
+ continue;
+
+ // Same orientation?
+ if( aTestOrientation && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ))
+ continue;
+
+ // Same length?
+ if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ))
+ continue;
+
+ foundMatch = true;
+ }
+
+ if( !foundMatch )
+ {
+ // This means there was not an identical (according to the arguments)
+ // pin at the same position in the other component.
+ return true;
+ }
+ }
+
+ // The loop never gave up, so no conflicts were found.
+ return false;
+}
+
+
+bool LIB_PART::Save( OUTPUTFORMATTER& aFormatter )
+{
+ LIB_FIELD& value = GetValueField();
+
+ // First line: it s a comment (component name for readers)
+ aFormatter.Print( 0, "#\n# %s\n#\n", TO_UTF8( value.GetText() ) );
+
+ // Save data
+ aFormatter.Print( 0, "DEF" );
+
+#if 0 && defined(DEBUG)
+ if( value.GetText() == wxT( "R" ) )
+ {
+ int breakhere = 1;
+ (void) breakhere;
+ }
+#endif
+
+ if( value.IsVisible() )
+ {
+ aFormatter.Print( 0, " %s", TO_UTF8( value.GetText() ) );
+ }
+ else
+ {
+ aFormatter.Print( 0, " ~%s", TO_UTF8( value.GetText() ) );
+ }
+
+ LIB_FIELD& reference = GetReferenceField();
+
+ if( !reference.GetText().IsEmpty() )
+ {
+ aFormatter.Print( 0, " %s", TO_UTF8( reference.GetText() ) );
+ }
+ else
+ {
+ aFormatter.Print( 0, " ~" );
+ }
+
+ aFormatter.Print( 0, " %d %d %c %c %d %c %c\n",
+ 0, m_pinNameOffset,
+ m_showPinNumbers ? 'Y' : 'N',
+ m_showPinNames ? 'Y' : 'N',
+ m_unitCount, m_unitsLocked ? 'L' : 'F',
+ m_options == ENTRY_POWER ? 'P' : 'N' );
+
+ if( !SaveDateAndTime( aFormatter ) )
+ return false;
+
+ LIB_FIELDS fields;
+ GetFields( fields );
+
+ // Mandatory fields:
+ // may have their own save policy so there is a separate loop for them.
+ // Empty fields are saved, because the user may have set visibility,
+ // size and orientation
+ for( int i = 0; i < MANDATORY_FIELDS; ++i )
+ {
+ if( !fields[i].Save( aFormatter ) )
+ return false;
+ }
+
+ // User defined fields:
+ // may have their own save policy so there is a separate loop for them.
+
+ int fieldId = MANDATORY_FIELDS; // really wish this would go away.
+
+ for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
+ {
+ // There is no need to save empty fields, i.e. no reason to preserve field
+ // names now that fields names come in dynamically through the template
+ // fieldnames.
+ if( !fields[i].GetText().IsEmpty() )
+ {
+ fields[i].SetId( fieldId++ );
+
+ if( !fields[i].Save( aFormatter ) )
+ return false;
+ }
+ }
+
+ // Save the alias list: a line starting by "ALIAS". The first alias is the root
+ // and has the same name as the component. In the old library file format this
+ // alias does not get added to the alias list.
+ if( m_aliases.size() > 1 )
+ {
+ aFormatter.Print( 0, "ALIAS" );
+
+ for( unsigned i = 1; i < m_aliases.size(); i++ )
+ {
+ aFormatter.Print( 0, " %s", TO_UTF8( m_aliases[i]->GetName() ) );
+ }
+
+ aFormatter.Print( 0, "\n" );
+ }
+
+ // Write the footprint filter list
+ if( m_FootprintList.GetCount() != 0 )
+ {
+ aFormatter.Print( 0, "$FPLIST\n" );
+
+ for( unsigned i = 0; i < m_FootprintList.GetCount(); i++ )
+ {
+ aFormatter.Print( 0, " %s\n", TO_UTF8( m_FootprintList[i] ) );
+ }
+
+ aFormatter.Print( 0, "$ENDFPLIST\n" );
+ }
+
+ // Save graphics items (including pins)
+ if( !drawings.empty() )
+ {
+ /* we sort the draw items, in order to have an edition more easy,
+ * when a file editing "by hand" is made */
+ drawings.sort();
+
+ aFormatter.Print( 0, "DRAW\n" );
+
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() == LIB_FIELD_T )
+ continue;
+
+ if( !item.Save( aFormatter ) )
+ return false;
+ }
+
+ aFormatter.Print( 0, "ENDDRAW\n" );
+ }
+
+ aFormatter.Print( 0, "ENDDEF\n" );
+
+ return true;
+}
+
+
+bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg )
+{
+ int unused;
+ char* p;
+ char* componentName;
+ char* prefix = NULL;
+ char* line;
+
+ bool result;
+ wxString Msg;
+
+ line = aLineReader.Line();
+
+ p = strtok( line, " \t\r\n" );
+
+ if( strcmp( p, "DEF" ) != 0 )
+ {
+ aErrorMsg.Printf( wxT( "DEF command expected in line %d, aborted." ),
+ aLineReader.LineNumber() );
+ return false;
+ }
+
+ // Read DEF line:
+ char drawnum = 0;
+ char drawname = 0;
+
+ if( ( componentName = strtok( NULL, " \t\n" ) ) == NULL // Part name:
+ || ( prefix = strtok( NULL, " \t\n" ) ) == NULL // Prefix name:
+ || ( p = strtok( NULL, " \t\n" ) ) == NULL // NumOfPins:
+ || sscanf( p, "%d", &unused ) != 1
+ || ( p = strtok( NULL, " \t\n" ) ) == NULL // TextInside:
+ || sscanf( p, "%d", &m_pinNameOffset ) != 1
+ || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
+ || sscanf( p, "%c", &drawnum ) != 1
+ || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
+ || sscanf( p, "%c", &drawname ) != 1
+ || ( p = strtok( NULL, " \t\n" ) ) == NULL // m_unitCount:
+ || sscanf( p, "%d", &m_unitCount ) != 1 )
+ {
+ aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
+ aLineReader.LineNumber() );
+
+ while( (line = aLineReader.ReadLine()) != NULL )
+ {
+ p = strtok( line, " \t\n" );
+
+ if( p && stricmp( p, "ENDDEF" ) == 0 )
+ break;
+ }
+
+ return false;
+ }
+
+ // Ensure m_unitCount is >= 1 (could be read as 0 in old libraries)
+ if( m_unitCount < 1 )
+ m_unitCount = 1;
+
+ m_showPinNumbers = ( drawnum == 'N' ) ? false : true;
+ m_showPinNames = ( drawname == 'N' ) ? false : true;
+
+ // Copy part name and prefix.
+ LIB_FIELD& value = GetValueField();
+
+ if( componentName[0] != '~' )
+ {
+ m_name = FROM_UTF8( componentName );
+ value.SetText( m_name );
+ }
+ else
+ {
+ m_name = FROM_UTF8( &componentName[1] );
+ value.SetText( m_name );
+ value.SetVisible( false );
+ }
+
+ // Add the root alias to the alias list.
+ m_aliases.push_back( new LIB_ALIAS( m_name, this ) );
+
+ LIB_FIELD& reference = GetReferenceField();
+
+ if( strcmp( prefix, "~" ) == 0 )
+ {
+ reference.Empty();
+ reference.SetVisible( false );
+ }
+ else
+ {
+ reference.SetText( FROM_UTF8( prefix ) );
+ }
+
+ // Copy optional infos
+ if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'L' )
+ m_unitsLocked = true;
+
+ if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'P' )
+ m_options = ENTRY_POWER;
+
+ // Read next lines, until "ENDDEF" is found
+ while( ( line = aLineReader.ReadLine() ) != NULL )
+ {
+ p = strtok( line, " \t\r\n" );
+
+ // This is the error flag ( if an error occurs, result = false)
+ result = true;
+
+ if( *line == '#' ) // a comment
+ continue;
+
+ if( p == NULL ) // empty line
+ continue;
+
+ if( line[0] == 'T' && line[1] == 'i' )
+ result = LoadDateAndTime( aLineReader );
+ else if( *line == 'F' )
+ result = LoadField( aLineReader, Msg );
+ else if( strcmp( p, "ENDDEF" ) == 0 ) // End of component description
+ goto ok;
+ else if( strcmp( p, "DRAW" ) == 0 )
+ result = LoadDrawEntries( aLineReader, Msg );
+ else if( strncmp( p, "ALIAS", 5 ) == 0 )
+ {
+ p = strtok( NULL, "\r\n" );
+ result = LoadAliases( p, aErrorMsg );
+ }
+ else if( strncmp( p, "$FPLIST", 5 ) == 0 )
+ result = LoadFootprints( aLineReader, Msg );
+
+ // End line or block analysis: test for an error
+ if( !result )
+ {
+ if( Msg.IsEmpty() )
+ aErrorMsg.Printf( wxT( "error occurred at line %d " ), aLineReader.LineNumber() );
+ else
+ aErrorMsg.Printf( wxT( "error <%s> occurred at line %d " ),
+ GetChars( Msg ), aLineReader.LineNumber() );
+
+ return false;
+ }
+ }
+
+ return false;
+
+ok:
+ // If we are here, this part is O.k. - put it in:
+ drawings.sort();
+
+ return true;
+}
+
+
+bool LIB_PART::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg )
+{
+ char* line;
+ LIB_ITEM* newEntry = NULL;
+
+ while( true )
+ {
+ if( !( line = aLineReader.ReadLine() ) )
+ {
+ aErrorMsg = wxT( "file ended prematurely loading component draw element" );
+ return false;
+ }
+
+ if( strncmp( line, "ENDDRAW", 7 ) == 0 )
+ break;
+
+ newEntry = NULL;
+
+ switch( line[0] )
+ {
+ case 'A': // Arc
+ newEntry = ( LIB_ITEM* ) new LIB_ARC( this );
+ break;
+
+ case 'C': // Circle
+ newEntry = ( LIB_ITEM* ) new LIB_CIRCLE( this );
+ break;
+
+ case 'T': // Text
+ newEntry = ( LIB_ITEM* ) new LIB_TEXT( this );
+ break;
+
+ case 'S': // Square
+ newEntry = ( LIB_ITEM* ) new LIB_RECTANGLE( this );
+ break;
+
+ case 'X': // Pin Description
+ newEntry = ( LIB_ITEM* ) new LIB_PIN( this );
+ break;
+
+ case 'P': // Polyline
+ newEntry = ( LIB_ITEM* ) new LIB_POLYLINE( this );
+ break;
+
+ case 'B': // Bezier Curves
+ newEntry = ( LIB_ITEM* ) new LIB_BEZIER( this );
+ break;
+
+ case '#': // Comment
+ continue;
+
+ case '\n':
+ case '\r':
+ case 0: // empty line
+ continue;
+
+ default:
+ aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] );
+ return false;
+ }
+
+ if( !newEntry->Load( aLineReader, aErrorMsg ) )
+ {
+ aErrorMsg.Printf( wxT( "error '%s' in DRAW command %c" ),
+ GetChars( aErrorMsg ), line[0] );
+ delete newEntry;
+
+ // Flush till end of draw section
+ do
+ {
+ if( !aLineReader.ReadLine() )
+ {
+ aErrorMsg = wxT( "file ended prematurely while attempting "
+ "to flush to end of drawing section." );
+ return false;
+ }
+ } while( strncmp( line, "ENDDRAW", 7 ) != 0 );
+
+ return false;
+ }
+ else
+ {
+ drawings.push_back( newEntry );
+ }
+ }
+
+ return true;
+}
+
+
+bool LIB_PART::LoadAliases( char* aLine, wxString& aErrorMsg )
+{
+ char* text = strtok( aLine, " \t\r\n" );
+
+ while( text )
+ {
+ m_aliases.push_back( new LIB_ALIAS( FROM_UTF8( text ), this ) );
+ text = strtok( NULL, " \t\r\n" );
+ }
+
+ return true;
+}
+
+
+bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
+{
+ LIB_FIELD* field = new LIB_FIELD( this );
+
+ if( !field->Load( aLineReader, aErrorMsg ) )
+ {
+ delete field;
+ return false;
+ }
+
+ if( field->GetId() < MANDATORY_FIELDS )
+ {
+ LIB_FIELD* fixedField = GetField( field->GetId() );
+
+ // this will fire only if somebody broke a constructor or editor.
+ // MANDATORY_FIELDS are always present in ram resident components, no
+ // exceptions, and they always have their names set, even fixed fields.
+ wxASSERT( fixedField );
+
+ *fixedField = *field;
+
+ if( field->GetId() == VALUE )
+ m_name = field->GetText();
+
+ delete field;
+ }
+ else
+ {
+ drawings.push_back( field );
+ }
+
+ return true;
+}
+
+
+bool LIB_PART::LoadFootprints( LINE_READER& aLineReader, wxString& aErrorMsg )
+{
+ char* line;
+ char* p;
+
+ while( true )
+ {
+ if( !( line = aLineReader.ReadLine() ) )
+ {
+ aErrorMsg = wxT( "file ended prematurely while loading footprints" );
+ return false;
+ }
+
+ p = strtok( line, " \t\r\n" );
+
+ if( stricmp( p, "$ENDFPLIST" ) == 0 )
+ break;
+
+ m_FootprintList.Add( FROM_UTF8( p ) );
+ }
+
+ return true;
+}
+
+
+const EDA_RECT LIB_PART::GetBoundingBox( int aUnit, int aConvert ) const
+{
+ EDA_RECT bBox;
+ bool initialized = false;
+
+ for( unsigned ii = 0; ii < drawings.size(); ii++ )
+ {
+ const LIB_ITEM& item = drawings[ii];
+
+ if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
+ && ( aUnit != item.m_Unit ) ) )
+ continue;
+
+ if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
+ continue;
+
+ if ( ( item.Type() == LIB_FIELD_T ) && !( ( LIB_FIELD& ) item ).IsVisible() )
+ continue;
+
+ if( initialized )
+ bBox.Merge( item.GetBoundingBox() );
+ else
+ {
+ bBox = item.GetBoundingBox();
+ initialized = true;
+ }
+ }
+
+ return bBox;
+}
+
+
+const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
+{
+ EDA_RECT bBox;
+ bool initialized = false;
+
+ for( unsigned ii = 0; ii < drawings.size(); ii++ )
+ {
+ const LIB_ITEM& item = drawings[ii];
+
+ if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
+ && ( aUnit != item.m_Unit ) ) )
+ continue;
+
+ if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
+ continue;
+
+ if ( item.Type() == LIB_FIELD_T )
+ continue;
+
+ if( initialized )
+ bBox.Merge( item.GetBoundingBox() );
+ else
+ {
+ bBox = item.GetBoundingBox();
+ initialized = true;
+ }
+ }
+
+ return bBox;
+}
+
+
+void LIB_PART::deleteAllFields()
+{
+ LIB_ITEMS::iterator it;
+
+ for( it = drawings.begin(); it!=drawings.end(); /* deleting */ )
+ {
+ if( it->Type() != LIB_FIELD_T )
+ {
+ ++it;
+ continue;
+ }
+
+ // 'it' is not advanced, but should point to next in list after erase()
+ it = drawings.erase( it );
+ }
+}
+
+
+void LIB_PART::SetFields( const std::vector & aFields )
+{
+ deleteAllFields();
+
+ for( unsigned i=0; iSetParent( this );
+ drawings.push_back( field );
+ }
+
+ // Reorder drawings: transparent polygons first, pins and text last.
+ // so texts have priority on screen.
+ drawings.sort();
+}
+
+
+void LIB_PART::GetFields( LIB_FIELDS& aList )
+{
+ LIB_FIELD* field;
+
+ // The only caller of this function is the library field editor, so it
+ // establishes policy here.
+
+ // Grab the MANDATORY_FIELDS first, in expected order given by
+ // enum NumFieldType
+ for( int id=0; idGetId() < MANDATORY_FIELDS )
+ continue; // was added above
+
+ aList.push_back( *field );
+ }
+}
+
+
+LIB_FIELD* LIB_PART::GetField( int aId )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() != LIB_FIELD_T )
+ continue;
+
+ LIB_FIELD* field = ( LIB_FIELD* ) &item;
+
+ if( field->GetId() == aId )
+ return field;
+ }
+
+ return NULL;
+}
+
+
+LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( item.Type() != LIB_FIELD_T )
+ continue;
+
+ LIB_FIELD* field = ( LIB_FIELD* ) &item;
+
+ if( field->GetName() == aFieldName )
+ return field;
+ }
+
+ return NULL;
+}
+
+
+LIB_FIELD& LIB_PART::GetValueField()
+{
+ LIB_FIELD* field = GetField( VALUE );
+ wxASSERT( field != NULL );
+ return *field;
+}
+
+
+LIB_FIELD& LIB_PART::GetReferenceField()
+{
+ LIB_FIELD* field = GetField( REFERENCE );
+ wxASSERT( field != NULL );
+ return *field;
+}
+
+
+bool LIB_PART::SaveDateAndTime( OUTPUTFORMATTER& aFormatter )
+{
+ int year, mon, day, hour, min, sec;
+
+ if( m_dateModified == 0 )
+ return true;
+
+ sec = m_dateModified & 63;
+ min = ( m_dateModified >> 6 ) & 63;
+ hour = ( m_dateModified >> 12 ) & 31;
+ day = ( m_dateModified >> 17 ) & 31;
+ mon = ( m_dateModified >> 22 ) & 15;
+ year = ( m_dateModified >> 26 ) + 1990;
+
+ aFormatter.Print( 0, "Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
+
+ return true;
+}
+
+
+bool LIB_PART::LoadDateAndTime( char* aLine )
+{
+ int year, mon, day, hour, min, sec;
+
+ year = mon = day = hour = min = sec = 0;
+ strtok( aLine, " \r\t\n" );
+ strtok( NULL, " \r\t\n" );
+
+ if( sscanf( aLine, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec ) != 6 )
+ return false;
+
+ m_dateModified = ( sec & 63 ) + ( ( min & 63 ) << 6 ) +
+ ( ( hour & 31 ) << 12 ) + ( ( day & 31 ) << 17 ) +
+ ( ( mon & 15 ) << 22 ) + ( ( year - 1990 ) << 26 );
+
+ return true;
+}
+
+
+void LIB_PART::SetOffset( const wxPoint& aOffset )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ item.SetOffset( aOffset );
+ }
+}
+
+
+void LIB_PART::RemoveDuplicateDrawItems()
+{
+ drawings.unique();
+}
+
+
+bool LIB_PART::HasConversion() const
+{
+ for( unsigned ii = 0; ii < drawings.size(); ii++ )
+ {
+ const LIB_ITEM& item = drawings[ii];
+ if( item.m_Convert > 1 )
+ return true;
+ }
+
+ return false;
+}
+
+
+void LIB_PART::ClearStatus()
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ item.m_Flags = 0;
+ }
+}
+
+
+int LIB_PART::SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditPinByPin )
+{
+ int itemCount = 0;
+
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ item.ClearFlags( SELECTED );
+
+ if( ( item.m_Unit && item.m_Unit != aUnit )
+ || ( item.m_Convert && item.m_Convert != aConvert ) )
+ {
+ if( item.Type() != LIB_PIN_T )
+ continue;
+
+ // Specific rules for pins.
+ if( aEditPinByPin || m_unitsLocked
+ || ( item.m_Convert && item.m_Convert != aConvert ) )
+ continue;
+ }
+
+ if( item.Inside( aRect ) )
+ {
+ item.SetFlags( SELECTED );
+ itemCount++;
+ }
+ }
+
+ return itemCount;
+}
+
+
+void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( !item.IsSelected() )
+ continue;
+
+ item.SetOffset( aOffset );
+ item.m_Flags = 0;
+ }
+
+ drawings.sort();
+}
+
+
+void LIB_PART::ClearSelectedItems()
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ item.m_Flags = 0;
+ }
+}
+
+
+void LIB_PART::DeleteSelectedItems()
+{
+ LIB_ITEMS::iterator item = drawings.begin();
+
+ // We *do not* remove the 2 mandatory fields: reference and value
+ // so skip them (do not remove) if they are flagged selected.
+ // Skip also not visible items.
+ // But I think fields must not be deleted by a block delete command or other global command
+ // because they are not really graphic items
+ while( item != drawings.end() )
+ {
+ if( item->Type() == LIB_FIELD_T )
+ {
+#if 0 // Set to 1 to allows fields deletion on block delete or other global command
+ LIB_FIELD& field = ( LIB_FIELD& ) *item;
+
+ if( (field.GetId() == REFERENCE) || (field.m_FieldId == VALUE) ||
+ (field.m_Attributs & TEXT_NO_VISIBLE) )
+#endif
+ item->ClearFlags( SELECTED );
+ }
+
+ if( !item->IsSelected() )
+ item++;
+ else
+ item = drawings.erase( item );
+ }
+}
+
+
+void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
+{
+ /* *do not* use iterators here, because new items
+ * are added to drawings that is a boost::ptr_vector.
+ * When push_back elements in buffer,
+ * a memory reallocation can happen and will break pointers
+ */
+ unsigned icnt = drawings.size();
+
+ for( unsigned ii = 0; ii < icnt; ii++ )
+ {
+ LIB_ITEM& item = drawings[ii];
+
+ // We *do not* copy fields because they are unique for the whole component
+ // so skip them (do not duplicate) if they are flagged selected.
+ if( item.Type() == LIB_FIELD_T )
+ item.ClearFlags( SELECTED );
+
+ if( !item.IsSelected() )
+ continue;
+
+ item.ClearFlags( SELECTED );
+ LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
+ newItem->SetFlags( SELECTED );
+ drawings.push_back( newItem );
+ }
+
+ MoveSelectedItems( aOffset );
+ drawings.sort();
+}
+
+
+
+void LIB_PART::MirrorSelectedItemsH( const wxPoint& aCenter )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( !item.IsSelected() )
+ continue;
+
+ item.MirrorHorizontal( aCenter );
+ item.m_Flags = 0;
+ }
+
+ drawings.sort();
+}
+
+void LIB_PART::MirrorSelectedItemsV( const wxPoint& aCenter )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( !item.IsSelected() )
+ continue;
+
+ item.MirrorVertical( aCenter );
+ item.m_Flags = 0;
+ }
+
+ drawings.sort();
+}
+
+void LIB_PART::RotateSelectedItems( const wxPoint& aCenter )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( !item.IsSelected() )
+ continue;
+
+ item.Rotate( aCenter );
+ item.m_Flags = 0;
+ }
+
+ drawings.sort();
+}
+
+
+
+LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
+ KICAD_T aType, const wxPoint& aPoint )
+{
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
+ || ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
+ || ( ( item.Type() != aType ) && ( aType != TYPE_NOT_INIT ) ) )
+ continue;
+
+ if( item.HitTest( aPoint ) )
+ return &item;
+ }
+
+ return NULL;
+}
+
+
+LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
+ const wxPoint& aPoint, const TRANSFORM& aTransform )
+{
+ /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
+ * wxPoint& pt ) to search items.
+ * because this function uses DefaultTransform as orient/mirror matrix
+ * we temporary copy aTransform in DefaultTransform
+ */
+ LIB_ITEM* item;
+ TRANSFORM transform = DefaultTransform;
+ DefaultTransform = aTransform;
+
+ item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
+
+ // Restore matrix
+ DefaultTransform = transform;
+
+ return item;
+}
+
+
+void LIB_PART::SetUnitCount( int aCount )
+{
+ if( m_unitCount == aCount )
+ return;
+
+ if( aCount < m_unitCount )
+ {
+ LIB_ITEMS::iterator i;
+ i = drawings.begin();
+
+ while( i != drawings.end() )
+ {
+ if( i->m_Unit > aCount )
+ i = drawings.erase( i );
+ else
+ i++;
+ }
+ }
+ else
+ {
+ int prevCount = m_unitCount;
+
+ // We cannot use an iterator here, because when adding items in vector
+ // the buffer can be reallocated, that change the previous value of
+ // .begin() and .end() iterators and invalidate others iterators
+ unsigned imax = drawings.size();
+
+ for( unsigned ii = 0; ii < imax; ii++ )
+ {
+ if( drawings[ii].m_Unit != 1 )
+ continue;
+
+ for( int j = prevCount + 1; j <= aCount; j++ )
+ {
+ LIB_ITEM* newItem = (LIB_ITEM*) drawings[ii].Clone();
+ newItem->m_Unit = j;
+ drawings.push_back( newItem );
+ }
+ }
+
+ drawings.sort();
+ }
+
+ m_unitCount = aCount;
+}
+
+
+void LIB_PART::SetConversion( bool aSetConvert )
+{
+ if( aSetConvert == HasConversion() )
+ return;
+
+ // Duplicate items to create the converted shape
+ if( aSetConvert )
+ {
+ std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
+
+ BOOST_FOREACH( LIB_ITEM& item, drawings )
+ {
+ // Only pins are duplicated.
+ if( item.Type() != LIB_PIN_T )
+ continue;
+
+ if( item.m_Convert == 1 )
+ {
+ LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
+ newItem->m_Convert = 2;
+ tmp.push_back( newItem );
+ }
+ }
+
+ // Transfer the new pins to the LIB_PART.
+ for( unsigned i = 0; i < tmp.size(); i++ )
+ drawings.push_back( tmp[i] );
+ }
+ else
+ {
+ // Delete converted shape items because the converted shape does
+ // not exist
+ LIB_ITEMS::iterator i = drawings.begin();
+
+ while( i != drawings.end() )
+ {
+ if( i->m_Convert > 1 )
+ i = drawings.erase( i );
+ else
+ i++;
+ }
+ }
+}
+
+
+wxArrayString LIB_PART::GetAliasNames( bool aIncludeRoot ) const
+{
+ wxArrayString names;
+
+ LIB_ALIASES::const_iterator it;
+
+ for( it=m_aliases.begin(); itIsRoot() )
+ continue;
+
+ names.Add( (*it)->GetName() );
+ }
+
+ return names;
+}
+
+
+bool LIB_PART::HasAlias( const wxString& aName ) const
+{
+ wxCHECK2_MSG( !aName.IsEmpty(), return false,
+ wxT( "Cannot get alias with an empty name, bad programmer." ) );
+
+ for( size_t i = 0; i < m_aliases.size(); i++ )
+ {
+ if( Cmp_KEEPCASE( aName, m_aliases[i]->GetName() ) == 0 )
+ return true;
+ }
+
+ return false;
+}
+
+
+void LIB_PART::SetAliases( const wxArrayString& aAliasList )
+{
+ wxCHECK_RET( !m_library,
+ wxT( "Part aliases cannot be changed when they are owned by a library." ) );
+
+ if( aAliasList == GetAliasNames() )
+ return;
+
+ // Add names not existing in the current component alias list.
+ for( size_t i = 0; i < aAliasList.GetCount(); i++ )
+ {
+ if( HasAlias( aAliasList[ i ] ) )
+ continue;
+
+ m_aliases.push_back( new LIB_ALIAS( aAliasList[ i ], this ) );
+ }
+
+ // Remove names in the current component that are not in the new alias list.
+ LIB_ALIASES::iterator it = m_aliases.begin();
+
+ while( it != m_aliases.end() )
+ {
+ int index = aAliasList.Index( (*it)->GetName(), false );
+
+ if( index != wxNOT_FOUND || (*it)->IsRoot() )
+ ++it;
+ else
+ it = m_aliases.erase( it );
+ }
+}
+
+
+#if 0 // this version looked suspect to me, it did not rename a deleted root
+
+void LIB_PART::RemoveAlias( const wxString& aName )
+{
+ wxCHECK_RET( m_library == NULL,
+ wxT( "Part aliases cannot be changed when they are owned by a library." ) );
+ wxCHECK_RET( !aName.IsEmpty(), wxT( "Cannot get alias with an empty name." ) );
+
+ LIB_ALIASES::iterator it;
+
+ for( it = m_aliases.begin(); it < m_aliases.end(); it++ )
+ {
+ if( Cmp_KEEPCASE( aName, (*it)->GetName() ) == 0 )
+ {
+ m_aliases.erase( it );
+ break;
+ }
+ }
+}
+
+#else
+void LIB_PART::RemoveAlias( const wxString& aName )
+{
+ LIB_ALIAS* a = GetAlias( aName );
+
+ if( a )
+ RemoveAlias( a );
+}
+#endif
+
+
+LIB_ALIAS* LIB_PART::RemoveAlias( LIB_ALIAS* aAlias )
+{
+ wxCHECK_MSG( aAlias, NULL, wxT( "Cannot remove alias by NULL pointer." ) );
+
+ LIB_ALIAS* nextAlias = NULL;
+
+ LIB_ALIASES::iterator it = find( m_aliases.begin(), m_aliases.end(), aAlias );
+
+ if( it != m_aliases.end() )
+ {
+ bool rename = aAlias->IsRoot();
+
+ wxLogTrace( traceSchLibMem,
+ wxT( "%s: part:'%s', alias:'%s', alias count %llu, reference count %ld." ),
+ GetChars( wxString::FromAscii( __WXFUNCTION__ ) ),
+ GetChars( m_name ),
+ GetChars( aAlias->GetName() ),
+ (long long unsigned) m_aliases.size(),
+ m_me.use_count() );
+
+ it = m_aliases.erase( it );
+
+ if( !m_aliases.empty() )
+ {
+ if( it == m_aliases.end() )
+ it = m_aliases.begin();
+
+ nextAlias = *it;
+
+ if( rename )
+ SetName( nextAlias->GetName() );
+ }
+ }
+
+ return nextAlias;
+}
+
+
+void LIB_PART::RemoveAllAliases()
+{
+ // Remove all of the aliases except the root alias.
+ while( m_aliases.size() > 1 )
+ m_aliases.pop_back();
+}
+
+
+LIB_ALIAS* LIB_PART::GetAlias( const wxString& aName )
+{
+ wxCHECK2_MSG( !aName.IsEmpty(), return NULL,
+ wxT( "Cannot get alias with an empty name. Bad programmer!" ) );
+
+ for( size_t i = 0; i < m_aliases.size(); i++ )
+ {
+ if( Cmp_KEEPCASE( aName, m_aliases[i]->GetName() ) == 0 )
+ return m_aliases[i];
+ }
+
+ return NULL;
+}
+
+
+LIB_ALIAS* LIB_PART::GetAlias( size_t aIndex )
+{
+ wxCHECK2_MSG( aIndex < m_aliases.size(), return NULL,
+ wxT( "Illegal alias list index, bad programmer." ) );
+
+ return m_aliases[aIndex];
+}
+
+
+void LIB_PART::AddAlias( const wxString& aName )
+{
+ wxCHECK_RET( !HasAlias( aName ),
+ wxT( "Part <" ) + GetName() + wxT( "> already has an alias <" ) +
+ aName + wxT( ">. Bad programmer." ) );
+
+ m_aliases.push_back( new LIB_ALIAS( aName, this ) );
+}
+
+
+void LIB_PART::SetSubpartIdNotation( int aSep, int aFirstId )
+{
+ m_subpartFirstId = 'A';
+ m_subpartIdSeparator = 0;
+
+ if( aSep == '.' || aSep == '-' || aSep == '_' )
+ m_subpartIdSeparator = aSep;
+
+ if( aFirstId == '1' && aSep != 0 )
+ m_subpartFirstId = aFirstId;
+}
diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h
new file mode 100644
index 00000000..b81859eb
--- /dev/null
+++ b/eeschema/class_libentry.h
@@ -0,0 +1,773 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_libentry.h
+ */
+
+#ifndef CLASS_LIBENTRY_H
+#define CLASS_LIBENTRY_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class LINE_READER;
+class OUTPUTFORMATTER;
+class PART_LIB;
+class LIB_ALIAS;
+class LIB_PART;
+class LIB_FIELD;
+
+
+/// Compiler controlled string compare function, either case independent or not:
+inline int Cmp_KEEPCASE( const wxString& aString1, const wxString& aString2 )
+{
+#ifdef KICAD_KEEPCASE
+ // case specificity, the normal behavior:
+ return aString1.Cmp( aString2 );
+#else
+ // case independence (only for guys who want that: not recommended)
+ return aString1.CmpNoCase( aString2 );
+#endif
+}
+
+
+typedef std::vector LIB_ALIASES;
+typedef boost::shared_ptr PART_SPTR; ///< shared pointer to LIB_PART
+typedef boost::weak_ptr PART_REF; ///< weak pointer to LIB_PART
+
+
+/* values for member .m_options */
+enum LIBRENTRYOPTIONS
+{
+ ENTRY_NORMAL, // Libentry is a standard part (real or alias)
+ ENTRY_POWER // Libentry is a power symbol
+};
+
+
+/// WXTRACE value to enable schematic library memory deletion debug output.
+extern const wxChar traceSchLibMem[];
+
+
+/**
+ * Part library alias object definition.
+ *
+ * Part aliases are not really parts. An alias uses the part definition
+ * (graphic, pins...) but has its own name, keywords and documentation. Therefore, when
+ * the part is modified, alias of this part are modified. This is a simple
+ * method to create parts that have the same physical layout with different names
+ * such as 74LS00, 74HC00 ... and many op amps.
+ */
+class LIB_ALIAS : public EDA_ITEM
+{
+ /**
+ * Actual LIB_PART referenced by [multiple] aliases.
+ *
+ * @note - Do not delete the shared part. The shared part is shared by
+ * all of the aliases associated with it. A shared LIB_PART will
+ * be deleted when all LIB_ALIASes pointing to it are deleted.
+ */
+ LIB_PART* shared;
+
+ friend class LIB_PART;
+
+protected:
+ wxString name;
+ wxString description; ///< documentation for info
+ wxString keyWords; ///< keyword list (used for search for parts by keyword)
+ wxString docFileName; ///< Associate doc file name
+
+public:
+ LIB_ALIAS( const wxString& aName, LIB_PART* aRootComponent );
+ LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_PART* aRootComponent = NULL );
+
+ virtual ~LIB_ALIAS();
+
+ virtual wxString GetClass() const
+ {
+ return wxT( "LIB_ALIAS" );
+ }
+
+ /**
+ * Function GetPart
+ * gets the shared LIB_PART.
+ *
+ * @return LIB_PART* - the LIB_PART shared by
+ * this LIB_ALIAS with possibly other LIB_ALIASes.
+ */
+ LIB_PART* GetPart() const
+ {
+ return shared;
+ }
+
+ const wxString GetLibraryName();
+
+ bool IsRoot() const;
+
+ PART_LIB* GetLib();
+
+ const wxString& GetName() const { return name; }
+
+ void SetName( const wxString& aName ) { name = aName; }
+
+ void SetDescription( const wxString& aDescription )
+ {
+ description = aDescription;
+ }
+
+ wxString GetDescription() const { return description; }
+
+ void SetKeyWords( const wxString& aKeyWords )
+ {
+ keyWords = aKeyWords;
+ }
+
+ wxString GetKeyWords() const { return keyWords; }
+
+ void SetDocFileName( const wxString& aDocFileName )
+ {
+ docFileName = aDocFileName;
+ }
+
+ wxString GetDocFileName() const { return docFileName; }
+
+ /**
+ * Function SaveDocs
+ * write the entry document information to \a aFormatter in "*.dcm" format.
+ *
+ * @param aFormatter The #OUTPUTFORMATTER to write the alias documents to.
+ * @return True if success writing else false.
+ */
+ bool SaveDoc( OUTPUTFORMATTER& aFormatter );
+
+ /**
+ * KEEPCASE sensitive comparison of the part entry name.
+ */
+ bool operator==( const wxChar* aName ) const;
+ bool operator!=( const wxChar* aName ) const
+ {
+ return !( *this == aName );
+ }
+
+ bool operator==( const LIB_ALIAS* aAlias ) const { return this == aAlias; }
+
+#if defined(DEBUG)
+ void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
+#endif
+};
+
+extern bool operator<( const LIB_ALIAS& aItem1, const LIB_ALIAS& aItem2 );
+
+extern int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2 );
+
+
+/**
+ * Class LIB_PART
+ * defines a library part object.
+ *
+ * A library part object is typically saved and loaded in a part library file (.lib).
+ * Library parts are different from schematic components.
+ */
+class LIB_PART : public EDA_ITEM
+{
+ friend class PART_LIB;
+ friend class LIB_ALIAS;
+
+ PART_SPTR m_me; ///< http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared
+ wxString m_name;
+ int m_pinNameOffset; ///< The offset in mils to draw the pin name. Set to 0
+ ///< to draw the pin name above the pin.
+ bool m_unitsLocked; ///< True if part has multiple units and changing
+ ///< one unit does not automatically change another unit.
+ bool m_showPinNames; ///< Determines if part pin names are visible.
+ bool m_showPinNumbers; ///< Determines if part pin numbers are visible.
+ long m_dateModified; ///< Date the part was last modified.
+ LIBRENTRYOPTIONS m_options; ///< Special part features such as POWER or NORMAL.)
+ int m_unitCount; ///< Number of units (parts) per package.
+ LIB_ITEMS drawings; ///< How to draw this part.
+ wxArrayString m_FootprintList; /**< List of suitable footprint names for the
+ part (wild card names accepted). */
+ LIB_ALIASES m_aliases; ///< List of alias object pointers associated with the
+ ///< part.
+ PART_LIB* m_library; ///< Library the part belongs to if any.
+
+ static int m_subpartIdSeparator; ///< the separator char between
+ ///< the subpart id and the reference
+ ///< like U1A ( m_subpartIdSeparator = 0 ) or U1.A or U1-A
+ static int m_subpartFirstId; ///< the ascii char value to calculate the subpart symbol id
+ ///< from the part number: only 'A', 'a' or '1' can be used,
+ ///< other values have no sense.
+private:
+ void deleteAllFields();
+
+ // LIB_PART() { } // not legal
+
+public:
+
+ LIB_PART( const wxString& aName, PART_LIB* aLibrary = NULL );
+ LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary = NULL );
+
+ virtual ~LIB_PART();
+
+ PART_SPTR SharedPtr()
+ {
+ // clone a shared pointer
+ return m_me;
+ }
+
+ virtual wxString GetClass() const
+ {
+ return wxT( "LIB_PART" );
+ }
+
+ virtual void SetName( const wxString& aName );
+
+ const wxString& GetName() { return m_name; }
+
+ const wxString GetLibraryName();
+
+ PART_LIB* GetLib() { return m_library; }
+
+ wxArrayString GetAliasNames( bool aIncludeRoot = true ) const;
+
+ size_t GetAliasCount() const { return m_aliases.size(); }
+
+ LIB_ALIAS* GetAlias( size_t aIndex );
+
+ LIB_ALIAS* GetAlias( const wxString& aName );
+
+ /**
+ * Function AddAlias
+ *
+ * Add an alias \a aName to the part.
+ *
+ * Duplicate alias names are not added to the alias list. Debug builds will raise an
+ * assertion. Release builds will fail silently.
+ *
+ * @param aName - Name of alias to add.
+ */
+ void AddAlias( const wxString& aName );
+
+ /**
+ * Test if alias \a aName is in part alias list.
+ *
+ * Alias name comparisons are case insensitive.
+ *
+ * @param aName - Name of alias.
+ * @return True if alias name in alias list.
+ */
+ bool HasAlias( const wxString& aName ) const;
+
+ void SetAliases( const wxArrayString& aAliasList );
+
+ void RemoveAlias( const wxString& aName );
+ LIB_ALIAS* RemoveAlias( LIB_ALIAS* aAlias );
+
+ void RemoveAllAliases();
+
+ wxArrayString& GetFootPrints() { return m_FootprintList; }
+
+ /**
+ * Function GetBoundingBox
+ * @return the part bounding box ( in user coordinates )
+ * @param aUnit = unit selection = 0, or 1..n
+ * @param aConvert = 0, 1 or 2
+ * If aUnit == 0, unit is not used
+ * if aConvert == 0 Convert is non used
+ * Invisible fields are not taken in account
+ **/
+ const EDA_RECT GetBoundingBox( int aUnit, int aConvert ) const;
+
+ /**
+ * Function GetBodyBoundingBox
+ * @return the part bounding box ( in user coordinates ) without fields
+ * @param aUnit = unit selection = 0, or 1..n
+ * @param aConvert = 0, 1 or 2
+ * If aUnit == 0, unit is not used
+ * if aConvert == 0 Convert is non used
+ * Fields are not taken in account
+ **/
+ const EDA_RECT GetBodyBoundingBox( int aUnit, int aConvert ) const;
+
+ /**
+ * Function SaveDateAndTime
+ * write the date and time of part to \a aFile in the format:
+ * "Ti yy/mm/jj hh:mm:ss"
+ *
+ * @param aFormatter A reference to an #OUTPUTFORMATTER object containing the
+ * output format to write to.
+ * @return True if the date and time were successfully written to \a aFormatter.
+ */
+ bool SaveDateAndTime( OUTPUTFORMATTER& aFormatter );
+
+ bool LoadDateAndTime( char* aLine );
+
+ /**
+ * Function Save
+ * writes the data structures out to \a aFormatter in the part library "*.lib"
+ * format.
+ *
+ * @param aFormatter A reference to an OUTPUTFORMATTER to write to.
+ * @return True if success writing else false.
+ */
+ bool Save( OUTPUTFORMATTER& aFormatter );
+
+ /**
+ * Load part definition from \a aReader.
+ *
+ * @param aReader A LINE_READER object to load file from.
+ * @param aErrorMsg - Description of error on load failure.
+ * @return True if the load was successful, false if there was an error.
+ */
+ bool Load( LINE_READER& aReader, wxString& aErrorMsg );
+ bool LoadField( LINE_READER& aReader, wxString& aErrorMsg );
+ bool LoadDrawEntries( LINE_READER& aReader, wxString& aErrorMsg );
+ bool LoadAliases( char* aLine, wxString& aErrorMsg );
+ bool LoadFootprints( LINE_READER& aReader, wxString& aErrorMsg );
+
+ bool IsPower() const { return m_options == ENTRY_POWER; }
+ bool IsNormal() const { return m_options == ENTRY_NORMAL; }
+
+ void SetPower() { m_options = ENTRY_POWER; }
+ void SetNormal() { m_options = ENTRY_NORMAL; }
+
+ void LockUnits( bool aLockUnits ) { m_unitsLocked = aLockUnits; }
+ bool UnitsLocked() const { return m_unitsLocked; }
+
+ /**
+ * Function SetFields
+ * overwrites all the existing in this part with fields supplied
+ * in \a aFieldsList. The only known caller of this function is the
+ * library part field editor, and it establishes needed behavior.
+ *
+` * @param aFieldsList is a set of fields to import, removing all previous fields.
+ */
+ void SetFields( const std::vector & aFieldsList );
+
+ /**
+ * Function GetFields
+ * returns a list of fields withing this part. The only known caller of
+ * this function is the library part field editor, and it establishes
+ * needed behavior.
+ *
+ * @param aList - List to add fields to
+ */
+ void GetFields( LIB_FIELDS& aList );
+
+ /**
+ * Function FindField
+ * finds a field within this part matching \a aFieldName and returns
+ * it or NULL if not found.
+ */
+ LIB_FIELD* FindField( const wxString& aFieldName );
+
+ /**
+ * Return pointer to the requested field.
+ *
+ * @param aId - Id of field to return.
+ * @return The field if found, otherwise NULL.
+ */
+ LIB_FIELD* GetField( int aId );
+
+ /** Return reference to the value field. */
+ LIB_FIELD& GetValueField();
+
+ /** Return reference to the reference designator field. */
+ LIB_FIELD& GetReferenceField();
+
+ /**
+ * Draw part.
+ *
+ * @param aPanel - Window to draw on. Can be NULL if not available.
+ * @param aDc - Device context to draw on.
+ * @param aOffset - Position of part.
+ * @param aMulti - unit if multiple units per part.
+ * @param aConvert - Component conversion (DeMorgan) if available.
+ * @param aDrawMode - Device context drawing mode, see wxDC.
+ * @param aColor - Color to draw part.
+ * @param aTransform - Coordinate adjustment settings.
+ * @param aShowPinText - Show pin text if true.
+ * @param aDrawFields - Draw field text if true otherwise just draw
+ * body items (useful to draw a body in schematic,
+ * because fields of schematic components replace
+ * the lib part fields).
+ * @param aOnlySelected - Draws only the body items that are selected.
+ * Used for block move redraws.
+ * @param aPinsDangling - if not NULL, this should be a pointer to
+ * vector exactly the same length as the number of pins,
+ * indicating whether each pin is dangling. If NULL, all pins
+ * will be drawn as if they were dangling.
+ */
+ void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
+ int aMulti, int aConvert, GR_DRAWMODE aDrawMode,
+ EDA_COLOR_T aColor = UNSPECIFIED_COLOR,
+ const TRANSFORM& aTransform = DefaultTransform,
+ bool aShowPinText = true, bool aDrawFields = true,
+ bool aOnlySelected = false,
+ const std::vector* aPinsDangling = NULL );
+
+ /**
+ * Plot lib part to plotter.
+ * Lib Fields not are plotted here, because this plot function
+ * is used to plot schematic items, which have they own fields
+ *
+ * @param aPlotter - Plotter object to plot to.
+ * @param aUnit - Component part to plot.
+ * @param aConvert - Component alternate body style to plot.
+ * @param aOffset - Distance to shift the plot coordinates.
+ * @param aTransform - Component plot transform matrix.
+ */
+ void Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint& aOffset,
+ const TRANSFORM& aTransform );
+
+ /**
+ * Plot Lib Fields only of the part to plotter.
+ * is used to plot the full lib part, outside the schematic
+ *
+ * @param aPlotter - Plotter object to plot to.
+ * @param aUnit - Component part to plot.
+ * @param aConvert - Component alternate body style to plot.
+ * @param aOffset - Distance to shift the plot coordinates.
+ * @param aTransform - Component plot transform matrix.
+ */
+ void PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
+ const wxPoint& aOffset, const TRANSFORM& aTransform );
+
+ /**
+ * Add a new draw \a aItem to the draw object list.
+ *
+ * @param aItem - New draw object to add to part.
+ */
+ void AddDrawItem( LIB_ITEM* aItem );
+
+ /**
+ * Remove draw \a aItem from list.
+ *
+ * @param aItem - Draw item to remove from list.
+ * @param aPanel - Panel to remove part from.
+ * @param aDc - Device context to remove part from.
+ */
+ void RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel = NULL, wxDC* aDc = NULL );
+
+ /**
+ * Return the next draw object pointer.
+ *
+ * @param aItem - Pointer to the current draw item. Setting item NULL
+ * with return the first item of type in the list.
+ * @param aType - type of searched item (filter).
+ * if TYPE_NOT_INIT search for all items types
+ * @return - The next drawing object in the list if found, otherwise NULL.
+ */
+ LIB_ITEM* GetNextDrawItem( LIB_ITEM* aItem = NULL, KICAD_T aType = TYPE_NOT_INIT );
+
+ /**
+ * Return the next pin object from the draw list.
+ *
+ * This is just a pin object specific version of GetNextDrawItem().
+ *
+ * @param aItem - Pointer to the previous pin item, or NULL to get the
+ * first pin in the draw object list.
+ * @return - The next pin object in the list if found, otherwise NULL.
+ */
+ LIB_PIN* GetNextPin( LIB_PIN* aItem = NULL )
+ {
+ return (LIB_PIN*) GetNextDrawItem( (LIB_ITEM*) aItem, LIB_PIN_T );
+ }
+
+
+ /**
+ * Return a list of pin object pointers from the draw item list.
+ *
+ * Note pin objects are owned by the draw list of the part.
+ * Deleting any of the objects will leave list in a unstable state
+ * and will likely segfault when the list is destroyed.
+ *
+ * @param aList - Pin list to place pin object pointers into.
+ * @param aUnit - Unit number of pin to add to list. Set to 0 to
+ * get pins from any part unit.
+ * @param aConvert - Convert number of pin to add to list. Set to 0 to
+ * get pins from any convert of part.
+ */
+ void GetPins( LIB_PINS& aList, int aUnit = 0, int aConvert = 0 );
+
+ /**
+ * Return pin object with the requested pin \a aNumber.
+ *
+ * @param aNumber - Number of the pin to find.
+ * @param aUnit - Unit of the part to find. Set to 0 if a specific
+ * unit number is not required.
+ * @param aConvert - Alternate body style filter (DeMorgan). Set to 0 if
+ * no alternate body style is required.
+ * @return The pin object if found. Otherwise NULL.
+ */
+ LIB_PIN* GetPin( const wxString& aNumber, int aUnit = 0, int aConvert = 0 );
+
+ /**
+ * Function PinsConflictWith
+ * returns true if this part's pins do not match another part's pins. This
+ * is used to detect whether the project cache is out of sync with the
+ * system libs.
+ *
+ * @param aOtherPart - The other library part to test
+ * @param aTestNums - Whether two pins at the same point must have the same number.
+ * @param aTestNames - Whether two pins at the same point must have the same name.
+ * @param aTestType - Whether two pins at the same point must have the same electrical type.
+ * @param aTestOrientation - Whether two pins at the same point must have the same orientation.
+ * @param aTestLength - Whether two pins at the same point must have the same length.
+ */
+ bool PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
+ bool aTestType, bool aTestOrientation, bool aTestLength );
+
+ /**
+ * Move the part \a aOffset.
+ *
+ * @param aOffset - Offset displacement.
+ */
+ void SetOffset( const wxPoint& aOffset );
+
+ /**
+ * Remove duplicate draw items from list.
+ */
+ void RemoveDuplicateDrawItems();
+
+ /**
+ * Test if part has more than one body conversion type (DeMorgan).
+ *
+ * @return True if part has more than one conversion.
+ */
+ bool HasConversion() const;
+
+ /**
+ * Clears the status flag all draw objects in this part.
+ */
+ void ClearStatus();
+
+ /**
+ * Checks all draw objects of part to see if they are with block.
+ *
+ * Use this method to mark draw objects as selected during block
+ * functions.
+ *
+ * @param aRect - The bounding rectangle to test in draw items are inside.
+ * @param aUnit - The current unit number to test against.
+ * @param aConvert - Are the draw items being selected a conversion.
+ * @param aEditPinByPin - Used to ignore pin selections when in edit pin
+ * by pin mode is enabled.
+ * @return The number of draw objects found inside the block select
+ * rectangle.
+ */
+ int SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditPinByPin );
+
+ /**
+ * Clears all the draw items marked by a block select.
+ */
+ void ClearSelectedItems();
+
+ /**
+ * Deletes the select draw items marked by a block select.
+ *
+ * The name and reference field will not be deleted. They are the
+ * minimum drawing items required for any part. Their properties
+ * can be changed but the cannot be removed.
+ */
+ void DeleteSelectedItems();
+
+ /**
+ * Move the selected draw items marked by a block select.
+ */
+ void MoveSelectedItems( const wxPoint& aOffset );
+
+ /**
+ * Make a copy of the selected draw items marked by a block select.
+ *
+ * Fields are not copied. Only part body items are copied.
+ * Copying fields would result in duplicate fields which does not
+ * make sense in this context.
+ */
+ void CopySelectedItems( const wxPoint& aOffset );
+
+ /**
+ * Horizontally (X axis) mirror selected draw items about a point.
+ *
+ * @param aCenter - Center point to mirror around.
+ */
+ void MirrorSelectedItemsH( const wxPoint& aCenter );
+
+ /**
+ * Vertically (Y axis) mirror selected draw items about a point.
+ *
+ * @param aCenter - Center point to mirror around.
+ */
+ void MirrorSelectedItemsV( const wxPoint& aCenter );
+
+ /**
+ * Rotate CCW selected draw items about a point.
+ *
+ * @param aCenter - Center point to mirror around.
+ */
+ void RotateSelectedItems( const wxPoint& aCenter );
+
+ /**
+ * Locate a draw object.
+ *
+ * @param aUnit - Unit number of draw item.
+ * @param aConvert - Body style of draw item.
+ * @param aType - Draw object type, set to 0 to search for any type.
+ * @param aPoint - Coordinate for hit testing.
+ * @return The draw object if found. Otherwise NULL.
+ */
+ LIB_ITEM* LocateDrawItem( int aUnit, int aConvert, KICAD_T aType, const wxPoint& aPoint );
+
+ /**
+ * Locate a draw object (overlaid)
+ *
+ * @param aUnit - Unit number of draw item.
+ * @param aConvert - Body style of draw item.
+ * @param aType - Draw object type, set to 0 to search for any type.
+ * @param aPoint - Coordinate for hit testing.
+ * @param aTransform = the transform matrix
+ * @return The draw object if found. Otherwise NULL.
+ */
+ LIB_ITEM* LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
+ const wxPoint& aPoint, const TRANSFORM& aTransform );
+
+ /**
+ * Return a reference to the draw item list.
+ *
+ * @return LIB_ITEMS& - Reference to the draw item object list.
+ */
+ LIB_ITEMS& GetDrawItemList() { return drawings; }
+
+ /**
+ * Set the units per part count.
+ *
+ * If the count is greater than the current count, then the all of the
+ * current draw items are duplicated for each additional part. If the
+ * count is less than the current count, all draw objects for units
+ * greater that count are removed from the part.
+ *
+ * @param count - Number of units per package.
+ */
+ void SetUnitCount( int count );
+
+ int GetUnitCount() const { return m_unitCount; }
+
+ /**
+ * Function IsMulti
+ * @return true if the part has multiple units per part.
+ * When happens, the reference has a sub reference ti identify part
+ */
+ bool IsMulti() const { return m_unitCount > 1; }
+
+ /**
+ * Function SubReference
+ * @return the sub reference for part having multiple units per part.
+ * The sub reference identify the part (or unit)
+ * @param aUnit = the part identifier ( 1 to max count)
+ * @param aAddSeparator = true (default) to prpebd the sub ref
+ * by the separator symbol (if any)
+ * Note: this is a static function.
+ */
+ static wxString SubReference( int aUnit, bool aAddSeparator = true );
+
+ // Accessors to sub ref parameters
+ static int GetSubpartIdSeparator() { return m_subpartIdSeparator; }
+
+ /** return a reference to m_subpartIdSeparator,
+ * only for read/save setting functions
+ */
+ static int* SubpartIdSeparatorPtr() { return &m_subpartIdSeparator; }
+
+ static int GetSubpartFirstId() { return m_subpartFirstId; }
+
+ /** return a reference to m_subpartFirstId, only for read/save setting functions
+ */
+ static int* SubpartFirstIdPtr() { return &m_subpartFirstId; }
+
+ /** Set the separator char between the subpart id and the reference
+ * 0 (no separator) or '.' , '-' and '_'
+ * and the ascii char value to calculate the subpart symbol id from the part number:
+ * 'A' or '1' only are allowed. (to print U1.A or U1.1)
+ * if this is a digit, a number is used as id symbol
+ * Note also if the subpart symbol is a digit, the separator cannot be null.
+ * @param aSep = the separator symbol (0 (no separator) or '.' , '-' and '_')
+ * @param aFirstId = the Id of the first part ('A' or '1')
+ */
+ static void SetSubpartIdNotation( int aSep, int aFirstId );
+
+ /**
+ * Set or clear the alternate body style (DeMorgan) for the part.
+ *
+ * If the part already has an alternate body style set and a
+ * asConvert if false, all of the existing draw items for the alternate
+ * body style are remove. If the alternate body style is not set and
+ * asConvert is true, than the base draw items are duplicated and
+ * added to the part.
+ *
+ * @param aSetConvert - Set or clear the part alternate body style.
+ */
+ void SetConversion( bool aSetConvert );
+
+ /**
+ * Set the offset in mils of the pin name text from the pin symbol.
+ *
+ * Set the offset to 0 to draw the pin name above the pin symbol.
+ *
+ * @param aOffset - The offset in mils.
+ */
+ void SetPinNameOffset( int aOffset ) { m_pinNameOffset = aOffset; }
+
+ int GetPinNameOffset() { return m_pinNameOffset; }
+
+ /**
+ * Set or clear the pin name visibility flag.
+ *
+ * @param aShow - True to make the part pin names visible.
+ */
+ void SetShowPinNames( bool aShow ) { m_showPinNames = aShow; }
+
+ bool ShowPinNames() { return m_showPinNames; }
+
+ /**
+ * Set or clear the pin number visibility flag.
+ *
+ * @param aShow - True to make the part pin numbers visible.
+ */
+ void SetShowPinNumbers( bool aShow ) { m_showPinNumbers = aShow; }
+
+ bool ShowPinNumbers() { return m_showPinNumbers; }
+
+ bool operator==( const LIB_PART* aPart ) const { return this == aPart; }
+
+#if defined(DEBUG)
+ void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
+#endif
+};
+
+#endif // CLASS_LIBENTRY_H
diff --git a/eeschema/class_library.cpp b/eeschema/class_library.cpp
new file mode 100644
index 00000000..93a5331e
--- /dev/null
+++ b/eeschema/class_library.cpp
@@ -0,0 +1,1208 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2015 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_library.cpp
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+#define duplicate_name_msg \
+ _( "Library '%s' has duplicate entry name '%s'.\n" \
+ "This may cause some unexpected behavior when loading components into a schematic." )
+
+
+PART_LIB::PART_LIB( int aType, const wxString& aFileName ) :
+ // start @ != 0 so each additional library added
+ // is immediately detectable, zero would not be.
+ m_mod_hash( PART_LIBS::s_modify_generation )
+{
+ type = aType;
+ isModified = false;
+ timeStamp = 0;
+ isCache = false;
+ timeStamp = wxDateTime::Now();
+ versionMajor = 0; // Will be updated after reading the lib file
+ versionMinor = 0; // Will be updated after reading the lib file
+
+ fileName = aFileName;
+
+ if( !fileName.IsOk() )
+ fileName = wxT( "unnamed.lib" );
+}
+
+
+PART_LIB::~PART_LIB()
+{
+ // When the library is destroyed, all of the alias objects on the heap should be deleted.
+ for( LIB_ALIAS_MAP::iterator it = m_amap.begin(); it != m_amap.end(); ++it )
+ {
+ wxLogTrace( traceSchLibMem, wxT( "Removing alias %s from library %s." ),
+ GetChars( it->second->GetName() ), GetChars( GetLogicalName() ) );
+ LIB_PART* part = it->second->GetPart();
+ LIB_ALIAS* alias = it->second;
+ delete alias;
+
+ // When the last alias of a part is destroyed, the part is no longer required and it
+ // too is destroyed.
+ if( part && part->GetAliasCount() == 0 )
+ delete part;
+ }
+
+ m_amap.clear();
+}
+
+
+void PART_LIB::GetEntryNames( wxArrayString& aNames, bool aSort, bool aMakeUpperCase )
+{
+ for( LIB_ALIAS_MAP::iterator it = m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ if( aMakeUpperCase )
+ {
+ wxString tmp = (*it).first;
+ tmp.MakeUpper();
+ aNames.Add( tmp );
+ }
+ else
+ {
+ aNames.Add( (*it).first );
+ }
+ }
+
+ if( aSort )
+ aNames.Sort();
+}
+
+
+void PART_LIB::GetEntryTypePowerNames( wxArrayString& aNames, bool aSort, bool aMakeUpperCase )
+{
+ for( LIB_ALIAS_MAP::iterator it = m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ LIB_ALIAS* alias = it->second;
+ LIB_PART* root = alias->GetPart();
+
+ if( !root || !root->IsPower() )
+ continue;
+
+ if( aMakeUpperCase )
+ {
+ wxString tmp = (*it).first;
+ tmp.MakeUpper();
+ aNames.Add( tmp );
+ }
+ else
+ {
+ aNames.Add( (*it).first );
+ }
+ }
+
+ if( aSort )
+ aNames.Sort();
+}
+
+
+/**
+ * Function sortFunction
+ * simple function used as comparator to sort a std::vector&.
+ *
+ * @param aItem1 is the first comparison parameter.
+ * @param aItem2 is the second.
+ * @return bool - which item should be put first in the sorted list.
+ */
+bool sortFunction( wxArrayString aItem1, wxArrayString aItem2 )
+{
+ return( aItem1.Item( 0 ) < aItem2.Item( 0 ) );
+}
+
+
+void PART_LIB::SearchEntryNames( std::vector& aNames,
+ const wxString& aNameSearch,
+ const wxString& aKeySearch,
+ bool aSort )
+{
+ for( LIB_ALIAS_MAP::iterator it = m_amap.begin(); it != m_amap.end(); ++it )
+ {
+ if( !!aKeySearch && KeyWordOk( aKeySearch, it->second->GetKeyWords() ) )
+ {
+ wxArrayString item;
+
+ item.Add( it->first );
+ item.Add( GetLogicalName() );
+ aNames.push_back( item );
+ }
+
+ if( !aNameSearch.IsEmpty() &&
+ WildCompareString( aNameSearch, it->second->GetName(), false ) )
+ {
+ wxArrayString item;
+
+ item.Add( it->first );
+ item.Add( GetLogicalName() );
+ aNames.push_back( item );
+ }
+ }
+
+ if( aSort )
+ std::sort( aNames.begin(), aNames.end(), sortFunction );
+}
+
+
+void PART_LIB::SearchEntryNames( wxArrayString& aNames, const wxRegEx& aRe, bool aSort )
+{
+ if( !aRe.IsValid() )
+ return;
+
+ LIB_ALIAS_MAP::iterator it;
+
+ for( it = m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ if( aRe.Matches( it->second->GetKeyWords() ) )
+ aNames.Add( it->first );
+ }
+
+ if( aSort )
+ aNames.Sort();
+}
+
+
+bool PART_LIB::Conflicts( LIB_PART* aPart )
+{
+ wxCHECK_MSG( aPart != NULL, false,
+ wxT( "Cannot test NULL component for conflicts in library " ) + GetName() );
+
+ for( size_t i=0; im_aliases.size(); i++ )
+ {
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aPart->m_aliases[i]->GetName() );
+
+ if( it != m_amap.end() )
+ return true;
+ }
+
+ return false;
+}
+
+
+LIB_ALIAS* PART_LIB::FindEntry( const wxString& aName )
+{
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aName );
+
+ if( it != m_amap.end() )
+ return it->second;
+
+ return NULL;
+}
+
+
+LIB_ALIAS* PART_LIB::GetFirstEntry()
+{
+ if( m_amap.size() )
+ return m_amap.begin()->second;
+ else
+ return NULL;
+}
+
+
+LIB_PART* PART_LIB::FindPart( const wxString& aName )
+{
+#if 0 && defined(DEBUG)
+ if( !aName.Cmp( wxT( "TI_STELLARIS_BOOSTERPACK" ) ) )
+ {
+ int breakhere = 1;
+ (void) breakhere;
+ }
+#endif
+
+ if( LIB_ALIAS* alias = FindEntry( aName ) )
+ {
+ return alias->GetPart();
+ }
+
+ return NULL;
+}
+
+
+bool PART_LIB::HasPowerParts()
+{
+ // return true if at least one power part is found in lib
+ for( LIB_ALIAS_MAP::iterator it = m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ LIB_ALIAS* alias = it->second;
+ LIB_PART* root = alias->GetPart();
+
+ if( root && root->IsPower() )
+ return true;
+ }
+
+ return false;
+}
+
+
+bool PART_LIB::AddAlias( LIB_ALIAS* aAlias )
+{
+ wxASSERT( aAlias );
+
+#if defined(DEBUG) && 0
+ if( !aAlias->GetName().Cmp( wxT( "TI_STELLARIS_BOOSTERPACK" ) ) )
+ {
+ int breakhere = 1;
+ (void) breakhere;
+ }
+#endif
+
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aAlias->GetName() );
+
+ if( it != m_amap.end() )
+ {
+ wxString msg;
+
+ msg.Printf( _( "Cannot add duplicate alias '%s' to library '%s'." ),
+ GetChars( aAlias->GetName() ),
+ GetChars( fileName.GetName() ) );
+ return false;
+ }
+
+ wxString name = aAlias->GetName();
+
+ m_amap[ name ] = aAlias;
+ isModified = true;
+ ++m_mod_hash;
+
+ return true;
+}
+
+
+bool PART_LIB::AddPart( LIB_PART* aPart )
+{
+ // Conflict detection: See if already existing aliases exist,
+ // and if yes, ask user for continue or abort
+ // Special case: if the library is the library cache of the project,
+ // old aliases are always removed to avoid conflict,
+ // and user is not prompted )
+ if( Conflicts( aPart ) && !IsCache() )
+ {
+ wxFAIL_MSG( wxT( "Cannot add component <" ) + aPart->GetName() +
+ wxT( "> to library <" ) + GetName() + wxT( "> due to name conflict." ) );
+ return false;
+ }
+
+ // add a clone, not the caller's copy
+ LIB_PART* my_part = new LIB_PART( *aPart, this );
+
+ for( size_t i = 0; i < my_part->m_aliases.size(); i++ )
+ {
+ wxString aliasname = my_part->m_aliases[i]->GetName();
+
+ if( LIB_ALIAS* alias = FindAlias( aliasname ) )
+ RemoveEntry( alias );
+
+ m_amap[ aliasname ] = my_part->m_aliases[i];
+ }
+
+ isModified = true;
+ ++m_mod_hash;
+
+ return true;
+}
+
+
+LIB_ALIAS* PART_LIB::RemoveEntry( LIB_ALIAS* aEntry )
+{
+ wxCHECK_MSG( aEntry != NULL, NULL, wxT( "NULL pointer cannot be removed from library." ) );
+
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aEntry->GetName() );
+
+ if( it == m_amap.end() )
+ return NULL;
+
+ // If the entry pointer doesn't match the name it is mapped to in the library, we
+ // have done something terribly wrong.
+ wxCHECK_MSG( *it->second == aEntry, NULL,
+ wxT( "Pointer mismatch while attempting to remove entry <" ) +
+ aEntry->GetName() + wxT( "> from library <" ) + GetName() + wxT( ">." ) );
+
+ LIB_ALIAS* alias = aEntry;
+ LIB_PART* part = alias->GetPart();
+
+ alias = part->RemoveAlias( alias );
+
+ if( !alias )
+ {
+ delete part;
+
+ if( m_amap.size() > 1 )
+ {
+ LIB_ALIAS_MAP::iterator next = it;
+ next++;
+
+ if( next == m_amap.end() )
+ next = m_amap.begin();
+
+ alias = next->second;
+ }
+ }
+
+ m_amap.erase( it );
+ isModified = true;
+ ++m_mod_hash;
+ return alias;
+}
+
+
+LIB_PART* PART_LIB::ReplacePart( LIB_PART* aOldPart, LIB_PART* aNewPart )
+{
+ wxASSERT( aOldPart != NULL );
+ wxASSERT( aNewPart != NULL );
+
+ /* Remove the old root component. The component will automatically be deleted
+ * when all it's aliases are deleted. Do not place any code that accesses
+ * aOldPart inside this loop that gets evaluated after the last alias is
+ * removed in RemoveEntry(). Failure to heed this warning will result in a
+ * segfault.
+ */
+ size_t i = aOldPart->m_aliases.size();
+
+ while( i > 0 )
+ {
+ i -= 1;
+ RemoveEntry( aOldPart->m_aliases[ i ] );
+ }
+
+ LIB_PART* my_part = new LIB_PART( *aNewPart, this );
+
+ // Add new aliases to library alias map.
+ for( i = 0; i < my_part->m_aliases.size(); i++ )
+ {
+ wxString aname = my_part->m_aliases[ i ]->GetName();
+ m_amap[ aname ] = my_part->m_aliases[ i ];
+ }
+
+ isModified = true;
+ ++m_mod_hash;
+ return my_part;
+}
+
+
+LIB_ALIAS* PART_LIB::GetNextEntry( const wxString& aName )
+{
+ if( m_amap.empty() )
+ return NULL;
+
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aName );
+
+ it++;
+
+ if( it == m_amap.end() )
+ it = m_amap.begin();
+
+ return it->second;
+}
+
+
+LIB_ALIAS* PART_LIB::GetPreviousEntry( const wxString& aName )
+{
+ if( m_amap.empty() )
+ return NULL;
+
+ LIB_ALIAS_MAP::iterator it = m_amap.find( aName );
+
+ if( it == m_amap.begin() )
+ it = m_amap.end();
+
+ it--;
+
+ return it->second;
+}
+
+
+bool PART_LIB::Load( wxString& aErrorMsg )
+{
+ FILE* file;
+ char* line;
+ wxString msg;
+
+ if( fileName.GetFullPath().IsEmpty() )
+ {
+ aErrorMsg = _( "The component library file name is not set." );
+ return false;
+ }
+
+ file = wxFopen( fileName.GetFullPath(), wxT( "rt" ) );
+
+ if( file == NULL )
+ {
+ aErrorMsg = _( "The file could not be opened." );
+ return false;
+ }
+
+ FILE_LINE_READER reader( file, fileName.GetFullPath() );
+
+ if( !reader.ReadLine() )
+ {
+ aErrorMsg = _( "The file is empty!" );
+ return false;
+ }
+
+ // There is no header if this is a symbol library.
+ if( type == LIBRARY_TYPE_EESCHEMA )
+ {
+ line = reader.Line();
+
+ header = FROM_UTF8( line );
+
+ wxStringTokenizer tkn( header );
+
+ /*
+ * The file header (first line) in library versions 2.0 and lower
+ * apparently started with EESchema-LIB. Sometime after 2.0, it
+ * was changed to EESchema-LIBRARY. Therefore, the test for
+ * EESchema-LIB will work in both cases. Don't change this unless
+ * backwards compatibility is no longer required.
+ */
+ if( !tkn.HasMoreTokens()
+ || !tkn.GetNextToken().Upper().StartsWith(wxT( "EESCHEMA-LIB" ) ) )
+ {
+ aErrorMsg = _( "The file is NOT an Eeschema library!" );
+ return false;
+ }
+
+ if( !tkn.HasMoreTokens() )
+ {
+ aErrorMsg = _( "The file header is missing version and time stamp information." );
+ return false;
+ }
+
+ if( tkn.GetNextToken() != wxT( "Version" ) || !tkn.HasMoreTokens() )
+ {
+ aErrorMsg = wxT( "The file header version information is invalid." );
+ return false;
+ }
+
+ long major, minor;
+ wxStringTokenizer vers( tkn.GetNextToken(), wxT( "." ) );
+
+ if( !vers.HasMoreTokens() || !vers.GetNextToken().ToLong( &major )
+ || major < 1L || !vers.HasMoreTokens()
+ || !vers.GetNextToken().ToLong( & minor ) || minor < 0L
+ || minor > 99 )
+ {
+#if 0 // Note for developers:
+ // Not sure this warning is very useful: old designs *must* be always loadable
+ wxLogWarning( wxT(
+ "The component library '%s' header version "
+ "number is invalid.\n\nIn future versions of Eeschema this library may not "
+ "load correctly. To resolve this problem open the library in the library "
+ "editor and save it. If this library is the project cache library, save "
+ "the current schematic." ),
+ GetChars( GetName() ) );
+#endif
+ }
+ else
+ {
+ versionMajor = (int) major;
+ versionMinor = (int) minor;
+ }
+ }
+
+ while( reader.ReadLine() )
+ {
+ line = reader.Line();
+
+ if( type == LIBRARY_TYPE_EESCHEMA && strnicmp( line, "$HEADER", 7 ) == 0 )
+ {
+ if( !LoadHeader( reader ) )
+ {
+ aErrorMsg = _( "An error occurred attempting to read the header." );
+ return false;
+ }
+
+ continue;
+ }
+
+ if( strnicmp( line, "DEF", 3 ) == 0 )
+ {
+ // Read one DEF/ENDDEF part entry from library:
+ LIB_PART* part = new LIB_PART( wxEmptyString, this );
+
+ if( part->Load( reader, msg ) )
+ {
+ // Check for duplicate entry names and warn the user about
+ // the potential conflict.
+ if( FindEntry( part->GetName() ) != NULL )
+ {
+ wxString msg = duplicate_name_msg;
+
+ wxLogWarning( msg,
+ GetChars( fileName.GetName() ),
+ GetChars( part->GetName() ) );
+ }
+
+ LoadAliases( part );
+ }
+ else
+ {
+ wxLogWarning( _( "Library '%s' component load error %s." ),
+ GetChars( fileName.GetName() ),
+ GetChars( msg ) );
+ msg.Clear();
+ delete part;
+ }
+ }
+ }
+
+ ++m_mod_hash;
+
+ return true;
+}
+
+
+void PART_LIB::LoadAliases( LIB_PART* aPart )
+{
+ wxCHECK_RET( aPart, wxT( "Cannot load aliases of NULL part. Bad programmer!" ) );
+
+ for( size_t i = 0; i < aPart->m_aliases.size(); i++ )
+ {
+ if( FindEntry( aPart->m_aliases[i]->GetName() ) != NULL )
+ {
+ wxString msg = duplicate_name_msg;
+
+ wxLogError( msg,
+ GetChars( fileName.GetName() ),
+ GetChars( aPart->m_aliases[i]->GetName() ) );
+ }
+
+ wxString aname = aPart->m_aliases[i]->GetName();
+ m_amap[ aname ] = aPart->m_aliases[i];
+ }
+}
+
+
+bool PART_LIB::LoadHeader( LINE_READER& aLineReader )
+{
+ char* line, * text, * data;
+
+ while( aLineReader.ReadLine() )
+ {
+ line = (char*) aLineReader;
+
+ text = strtok( line, " \t\r\n" );
+ data = strtok( NULL, " \t\r\n" );
+
+ if( stricmp( text, "TimeStamp" ) == 0 )
+ timeStamp = atol( data );
+
+ if( stricmp( text, "$ENDHEADER" ) == 0 )
+ return true;
+ }
+
+ return false;
+}
+
+
+bool PART_LIB::LoadDocs( wxString& aErrorMsg )
+{
+ int lineNumber = 0;
+ char line[8000], * name, * text;
+ LIB_ALIAS* entry;
+ FILE* file;
+ wxFileName fn = fileName;
+
+ fn.SetExt( DOC_EXT );
+
+ file = wxFopen( fn.GetFullPath(), wxT( "rt" ) );
+
+ if( file == NULL )
+ {
+ aErrorMsg.Printf( _( "Could not open component document library file '%s'." ),
+ GetChars( fn.GetFullPath() ) );
+ return false;
+ }
+
+ if( GetLine( file, line, &lineNumber, sizeof(line) ) == NULL )
+ {
+ aErrorMsg.Printf( _( "Part document library file '%s' is empty." ),
+ GetChars( fn.GetFullPath() ) );
+ fclose( file );
+ return false;
+ }
+
+ if( strnicmp( line, DOCFILE_IDENT, 10 ) != 0 )
+ {
+ aErrorMsg.Printf( _( "File '%s' is not a valid component library document file." ),
+ GetChars( fn.GetFullPath() ) );
+ fclose( file );
+ return false;
+ }
+
+ while( GetLine( file, line, &lineNumber, sizeof(line) ) )
+ {
+ if( strncmp( line, "$CMP", 4 ) != 0 )
+ {
+ aErrorMsg.Printf( wxT( "$CMP command expected in line %d, aborted." ), lineNumber );
+ fclose( file );
+ return false;
+ }
+
+ // Read one $CMP/$ENDCMP part entry from library:
+ name = strtok( line + 5, "\n\r" );
+
+ wxString cmpname = FROM_UTF8( name );
+
+ entry = FindEntry( cmpname );
+
+ while( GetLine( file, line, &lineNumber, sizeof(line) ) )
+ {
+ if( strncmp( line, "$ENDCMP", 7 ) == 0 )
+ break;
+
+ text = strtok( line + 2, "\n\r" );
+
+ if( entry )
+ {
+ switch( line[0] )
+ {
+ case 'D':
+ entry->SetDescription( FROM_UTF8( text ) );
+ break;
+
+ case 'K':
+ entry->SetKeyWords( FROM_UTF8( text ) );
+ break;
+
+ case 'F':
+ entry->SetDocFileName( FROM_UTF8( text ) );
+ break;
+ }
+ }
+ }
+ }
+
+ fclose( file );
+ return true;
+}
+
+
+bool PART_LIB::Save( OUTPUTFORMATTER& aFormatter )
+{
+ if( isModified )
+ {
+ timeStamp = GetNewTimeStamp();
+ isModified = false;
+ }
+
+ bool success = true;
+
+ try
+ {
+ SaveHeader( aFormatter );
+
+ for( LIB_ALIAS_MAP::iterator it=m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ if( !it->second->IsRoot() )
+ continue;
+
+ it->second->GetPart()->Save( aFormatter );
+ }
+
+ aFormatter.Print( 0, "#\n#End Library\n" );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ success = false;
+ }
+
+ return success;
+}
+
+
+bool PART_LIB::SaveDocs( OUTPUTFORMATTER& aFormatter )
+{
+ bool success = true;
+
+ try
+ {
+ aFormatter.Print( 0, "%s\n", DOCFILE_IDENT );
+
+ for( LIB_ALIAS_MAP::iterator it=m_amap.begin(); it!=m_amap.end(); it++ )
+ {
+ if( !it->second->SaveDoc( aFormatter ) )
+ success = false;
+ }
+
+ aFormatter.Print( 0, "#\n#End Doc Library\n" );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ success = false;
+ }
+
+ return success;
+}
+
+
+bool PART_LIB::SaveHeader( OUTPUTFORMATTER& aFormatter )
+{
+ aFormatter.Print( 0, "%s %d.%d\n", LIBFILE_IDENT,
+ LIB_VERSION_MAJOR, LIB_VERSION_MINOR );
+
+ aFormatter.Print( 0, "#encoding utf-8\n");
+
+#if 0
+ aFormatter.Print( 0, "$HEADER\n" );
+ aFormatter.Print( 0, "TimeStamp %8.8lX\n", m_TimeStamp );
+ aFormatter.Print( 0, "Parts %d\n", m_amap.size() );
+ aFormatter.Print( 0, "$ENDHEADER\n" ) != 1 );
+#endif
+
+ return true;
+}
+
+
+PART_LIB* PART_LIB::LoadLibrary( const wxString& aFileName ) throw( IO_ERROR, boost::bad_pointer )
+{
+ std::auto_ptr lib( new PART_LIB( LIBRARY_TYPE_EESCHEMA, aFileName ) );
+
+ wxBusyCursor ShowWait;
+
+ wxString errorMsg;
+
+ if( !lib->Load( errorMsg ) )
+ THROW_IO_ERROR( errorMsg );
+
+ if( USE_OLD_DOC_FILE_FORMAT( lib->versionMajor, lib->versionMinor ) )
+ {
+#if 1
+ // not fatal if error here.
+ lib->LoadDocs( errorMsg );
+#else
+ if( !lib->LoadDocs( errorMsg ) )
+ THROW_IO_ERROR( errorMsg );
+#endif
+ }
+
+ PART_LIB* ret = lib.release();
+
+ return ret;
+}
+
+
+PART_LIB* PART_LIBS::AddLibrary( const wxString& aFileName ) throw( IO_ERROR, boost::bad_pointer )
+{
+ PART_LIB* lib;
+
+#if 1
+ wxFileName fn = aFileName;
+ // Don't reload the library if it is already loaded.
+ lib = FindLibrary( fn.GetName() );
+ if( lib )
+ return lib;
+#endif
+
+ lib = PART_LIB::LoadLibrary( aFileName );
+
+ push_back( lib );
+
+ return lib;
+}
+
+
+PART_LIB* PART_LIBS::AddLibrary( const wxString& aFileName, PART_LIBS::iterator& aIterator )
+ throw( IO_ERROR, boost::bad_pointer )
+{
+#if 1
+ // Don't reload the library if it is already loaded.
+ wxFileName fn( aFileName );
+ PART_LIB* lib = FindLibrary( fn.GetName() );
+
+ if( lib )
+ return lib;
+#endif
+
+ lib = PART_LIB::LoadLibrary( aFileName );
+
+ if( aIterator >= begin() && aIterator < end() )
+ insert( aIterator, lib );
+ else
+ push_back( lib );
+
+ return lib;
+}
+
+
+void PART_LIBS::RemoveLibrary( const wxString& aName )
+{
+ if( aName.IsEmpty() )
+ return;
+
+ for( PART_LIBS::iterator it = begin(); it < end(); ++it )
+ {
+ if( it->GetName().CmpNoCase( aName ) == 0 )
+ {
+ erase( it );
+ return;
+ }
+ }
+}
+
+
+PART_LIB* PART_LIBS::FindLibrary( const wxString& aName )
+{
+ for( PART_LIBS::iterator it = begin(); it!=end(); ++it )
+ {
+ if( it->GetName() == aName )
+ return &*it;
+ }
+
+ return NULL;
+}
+
+
+wxArrayString PART_LIBS::GetLibraryNames( bool aSorted )
+{
+ wxArrayString cacheNames;
+ wxArrayString names;
+
+ BOOST_FOREACH( PART_LIB& lib, *this )
+ {
+ if( lib.IsCache() && aSorted )
+ cacheNames.Add( lib.GetName() );
+ else
+ names.Add( lib.GetName() );
+ }
+
+ // Even sorted, the cache library is always at the end of the list.
+ if( aSorted )
+ names.Sort();
+
+ for( unsigned int i = 0; i& aEntries )
+{
+ BOOST_FOREACH( PART_LIB& lib, *this )
+ {
+ LIB_ALIAS* entry = lib.FindEntry( aEntryName );
+
+ if( entry )
+ aEntries.push_back( entry );
+ }
+}
+
+/* searches all libraries in the list for an entry, using a case insensitive comparison.
+ * Used to find an entry, when the normal (case sensitive) search fails.
+ */
+void PART_LIBS::FindLibraryNearEntries( std::vector& aCandidates,
+ const wxString& aEntryName,
+ const wxString& aLibraryName )
+{
+ BOOST_FOREACH( PART_LIB& lib, *this )
+ {
+ if( !!aLibraryName && lib.GetName() != aLibraryName )
+ continue;
+
+ LIB_ALIAS* entry = lib.GetFirstEntry();
+
+ if( ! entry )
+ continue;
+
+ wxString first_entry_name = entry->GetName();
+ wxString entry_name = first_entry_name;
+
+ for( ;; )
+ {
+ if( entry_name.CmpNoCase( aEntryName ) == 0 )
+ aCandidates.push_back( entry );
+
+ entry = lib.GetNextEntry( entry_name );
+ entry_name = entry->GetName();
+
+ if( first_entry_name == entry_name )
+ break;
+ }
+ }
+}
+
+
+int PART_LIBS::s_modify_generation = 1; // starts at 1 and goes up
+
+
+int PART_LIBS::GetModifyHash()
+{
+ int hash = 0;
+
+ for( PART_LIBS::const_iterator it = begin(); it != end(); ++it )
+ {
+ hash += it->m_mod_hash;
+ }
+
+ return hash;
+}
+
+
+/*
+void PART_LIBS::RemoveCacheLibrary()
+{
+ for( PART_LIBS::iterator it = begin(); it < end(); ++it )
+ {
+ if( it->IsCache() )
+ erase( it-- );
+ }
+}
+*/
+
+
+void PART_LIBS::LibNamesAndPaths( PROJECT* aProject, bool doSave,
+ wxString* aPaths, wxArrayString* aNames )
+ throw( IO_ERROR, boost::bad_pointer )
+{
+ wxString pro = aProject->GetProjectFullName();
+
+ PARAM_CFG_ARRAY ca;
+
+ if( aPaths )
+ ca.push_back( new PARAM_CFG_FILENAME( wxT( "LibDir" ), aPaths ) );
+
+ if( aNames )
+ ca.push_back( new PARAM_CFG_LIBNAME_LIST( wxT( "LibName" ), aNames, GROUP_SCH_LIBS ) );
+
+ if( doSave )
+ {
+ aProject->ConfigSave( Kiface().KifaceSearch(), GROUP_SCH, ca );
+
+ /*
+ {
+ wxString msg = wxString::Format( _(
+ "Unable save project's '%s' file" ),
+ GetChars( pro )
+ );
+ THROW_IO_ERROR( msg );
+ }
+ */
+ }
+ else
+ {
+ if( !aProject->ConfigLoad( Kiface().KifaceSearch(), GROUP_SCH, ca ) )
+ {
+ wxString msg = wxString::Format( _(
+ "Unable to load project's '%s' file" ),
+ GetChars( pro )
+ );
+ THROW_IO_ERROR( msg );
+ }
+ }
+}
+
+
+const wxString PART_LIBS::CacheName( const wxString& aFullProjectFilename )
+{
+ /* until apr 2009 the project cache lib was named: .cache.lib,
+ * and after: -cache.lib. So if the -cache.lib is not found,
+ * the old file will be renamed and returned.
+ */
+ wxFileName new_name = aFullProjectFilename;
+
+ new_name.SetName( new_name.GetName() + wxT( "-cache" ) );
+ new_name.SetExt( SchematicLibraryFileExtension );
+
+ if( new_name.FileExists() )
+ return new_name.GetFullPath();
+ else
+ {
+ wxFileName old_name = aFullProjectFilename;
+ old_name.SetExt( wxT( "cache.lib" ) );
+
+ if( old_name.FileExists() )
+ {
+ wxRenameFile( old_name.GetFullPath(), new_name.GetFullPath() );
+ return new_name.GetFullPath();
+ }
+ }
+ return wxEmptyString;
+}
+
+
+void PART_LIBS::LoadAllLibraries( PROJECT* aProject ) throw( IO_ERROR, boost::bad_pointer )
+{
+ wxFileName fn;
+ wxString filename;
+ wxString libs_not_found;
+ SEARCH_STACK* lib_search = aProject->SchSearchS();
+
+#if defined(DEBUG) && 1
+ lib_search->Show( __func__ );
+#endif
+
+ wxArrayString lib_names;
+
+ LibNamesAndPaths( aProject, false, NULL, &lib_names );
+
+ // If the list is empty, force loading the standard power symbol library.
+ if( !lib_names.GetCount() )
+ lib_names.Add( wxT( "power" ) );
+
+ wxASSERT( !size() ); // expect to load into "this" empty container.
+
+ for( unsigned i = 0; i < lib_names.GetCount(); ++i )
+ {
+ fn.Clear();
+ fn.SetName( lib_names[i] );
+ fn.SetExt( SchematicLibraryFileExtension );
+
+ // Skip if the file name is not valid..
+ if( !fn.IsOk() )
+ continue;
+
+ if( !fn.FileExists() )
+ {
+ filename = lib_search->FindValidPath( fn.GetFullPath() );
+
+ if( !filename )
+ {
+ libs_not_found += fn.GetName();
+ libs_not_found += wxT( '\n' );
+ continue;
+ }
+ }
+ else
+ {
+ filename = fn.GetFullPath();
+ }
+
+ try
+ {
+ AddLibrary( filename );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ wxString msg = wxString::Format( _(
+ "Part library '%s' failed to load. Error:\n"
+ "%s" ),
+ GetChars( filename ),
+ GetChars( ioe.errorText )
+ );
+
+ THROW_IO_ERROR( msg );
+ }
+ }
+
+ // add the special cache library.
+ wxString cache_name = CacheName( aProject->GetProjectFullName() );
+ PART_LIB* cache_lib;
+
+ if( !!cache_name )
+ {
+ try
+ {
+ cache_lib = AddLibrary( cache_name );
+ if( cache_lib )
+ cache_lib->SetCache();
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ wxString msg = wxString::Format( _(
+ "Part library '%s' failed to load.\nError: %s" ),
+ GetChars( cache_name ),
+ GetChars( ioe.errorText )
+ );
+
+ THROW_IO_ERROR( msg );
+ }
+ }
+
+ // Print the libraries not found
+ if( !!libs_not_found )
+ {
+ // Use a different exception type so catch()er can route to proper use
+ // of the HTML_MESSAGE_BOX.
+ THROW_PARSE_ERROR( wxEmptyString, UTF8( __func__ ),
+ UTF8( libs_not_found ), 0, 0 );
+ }
+
+#if defined(DEBUG) && 1
+ printf( "%s: lib_names:\n", __func__ );
+
+ for( PART_LIBS::const_iterator it = begin(); it < end(); ++it )
+ printf( " %s\n", TO_UTF8( it->GetName() ) );
+#endif
+}
diff --git a/eeschema/class_library.h b/eeschema/class_library.h
new file mode 100644
index 00000000..37bf0ddd
--- /dev/null
+++ b/eeschema/class_library.h
@@ -0,0 +1,670 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2008-2011 Wayne Stambaugh
+ * Copyright (C) 2004-2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_library.h
+ * @brief Definition for part library class.
+ */
+
+#ifndef CLASS_LIBRARY_H
+#define CLASS_LIBRARY_H
+
+#include
+
+#include
+
+#include
+
+class LINE_READER;
+class OUTPUTFORMATTER;
+
+
+/*
+ * Part Library version and file header macros.
+ */
+#define LIB_VERSION_MAJOR 2
+#define LIB_VERSION_MINOR 3
+
+/* Must be the first line of part library (.lib) files. */
+#define LIBFILE_IDENT "EESchema-LIBRARY Version"
+
+#define LIB_VERSION( major, minor ) ( major * 100 + minor )
+
+#define IS_LIB_CURRENT_VERSION( major, minor ) \
+ ( \
+ LIB_VERSION( major1, minor1 ) == \
+ LIB_VERSION( LIB_VERSION_MAJOR, LIB_VERSION_MINOR) \
+ )
+
+/*
+ * Library versions 2.3 and lower use the old separate library (.lib) and
+ * document (.dcm) files. Part libraries after 2.3 merged the library
+ * and document files into a single library file. This macro checks if the
+ * library version supports the old format
+ */
+#define USE_OLD_DOC_FILE_FORMAT( major, minor ) \
+ ( LIB_VERSION( major, minor ) <= LIB_VERSION( 2, 3 ) )
+
+/* Must be the first line of part library document (.dcm) files. */
+#define DOCFILE_IDENT "EESchema-DOCLIB Version 2.0"
+
+#define DOC_EXT wxT( "dcm" )
+
+// Helper class to filter a list of libraries, and/or a list of PART_LIB
+// in dialogs
+class SCHLIB_FILTER
+{
+ wxArrayString m_allowedLibs; ///< a list of lib names to list some libraries
+ ///< if empty: no filter
+ bool m_filterPowerParts; ///< true to filter (show only) power parts
+ bool m_forceLoad; // When true, load a part lib from the lib
+ // which is given in m_allowedLibs[0]
+
+public:
+ SCHLIB_FILTER()
+ {
+ m_filterPowerParts = false;
+ m_forceLoad = false;
+ }
+
+ /**
+ * add a lib name to the allowed libraries
+ */
+ void AddLib( const wxString& aLibName )
+ {
+ m_allowedLibs.Add( aLibName );
+ m_forceLoad = false;
+ }
+
+
+ /**
+ * add a lib name to the allowed libraries
+ */
+ void LoadFrom( const wxString& aLibName )
+ {
+ m_allowedLibs.Clear();
+ m_allowedLibs.Add( aLibName );
+ m_forceLoad = true;
+ }
+
+ /**
+ * Clear the allowed libraries list (allows all libs)
+ */
+ void ClearLibList()
+ {
+ m_allowedLibs.Clear();
+ m_forceLoad = false;
+ }
+
+ /**
+ * set the filtering of power parts
+ */
+ void FilterPowerParts( bool aFilterEnable )
+ {
+ m_filterPowerParts = aFilterEnable;
+ }
+
+ // Accessors
+
+ /**
+ * Function GetFilterPowerParts
+ * @return true if the filtering of power parts is on
+ */
+ bool GetFilterPowerParts() const { return m_filterPowerParts; }
+
+
+ /**
+ * Function GetAllowedLibList
+ * @return am wxArrayString of the names of allowed libs
+ */
+ const wxArrayString& GetAllowedLibList() const { return m_allowedLibs; }
+
+ /**
+ * Function GetLibSource
+ * @return the name of the lib to use to load a part, or an a emty string
+ * Useful to load (in lib editor or lib viewer) a part from a given library
+ */
+ const wxString& GetLibSource() const
+ {
+ static wxString dummy;
+
+ if( m_forceLoad && m_allowedLibs.GetCount() > 0 )
+ return m_allowedLibs[0];
+ else
+ return dummy;
+ }
+};
+
+
+/* Helpers for creating a list of part libraries. */
+class PART_LIB;
+class wxRegEx;
+
+/**
+ * LIB_ALIAS map sorting.
+ */
+struct AliasMapSort
+{
+ bool operator() ( const wxString& aItem1, const wxString& aItem2 ) const
+ {
+ return Cmp_KEEPCASE( aItem1, aItem2 ) < 0;
+ }
+};
+
+/// Alias map used by part library object.
+
+typedef std::map< wxString, LIB_ALIAS*, AliasMapSort > LIB_ALIAS_MAP;
+typedef std::vector< LIB_ALIAS* > LIB_ALIASES;
+typedef boost::ptr_vector< PART_LIB > PART_LIBS_BASE;
+
+
+/**
+ * Class PART_LIBS
+ * is a collection of PART_LIBs. It extends from PROJECT::_ELEM so it can be
+ * hung in the PROJECT. It does not use any UI calls, but rather simply throws
+ * an IO_ERROR when there is a problem.
+ */
+class PART_LIBS : public PART_LIBS_BASE, public PROJECT::_ELEM
+{
+public:
+
+ static int s_modify_generation; ///< helper for GetModifyHash()
+
+ PART_LIBS()
+ {
+ ++s_modify_generation;
+ }
+
+ /// Return the modification hash for all libraries. The value returned
+ /// changes on every library modification.
+ int GetModifyHash();
+
+ /**
+ * Function AddLibrary
+ * allocates and adds a part library to the library list.
+ *
+ * @param aFileName - File name object of part library.
+ * @throw IO_ERROR if there's any problem loading.
+ */
+ PART_LIB* AddLibrary( const wxString& aFileName ) throw( IO_ERROR, boost::bad_pointer );
+
+ /**
+ * Function AddLibrary
+ * inserts a part library into the library list.
+ *
+ * @param aFileName - File name object of part library.
+ * @param aIterator - Iterator to insert library in front of.
+ * @return PART_LIB* - the new PART_LIB, which remains owned by this PART_LIBS container.
+ * @throw IO_ERROR if there's any problem loading.
+ */
+ PART_LIB* AddLibrary( const wxString& aFileName, PART_LIBS::iterator& aIterator )
+ throw( IO_ERROR, boost::bad_pointer );
+
+ /**
+ * Function RemoveLibrary
+ * removes a part library from the library list.
+ *
+ * @param aName - Name of part library to remove.
+ */
+ void RemoveLibrary( const wxString& aName );
+
+ void RemoveAllLibraries() { clear(); }
+
+ /**
+ * Function LoadAllLibraries
+ * loads all of the project's libraries into this container, which should
+ * be cleared before calling it.
+ */
+ void LoadAllLibraries( PROJECT* aProject ) throw( IO_ERROR, boost::bad_pointer );
+
+ /**
+ * Function LibNamesAndPaths
+ * either saves or loads the names of the currently configured part libraries
+ * (without paths).
+ */
+ static void LibNamesAndPaths( PROJECT* aProject, bool doSave,
+ wxString* aPaths, wxArrayString* aNames=NULL )
+ throw( IO_ERROR, boost::bad_pointer );
+
+ /**
+ * Function cacheName
+ * returns the name of the cache library after potentially fixing it from
+ * an older naming scheme. That is, the old file is renamed if needed.
+ * @param aFullProjectFilename - the *.pro filename with absolute path.
+ */
+ static const wxString CacheName( const wxString& aFullProjectFilename );
+
+ /**
+ * Function FindLibrary
+ * finds a part library by \a aName.
+ *
+ * @param aName - Library file name without path or extension to find.
+ * @return Part library if found, otherwise NULL.
+ */
+ PART_LIB* FindLibrary( const wxString& aName );
+
+ /**
+ * Function GetLibraryNames
+ * returns the list of part library file names without path and extension.
+ *
+ * @param aSorted - Sort the list of name if true. Otherwise use the
+ * library load order.
+ * @return The list of library names.
+ */
+ wxArrayString GetLibraryNames( bool aSorted = true );
+
+ /**
+ * Function FindLibPart
+ * searches all libraries in the list for a part.
+ *
+ * A part object will always be returned. If the entry found
+ * is an alias. The root part will be found and returned.
+ *
+ * @param aPartName - Name of part to search for.
+ * @param aLibraryName - Name of the library to search for part.
+ * @return LIB_PART* - The part object if found, otherwise NULL.
+ */
+ LIB_PART* FindLibPart( const wxString& aPartName, const wxString& aLibraryName = wxEmptyString );
+
+ /**
+ * Function FindLibraryEntry
+ * searches all libraries in the list for an entry.
+ *
+ * The object can be either a part or an alias.
+ *
+ * @param aEntryName - Name of entry to search for (case sensitive).
+ * @param aLibraryName - Name of the library to search.
+ * @return The entry object if found, otherwise NULL.
+ */
+ LIB_ALIAS* FindLibraryEntry( const wxString& aEntryName,
+ const wxString& aLibraryName = wxEmptyString );
+
+ /**
+ * Function FindLibraryEntries
+ * searches all libraries in the list for an entry, returns all matches.
+ *
+ * @param aEntryName - Name of entry to search for (case sensitive).
+ * @param aEntries - a std::vector to store entries
+ */
+ void FindLibraryEntries( const wxString& aEntryName, std::vector& aEntries );
+
+ /**
+ * Function FindLibraryNearEntries
+ * Searches all libraries in the list for an entry, using a case insensitive comparison.
+ * Helper function used in dialog to find all candidates.
+ * During a long time, eeschema was using a case insensitive search.
+ * Therefore, for old schematics (<= 2013), or libs, for some components,
+ * the chip name (name of alias in lib) can be broken.
+ * This function can be used to display a list of candidates, in component properties dialog.
+ *
+ * @param aEntryName - Name of entries to search for (case insensitive).
+ * @param aLibraryName - Name of the library to search.
+ * @param aCandidates - a std::vector to store candidates
+ */
+ void FindLibraryNearEntries( std::vector& aCandidates, const wxString& aEntryName,
+ const wxString& aLibraryName = wxEmptyString );
+
+ /**
+ * Function RemoveCacheLibrary
+ * removes all cache libraries from library list.
+ */
+ //void RemoveCacheLibrary();
+
+ int GetLibraryCount() { return size(); }
+
+};
+
+
+/**
+ * Class PART_LIB
+ * is used to load, save, search, and otherwise manipulate
+ * part library files.
+ */
+class PART_LIB
+{
+ int type; ///< Library type indicator.
+ wxFileName fileName; ///< Library file name.
+ wxDateTime timeStamp; ///< Library save time and date.
+ int versionMajor; ///< Library major version number.
+ int versionMinor; ///< Library minor version number.
+ bool isCache; /**< False for the "standard" libraries,
+ True for the library cache */
+ wxString header; ///< first line of loaded library.
+ bool isModified; ///< Library modification status.
+ LIB_ALIAS_MAP m_amap; ///< Map of alias objects associated with the library.
+ int m_mod_hash; ///< incremented each time library is changed.
+
+ friend class LIB_PART;
+ friend class PART_LIBS;
+
+public:
+ PART_LIB( int aType, const wxString& aFileName );
+ ~PART_LIB();
+
+ /**
+ * Function Save
+ * writes library to \a aFormatter.
+ *
+ * @param aFormatter An #OUTPUTFORMATTER object to write the library to.
+ * @return True if success writing to \a aFormatter.
+ */
+ bool Save( OUTPUTFORMATTER& aFormatter );
+
+ /**
+ * Function SaveDocs
+ * write the library document information to \a aFormatter.
+ *
+ * @param aFormatter An #OUTPUTFORMATTER object to write the library documentation to.
+ * @return True if success writing to \a aFormatter.
+ */
+ bool SaveDocs( OUTPUTFORMATTER& aFormatter );
+
+ /**
+ * Load library from file.
+ *
+ * @param aErrorMsg - Error message if load fails.
+ * @return True if load was successful otherwise false.
+ */
+ bool Load( wxString& aErrorMsg );
+
+ bool LoadDocs( wxString& aErrorMsg );
+
+private:
+ bool SaveHeader( OUTPUTFORMATTER& aFormatter );
+
+ bool LoadHeader( LINE_READER& aLineReader );
+ void LoadAliases( LIB_PART* aPart );
+
+public:
+ /**
+ * Get library entry status.
+ *
+ * @return True if there are no entries in the library.
+ */
+ bool IsEmpty() const
+ {
+ return m_amap.empty();
+ }
+
+ /**
+ * Function GetCount
+ * returns the number of entries in the library.
+ *
+ * @return The number of part and alias entries.
+ */
+ int GetCount() const
+ {
+ return m_amap.size();
+ }
+
+ bool IsModified() const
+ {
+ return isModified;
+ }
+
+ bool IsCache() const { return isCache; }
+
+ void SetCache( void ) { isCache = true; }
+
+ /**
+ * Function IsReadOnly
+ * @return true if current user does not have write access to the library file.
+ */
+ bool IsReadOnly() const { return !fileName.IsFileWritable(); }
+
+ /**
+ * Load a string array with the names of all the entries in this library.
+ *
+ * @param aNames - String array to place entry names into.
+ * @param aSort - Sort names if true.
+ * @param aMakeUpperCase - Force entry names to upper case.
+ */
+ void GetEntryNames( wxArrayString& aNames, bool aSort = true,
+ bool aMakeUpperCase = false );
+
+ /**
+ * Load a string array with the names of entries of type POWER in this library.
+ *
+ * @param aNames - String array to place entry names into.
+ * @param aSort - Sort names if true.
+ * @param aMakeUpperCase - Force entry names to upper case.
+ */
+ void GetEntryTypePowerNames( wxArrayString& aNames, bool aSort = true,
+ bool aMakeUpperCase = false );
+
+ /**
+ * Load string array with entry names matching name and/or key word.
+ *
+ * This currently mimics the old behavior of calling KeyWordOk() and
+ * WildCompareString(). The names array will be populated with the
+ * library entry names that meat the search criteria on exit.
+ *
+ * @param aNames - String array to place entry names into.
+ * @param aNameSearch - Name wild card search criteria.
+ * @param aKeySearch - Key word search criteria.
+ * @param aSort - Sort names if true.
+ */
+ void SearchEntryNames( std::vector& aNames,
+ const wxString& aNameSearch = wxEmptyString,
+ const wxString& aKeySearch = wxEmptyString,
+ bool aSort = true );
+
+ /**
+ * Find parts in library by key word regular expression search.
+ *
+ * @param aNames - String array to place found part names into.
+ * @param aRe - Regular expression used to search part key words.
+ * @param aSort - Sort part name list.
+ */
+ void SearchEntryNames( wxArrayString& aNames, const wxRegEx& aRe, bool aSort = true );
+
+ /**
+ * Checks \a aPart for name conflict in the library.
+ *
+ * @param aPart - The part to check.
+ * @return True if a conflict exists. Otherwise false.
+ */
+ bool Conflicts( LIB_PART* aPart );
+
+ /**
+ * Find entry by name.
+ *
+ * @param aName - Name of entry, case sensitive.
+ * @return Entry if found. NULL if not found.
+ */
+ LIB_ALIAS* FindEntry( const wxString& aName );
+
+ /**
+ * Find part by \a aName.
+ *
+ * This is a helper for FindEntry so casting a LIB_ALIAS pointer to
+ * a LIB_PART pointer is not required.
+ *
+ * @param aName - Name of part, case sensitive.
+ * @return LIB_PART* - part if found, else NULL.
+ */
+ LIB_PART* FindPart( const wxString& aName );
+
+ /**
+ * Find alias by \a nName.
+ *
+ * @param aName - Name of alias, case sensitive.
+ * @return Alias if found. NULL if not found.
+ */
+ LIB_ALIAS* FindAlias( const wxString& aName )
+ {
+ return (LIB_ALIAS*) FindEntry( aName );
+ }
+
+ /**
+ * Add a new \a aAlias entry to the library.
+ *
+ * First check if a part or alias with the same name already exists
+ * in the library and add alias if no conflict occurs. Once the alias
+ * is added to the library it is owned by the library. Deleting the
+ * alias pointer will render the library unstable. Use RemoveEntry to
+ * remove the alias from the library.
+ *
+ * @param aAlias - Alias to add to library.
+ * @return True if alias added to library. False if a conflict exists.
+ */
+ bool AddAlias( LIB_ALIAS* aAlias );
+
+ /**
+ * Add \a aPart entry to library.
+ * Note a part can have an alias list,
+ * so these alias will be added in library.
+ * Conflicts can happen if aliases are already existing.
+ * User is asked to choose what alias is removed (existing, or new)
+ *
+ * @param aPart - Part to add, caller retains ownership, a clone is added.
+ * @return bool - true iff successful.
+ */
+ bool AddPart( LIB_PART* aPart );
+
+ /**
+ * Safely remove \a aEntry from the library and return the next entry.
+ *
+ * The next entry returned depends on the entry being removed. If the entry being
+ * remove also removes the part, then the next entry from the list is returned.
+ * If the entry being used only removes an alias from a part, then the next alias
+ * of the part is returned.
+ *
+ * @param aEntry - Entry to remove from library.
+ * @return The next entry in the library or NULL if the library is empty.
+ */
+ LIB_ALIAS* RemoveEntry( LIB_ALIAS* aEntry );
+
+ /**
+ * Replace an existing part entry in the library.
+ * Note a part can have an alias list,
+ * so these alias will be added in library (and previously existing alias removed)
+ * @param aOldPart - The part to replace.
+ * @param aNewPart - The new part.
+ */
+ LIB_PART* ReplacePart( LIB_PART* aOldPart, LIB_PART* aNewPart );
+
+ /**
+ * Return the first entry in the library.
+ *
+ * @return The first entry or NULL if the library has no entries.
+ */
+ LIB_ALIAS* GetFirstEntry();
+
+ /**
+ * Find next library entry by \a aName.
+ *
+ * If the name of the entry is the last entry in the library, the first
+ * entry in the list is returned.
+ *
+ * @param aName - Name of current entry.
+ * @return Next entry if entry name is found. Otherwise NULL.
+ */
+ LIB_ALIAS* GetNextEntry( const wxString& aName );
+
+ /**
+ * Find previous library entry by \a aName.
+ *
+ * If the name of the entry is the first entry in the library, the last
+ * entry in the list is returned.
+ *
+ * @param aName - Name of current entry.
+ * @return Previous entry if entry name is found, otherwise NULL.
+ */
+ LIB_ALIAS* GetPreviousEntry( const wxString& aName );
+
+ /**
+ * Return the file name without path or extension.
+ *
+ * @return Name of library file.
+ */
+ const wxString GetName() const { return fileName.GetName(); }
+
+ /**
+ * Function GetFullFileName
+ * returns the full file library name with path and extension.
+ *
+ * @return wxString - Full library file name with path and extension.
+ */
+ wxString GetFullFileName() { return fileName.GetFullPath(); }
+
+ /**
+ * Function GetLogicalName
+ * returns the logical name of the library.
+ * @return wxString - The logical name of this library.
+ */
+ const wxString GetLogicalName()
+ {
+ /* for now is the filename without path or extension.
+
+ Technically the library should not know its logical name!
+ This will eventually come out of a pair of lookup tables using a
+ reverse lookup using the full name or library pointer as a key.
+ Search will be by project lookup table and then user lookup table if
+ not found.
+ */
+ return fileName.GetName();
+ }
+
+
+ /**
+ * Function SetFileName
+ * sets the part library file name.
+ *
+ * @param aFileName - New library file name.
+ */
+ void SetFileName( const wxString& aFileName )
+ {
+ if( aFileName != fileName.GetFullName() )
+ fileName = aFileName;
+ }
+
+ /**
+ * Function LoadLibrary
+ * allocates and loads a part library file.
+ *
+ * @param aFileName - File name of the part library to load.
+ * @return PART_LIB* - the allocated and loaded PART_LIB, which is owned by
+ * the caller.
+ * @throw IO_ERROR if there's any problem loading the library.
+ */
+ static PART_LIB* LoadLibrary( const wxString& aFileName ) throw( IO_ERROR, boost::bad_pointer );
+
+ /**
+ * Function HasPowerParts
+ * @return true if at least one power part is found in lib
+ * Useful to select or list only libs containing power parts
+ */
+ bool HasPowerParts();
+};
+
+
+/**
+ * Case insensitive library name comparison.
+ */
+bool operator==( const PART_LIB& aLibrary, const wxString& aName );
+bool operator!=( const PART_LIB& aLibrary, const wxString& aName );
+
+#endif // CLASS_LIBRARY_H
diff --git a/eeschema/class_netlist_object.cpp b/eeschema/class_netlist_object.cpp
new file mode 100644
index 00000000..760af590
--- /dev/null
+++ b/eeschema/class_netlist_object.cpp
@@ -0,0 +1,423 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2013 Wayne Stambaugh
+ * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_netlist_object.cpp
+ * @brief Class NETLIST_OBJECT to handle 1 item connected (in netlist and erc calculations)
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+
+/**
+ * The regular expression string for label bus notation. Valid bus labels are defined as
+ * one or more non-whitespace characters from the beginning of the string followed by the
+ * bus notation [nn...mm] with no characters after the closing bracket.
+ */
+static wxRegEx busLabelRe( wxT( "^([^[:space:]]+)(\\[[\\d]+\\.+[\\d]+\\])$" ), wxRE_ADVANCED );
+
+
+bool IsBusLabel( const wxString& aLabel )
+{
+ wxCHECK_MSG( busLabelRe.IsValid(), false,
+ wxT( "Invalid regular expression in IsBusLabel()." ) );
+
+ return busLabelRe.Matches( aLabel );
+}
+
+
+#if defined(DEBUG)
+
+#include
+const char* ShowType( NETLIST_ITEM_T aType )
+{
+ const char* ret;
+
+ switch( aType )
+ {
+ case NET_SEGMENT:
+ ret = "segment"; break;
+
+ case NET_BUS:
+ ret = "bus"; break;
+
+ case NET_JUNCTION:
+ ret = "junction"; break;
+
+ case NET_LABEL:
+ ret = "label"; break;
+
+ case NET_HIERLABEL:
+ ret = "hierlabel"; break;
+
+ case NET_GLOBLABEL:
+ ret = "glabel"; break;
+
+ case NET_BUSLABELMEMBER:
+ ret = "buslblmember"; break;
+
+ case NET_HIERBUSLABELMEMBER:
+ ret = "hierbuslblmember"; break;
+
+ case NET_GLOBBUSLABELMEMBER:
+ ret = "gbuslblmember"; break;
+
+ case NET_SHEETBUSLABELMEMBER:
+ ret = "sbuslblmember"; break;
+
+ case NET_SHEETLABEL:
+ ret = "sheetlabel"; break;
+
+ case NET_PINLABEL:
+ ret = "pinlabel"; break;
+
+ case NET_PIN:
+ ret = "pin"; break;
+
+ case NET_NOCONNECT:
+ ret = "noconnect"; break;
+
+ default:
+ ret = "??"; break;
+ }
+
+ return ret;
+}
+
+
+void NETLIST_OBJECT::Show( std::ostream& out, int ndx ) const
+{
+ wxString path = m_SheetPath.PathHumanReadable();
+
+ out << "\n";
+
+ out << " \n";
+
+ if( !m_Label.IsEmpty() )
+ out << " \n";
+
+ out << " " << m_SheetPath.PathHumanReadable().mb_str() << "\n";
+
+ switch( m_Type )
+ {
+ case NET_PIN:
+ /* GetRef() needs to be const
+ out << " " << GetComponentParent()->GetRef(&m_SheetPath).mb_str()
+ << "\n";
+ */
+
+ if( m_Comp )
+ m_Comp->Show( 1, out );
+
+ break;
+
+ default:
+ // not all the m_Comp classes have working Show functions.
+ ;
+ }
+
+/* was segfault-ing
+ if( m_Comp )
+ m_Comp->Show( 1, out ); // labels may not have good Show() funcs?
+ else
+ out << " m_Comp==NULL\n";
+*/
+
+ out << "\n";
+}
+
+#endif
+
+
+NETLIST_OBJECT::NETLIST_OBJECT()
+{
+ m_Type = NET_ITEM_UNSPECIFIED; /* Type of this item (see NETLIST_ITEM_T enum) */
+ m_Comp = NULL; /* Pointer on the library item that created this net object
+ * (the parent)*/
+ m_Link = NULL; /* For SCH_SHEET_PIN:
+ * Pointer to the hierarchy sheet that contains this
+ * SCH_SHEET_PIN For Pins: pointer to the component that
+ * contains this pin
+ */
+ m_Flag = 0; /* flag used in calculations */
+ m_ElectricalType = 0; /* Has meaning only for Pins and hierarchical pins: electrical
+ * type */
+ m_netCode = 0; /* net code for all items except BUS labels because a BUS
+ * label has as many net codes as bus members
+ */
+ m_BusNetCode = 0; /* Used for BUS connections */
+ m_Member = 0; /* for labels type NET_BUSLABELMEMBER ( bus member created
+ * from the BUS label ) member number
+ */
+ m_ConnectionType = UNCONNECTED;
+ m_PinNum = 0; /* pin number ( 1 long = 4 bytes -> 4 ascii codes) */
+ m_netNameCandidate = NULL; /* a pointer to a NETLIST_OBJECT type label connected to this
+ * object used to give a name to the net
+ */
+}
+
+
+// Copy constructor
+NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource )
+{
+ *this = aSource;
+}
+
+
+NETLIST_OBJECT::~NETLIST_OBJECT()
+{
+}
+
+
+// return true if the object is a label of any type
+bool NETLIST_OBJECT::IsLabelType() const
+{
+ return m_Type == NET_LABEL
+ || m_Type == NET_GLOBLABEL || m_Type == NET_HIERLABEL
+ || m_Type == NET_BUSLABELMEMBER || m_Type == NET_GLOBBUSLABELMEMBER
+ || m_Type == NET_HIERBUSLABELMEMBER
+ || m_Type == NET_PINLABEL;
+}
+
+bool NETLIST_OBJECT::IsLabelConnected( NETLIST_OBJECT* aNetItem )
+{
+ if( aNetItem == this ) // Don't compare the same net list object.
+ return false;
+
+ int at = m_Type;
+ int bt = aNetItem->m_Type;
+
+ if( ( at == NET_HIERLABEL || at == NET_HIERBUSLABELMEMBER )
+ && ( bt == NET_SHEETLABEL || bt == NET_SHEETBUSLABELMEMBER ) )
+ {
+ if( m_SheetPath == aNetItem->m_SheetPathInclude )
+ {
+ return true; //connected!
+ }
+ }
+ else if( ( at == NET_GLOBLABEL ) && ( bt == NET_GLOBLABEL ) )
+ {
+ if( m_Label == aNetItem->m_Label )
+ return true; //connected!
+ }
+
+ return false; //these two are unconnected
+}
+
+
+void NETLIST_OBJECT::ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems )
+{
+ wxCHECK_RET( IsBusLabel( m_Label ),
+ wxT( "<" ) + m_Label + wxT( "> is not a valid bus label." ) );
+
+ if( m_Type == NET_HIERLABEL )
+ m_Type = NET_HIERBUSLABELMEMBER;
+ else if( m_Type == NET_GLOBLABEL )
+ m_Type = NET_GLOBBUSLABELMEMBER;
+ else if( m_Type == NET_SHEETLABEL )
+ m_Type = NET_SHEETBUSLABELMEMBER;
+ else if( m_Type == NET_LABEL )
+ m_Type = NET_BUSLABELMEMBER;
+ else
+ wxCHECK_RET( false, wxT( "Net list object type is not valid." ) );
+
+ unsigned i;
+ wxString tmp, busName, busNumber;
+ long begin, end, member;
+
+ busName = busLabelRe.GetMatch( m_Label, 1 );
+ busNumber = busLabelRe.GetMatch( m_Label, 2 );
+
+ /* Search for '[' because a bus label is like "busname[nn..mm]" */
+ i = busNumber.Find( '[' );
+ i++;
+
+ while( i < busNumber.Len() && busNumber[i] != '.' )
+ {
+ tmp.Append( busNumber[i] );
+ i++;
+ }
+
+ tmp.ToLong( &begin );
+
+ while( i < busNumber.Len() && busNumber[i] == '.' )
+ i++;
+
+ tmp.Empty();
+
+ while( i < busNumber.Len() && busNumber[i] != ']' )
+ {
+ tmp.Append( busNumber[i] );
+ i++;
+ }
+
+ tmp.ToLong( &end );
+
+ if( begin < 0 )
+ begin = 0;
+
+ if( end < 0 )
+ end = 0;
+
+ if( begin > end )
+ std::swap( begin, end );
+
+ member = begin;
+ tmp = busName;
+ tmp << member;
+ m_Label = tmp;
+ m_Member = member;
+
+ for( member++; member <= end; member++ )
+ {
+ NETLIST_OBJECT* item = new NETLIST_OBJECT( *this );
+
+ // Conversion of bus label to the root name + the current member id.
+ tmp = busName;
+ tmp << member;
+ item->m_Label = tmp;
+ item->m_Member = member;
+
+ aNetListItems.push_back( item );
+ }
+}
+
+
+bool NETLIST_OBJECT::IsLabelGlobal() const
+{
+ // return true if the object is a global label
+ // * a actual global label
+ // * a pin label coming from a invisible power pin
+ return ( m_Type == NET_PINLABEL ) ||
+ ( m_Type == NET_GLOBLABEL ) ||
+ ( m_Type == NET_GLOBBUSLABELMEMBER );
+}
+
+
+bool NETLIST_OBJECT::IsLabelBusMemberType() const
+{
+ // return true if the object is a bus label member build from a
+ // schematic bus label (like label[xx..yy)
+ // They are labels with very specific properties, especially for connection
+ // between them: 2 bus label members can be connected only
+ // if they have the same member value.
+ return ( m_Type == NET_SHEETBUSLABELMEMBER ) ||
+ ( m_Type == NET_BUSLABELMEMBER ) ||
+ ( m_Type == NET_HIERBUSLABELMEMBER ) ||
+ ( m_Type == NET_GLOBBUSLABELMEMBER );
+}
+
+
+/*
+ * return the net name of the item
+ */
+wxString NETLIST_OBJECT::GetNetName() const
+{
+ if( m_netNameCandidate == NULL )
+ return wxEmptyString;
+
+ wxString netName;
+
+ if( m_netNameCandidate->m_Type == NET_PIN )
+ return GetShortNetName();
+
+ if( !m_netNameCandidate->IsLabelGlobal() )
+ {
+ // usual net name, prefix it by the sheet path
+ netName = m_netNameCandidate->m_SheetPath.PathHumanReadable();
+ }
+
+ netName += m_netNameCandidate->m_Label;
+
+ return netName;
+}
+
+/**
+ * return the short net name of the item i.e. the net name
+ * from the "best" label without any prefix.
+ * 2 different nets can have the same short name
+ */
+wxString NETLIST_OBJECT::GetShortNetName() const
+{
+ if( m_netNameCandidate == NULL )
+ return wxEmptyString;
+
+ wxString netName;
+
+ if( m_netNameCandidate->m_Type == NET_PIN )
+ {
+ SCH_COMPONENT* link = m_netNameCandidate->GetComponentParent();
+ if( link ) // Should be always true
+ {
+ netName = wxT("Net-(");
+ netName << link->GetRef( &m_netNameCandidate->m_SheetPath );
+ netName << wxT("-Pad")
+ << LIB_PIN::PinStringNum( m_netNameCandidate->m_PinNum )
+ << wxT(")");
+ }
+ }
+ else
+ netName = m_netNameCandidate->m_Label;
+
+ return netName;
+}
+
+/**
+ * Set m_netNameCandidate to a connected item which will
+ * be used to calcule the net name of the item
+ * Obviously the candidate can be only a label
+ * If there is no label on the net, a pad name will be
+ * used to build a net name (something like Cmp_Pad
+ * @param aCandidate = the connected item candidate
+ */
+void NETLIST_OBJECT::SetNetNameCandidate( NETLIST_OBJECT* aCandidate )
+{
+ switch( aCandidate->m_Type )
+ {
+ case NET_HIERLABEL:
+ case NET_LABEL:
+ case NET_PINLABEL:
+ case NET_GLOBLABEL:
+ case NET_GLOBBUSLABELMEMBER:
+ case NET_SHEETBUSLABELMEMBER:
+ case NET_PIN:
+ m_netNameCandidate = aCandidate;
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/eeschema/class_netlist_object.h b/eeschema/class_netlist_object.h
new file mode 100644
index 00000000..3e726d45
--- /dev/null
+++ b/eeschema/class_netlist_object.h
@@ -0,0 +1,483 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2013 Wayne Stambaugh
+ * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_netlist_object.h
+ * @brief Definition of the NETLIST_OBJECT class.
+ */
+
+#ifndef _CLASS_NETLIST_OBJECT_H_
+#define _CLASS_NETLIST_OBJECT_H_
+
+
+#include
+#include // LIB_PIN::PinStringNum( m_PinNum )
+#include
+
+class NETLIST_OBJECT_LIST;
+class SCH_COMPONENT;
+
+
+/* Type of Net objects (wires, labels, pins...) */
+enum NETLIST_ITEM_T
+{
+ NET_ITEM_UNSPECIFIED, // only for not yet initialized instances
+ NET_SEGMENT, // connection by wire
+ NET_BUS, // connection by bus
+ NET_JUNCTION, // connection by junction: can connect to
+ // or more crossing wires
+ NET_LABEL, // this is a local label
+ NET_GLOBLABEL, // this is a global label that connect all
+ // others global label in whole hierarchy
+ NET_HIERLABEL, // element to indicate connection to a
+ // higher-level sheet
+ NET_SHEETLABEL, // element to indicate connection to a
+ // lower-level sheet.
+ NET_BUSLABELMEMBER, /* created when a bus label is found:
+ * the bus label (like DATA[0..7] is
+ * converted to n single labels like
+ * DATA0, DATA1 ...
+ * These objects are living only in the current
+ * NETLIST_OBJECT_LIST, not in shematic.
+ */
+ NET_GLOBBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a
+ // global bus label is found
+ NET_HIERBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a
+ // hierarchical bus label is found
+ NET_SHEETBUSLABELMEMBER, // see NET_BUSLABELMEMBER, used when a
+ // pin sheet label using bus notation
+ // is found
+ NET_PINLABEL, /* created when a pin is POWER (IN or
+ * OUT) with invisible attribute is found:
+ * these pins are equivalent to a global
+ * label and are automatically connected
+ */
+ NET_PIN, // this is an usual pin
+ NET_NOCONNECT // this is a no connect symbol
+};
+
+
+/* Values for .m_FlagOfConnection member */
+enum NET_CONNECTION_T
+{
+ UNCONNECTED = 0, /* Pin or Label not connected (error) */
+ NOCONNECT_SYMBOL_PRESENT, /* Pin not connected but have a NoConnect
+ * symbol on it (no error) */
+ PAD_CONNECT /* Normal connection (no error) */
+};
+
+
+class NETLIST_OBJECT
+{
+public:
+ NETLIST_ITEM_T m_Type; /* Type of item (see NETLIST_ITEM_T enum) */
+ EDA_ITEM* m_Comp; /* Pointer to the library item that
+ * created this net object (the parent)
+ */
+ SCH_ITEM* m_Link; /* For SCH_SHEET_PIN:
+ * Pointer to the hierarchy sheet that
+ * contains this SCH_SHEET_PIN
+ * For Pins: pointer to the schematic component
+ * that contains this pin
+ */
+ int m_Flag; /* flag used in calculations */
+ SCH_SHEET_PATH m_SheetPath; // the sheet path which contains this item
+ SCH_SHEET_PATH m_SheetPathInclude; // sheet path which contains the hierarchical label
+ int m_ElectricalType; /* Has meaning only for Pins and
+ * hierarchical pins: electrical type */
+ int m_BusNetCode; /* Used for BUS connections */
+ int m_Member; /* for labels type NET_BUSLABELMEMBER ( bus member
+ * created from the BUS label ) member number.
+ */
+ NET_CONNECTION_T m_ConnectionType; // Used to store the connection type
+ long m_PinNum; // pin number ( 1 long = 4 bytes -> 4 ascii codes)
+ wxString m_Label; // Label text (for labels) or Pin name (for pins)
+ wxPoint m_Start; // Position of object or for segments: starting point
+ wxPoint m_End; // For segments (wire and buses): ending point
+
+private:
+ int m_netCode; /* net code for all items except BUS
+ * labels because a BUS label has
+ * as many net codes as bus members
+ */
+ NETLIST_OBJECT* m_netNameCandidate; /* a pointer to a label connected to the net,
+ * that can be used to give a name to the net
+ * or a pin if there is no label in net
+ * When no label, the pin is used to build
+ * default net name.
+ */
+
+public:
+
+#if defined(DEBUG)
+ void Show( std::ostream& out, int ndx ) const; // override
+
+#endif
+
+ NETLIST_OBJECT();
+ NETLIST_OBJECT( NETLIST_OBJECT& aSource ); // Copy constructor
+
+ ~NETLIST_OBJECT();
+
+ // Accessors:
+ void SetNet( int aNetCode ) { m_netCode = aNetCode; }
+ int GetNet() const { return m_netCode; }
+
+ /**
+ * Set the item connection type:
+ * UNCONNECTED Pin or Label not connected (error)
+ * NOCONNECT_SYMBOL_PRESENT Pin not connected but have a NoConnect
+ * symbol on it (no error)
+ * PAD_CONNECT Normal connection (no error)
+ */
+ void SetConnectionType( NET_CONNECTION_T aFlg = UNCONNECTED )
+ {
+ m_ConnectionType = aFlg;
+ }
+
+ NET_CONNECTION_T GetConnectionType()
+ {
+ return m_ConnectionType;
+ }
+
+ /**
+ * Set m_netNameCandidate to a connected item which will
+ * be used to calcule the net name of the item
+ * Obviously the candidate can be only a label
+ * when there is no label on the net a pad which will
+ * used to build a net name (something like Cmp_Pad
+ * @param aCandidate = the connected item candidate
+ */
+ void SetNetNameCandidate( NETLIST_OBJECT* aCandidate );
+
+ /**
+ * @return true if an item has already a net name candidate
+ * and false if not ( m_netNameCandidate == NULL )
+ */
+ bool HasNetNameCandidate() { return m_netNameCandidate != NULL; }
+
+ /**
+ * Function GetPinNum
+ * returns a pin number in wxString form. Pin numbers are not always
+ * numbers. \"A23\" would be a valid pin number.
+ */
+ wxString GetPinNumText()
+ {
+ // hide the ugliness in here, but do it inline.
+ return LIB_PIN::PinStringNum( m_PinNum );
+ }
+
+ /** For Pins (NET_PINS):
+ * @return the schematic component which contains this pin
+ * (Note: this is the schematic component, not the library component
+ * for others items: return NULL
+ */
+ SCH_COMPONENT* GetComponentParent() const
+ {
+ if( m_Link && m_Link->Type() == SCH_COMPONENT_T )
+ return (SCH_COMPONENT*) m_Link;
+
+ return NULL;
+ }
+
+ /**
+ * Function IsLabelConnected
+ * tests if the net list object is a hierarchical label or sheet label and is
+ * connected to an associated hierarchical label or sheet label of \a aNetItem.
+ *
+ * @param aNetItem A pointer to a NETLIST_OBJECT to test against.
+ * @return A bool value of true if there is a connection with \a aNetItem or false
+ * if no connection to \a aNetItem.
+ */
+ bool IsLabelConnected( NETLIST_OBJECT* aNetItem );
+
+ /**
+ * Function IsLabelGlobal
+ * @return true if the object is a global label
+ * (i.e. an real global label or a pin label coming
+ * from a power pin invisible
+ */
+ bool IsLabelGlobal() const;
+
+ /**
+ * Function IsLabelBusMemberType
+ * @return true if the object is a bus label member build from a
+ * schematic bus label (like label[xx..yy], xx and yy are the first and last
+ * bus member id)
+ * bus label members have specific properties:
+ * they do not live in schematic
+ * they have specific properties in connections:
+ * 2 bus label members can be connected connected only if they have the same member value.
+ */
+ bool IsLabelBusMemberType() const;
+
+ /**
+ * Function IsLabelType
+ * @return true if the object is a label of any type
+ */
+ bool IsLabelType() const;
+
+ /**
+ * Function GetNetName
+ * @return the full net name of the item, i.e. the net name
+ * from the "best" label, prefixed by the sheet path
+ */
+ wxString GetNetName() const;
+
+ /**
+ * Function GetShortNetName
+ * @return the short net name of the item i.e. the net name
+ * from the "best" label without any prefix.
+ * 2 different nets can have the same short name
+ */
+ wxString GetShortNetName() const;
+
+ /**
+ * Function ConvertBusToNetListItems
+ * breaks the text of a bus label type net list object into as many members as
+ * it contains and creates a #NETLIST_OBJECT for each label and adds it to \a
+ * aNetListItems.
+ *
+ * @param aNetListItems A reference to vector of #NETLIST_OBJECT pointers to add
+ * the bus label NETLIST_OBJECTs.
+ */
+ void ConvertBusToNetListItems( NETLIST_OBJECT_LIST& aNetListItems );
+};
+
+
+/**
+ * Type NETLIST_OBJECTS
+ * is a container referring to (not owning) NETLIST_OBJECTs, which are connected items
+ * in a full schematic hierarchy. It is useful when referring to NETLIST_OBJECTs
+ * actually owned by some other container.
+ */
+typedef std::vector NETLIST_OBJECTS;
+
+
+/**
+ * Class NETLIST_OBJECT_LIST
+ * is a container holding and _owning_ NETLIST_OBJECTs, which are connected items
+ * in a full schematic hierarchy. It is helpful for netlist and ERC calculations.
+ */
+class NETLIST_OBJECT_LIST : public NETLIST_OBJECTS
+{
+ int m_lastNetCode; // Used in intermediate calculation: last net code created
+ int m_lastBusNetCode; // Used in intermediate calculation:
+ // last net code created for bus members
+
+public:
+ /**
+ * Constructor.
+ * NETLIST_OBJECT_LIST handle a list of connected items.
+ * the instance can be owner of items or not.
+ * If it is the owner, the items are freeed by the destructor
+ * @param aIsOwner true if the instance is the owner of item list
+ * (default = false)
+ */
+ NETLIST_OBJECT_LIST()
+ {
+ // Do not leave some members uninitialized:
+ m_lastNetCode = 0;
+ m_lastBusNetCode = 0;
+ }
+
+ ~NETLIST_OBJECT_LIST();
+
+ /**
+ * Function BuildNetListInfo
+ * the master function of tgis class.
+ * Build the list of connected objects (pins, labels ...) and
+ * all info to generate netlists or run ERC diags
+ * @param aSheets = the flattened sheet list
+ * @return true if OK, false is not item found
+ */
+ bool BuildNetListInfo( SCH_SHEET_LIST& aSheets );
+
+ /**
+ * Acces to an item in list
+ */
+ NETLIST_OBJECT* GetItem( unsigned aIdx ) const
+ {
+ return *( this->begin() + aIdx );
+ }
+
+ /**
+ * Acces to an item type
+ */
+ NETLIST_ITEM_T GetItemType( unsigned aIdx ) const
+ {
+ return GetItem( aIdx )->m_Type;
+ }
+
+ /**
+ * Acces to an item net code
+ */
+ int GetItemNet( unsigned aIdx ) const
+ {
+ return GetItem( aIdx )->GetNet();
+ }
+
+ NET_CONNECTION_T GetConnectionType( unsigned aIdx )
+ {
+ return GetItem( aIdx )->GetConnectionType();
+ }
+
+ /**
+ * Set the item connection type:
+ * UNCONNECTED Pin or Label not connected (error)
+ * NOCONNECT_SYMBOL_PRESENT Pin not connected but have a NoConnect
+ * symbol on it (no error)
+ * PAD_CONNECT Normal connection (no error)
+ */
+ void SetConnectionType( unsigned aIdx, NET_CONNECTION_T aFlg = UNCONNECTED )
+ {
+ GetItem( aIdx )->SetConnectionType( aFlg );
+ }
+
+ /** Delete all objects in list and clear list */
+ void Clear();
+
+ /**
+ * Reset the connection type of all items to UNCONNECTED type
+ */
+ void ResetConnectionsType()
+ {
+ for( unsigned ii = 0; ii < size(); ii++ )
+ GetItem( ii )->SetConnectionType( UNCONNECTED );
+ }
+
+ /*
+ * Sorts the list of connected items by net code
+ */
+ void SortListbyNetcode();
+
+ /*
+ * Sorts the list of connected items by sheet.
+ * This sorting is used when searching "physical" connection between items
+ * because obviously only items inside the same sheet can be connected
+ */
+ void SortListbySheet();
+
+
+ #if defined(DEBUG)
+ void DumpNetTable()
+ {
+ for( unsigned idx = 0; idx < size(); ++idx )
+ {
+ GetItem( idx )->Show( std::cout, idx );
+ }
+ }
+
+ #endif
+
+private:
+ /*
+ * Propagate aNewNetCode to items having an internal netcode aOldNetCode
+ * used to interconnect group of items already physically connected,
+ * when a new connection is found between aOldNetCode and aNewNetCode
+ */
+ void propageNetCode( int aOldNetCode, int aNewNetCode, bool aIsBus );
+
+ /*
+ * This function merges the net codes of groups of objects already connected
+ * to labels (wires, bus, pins ... ) when 2 labels are equivalents
+ * (i.e. group objects connected by labels)
+ */
+ void labelConnect( NETLIST_OBJECT* aLabelRef );
+
+ /* Comparison function to sort by increasing Netcode the list of connected items
+ */
+ static bool sortItemsbyNetcode( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 )
+ {
+ return Objet1->GetNet() < Objet2->GetNet();
+ }
+
+ /* Comparison routine to sort items by Sheet Number
+ */
+ static bool sortItemsBySheet( const NETLIST_OBJECT* Objet1, const NETLIST_OBJECT* Objet2 )
+ {
+ return Objet1->m_SheetPath.Cmp( Objet2->m_SheetPath ) < 0;
+ }
+
+ /**
+ * Propagate net codes from a parent sheet to an include sheet,
+ * from a pin sheet connection
+ */
+ void sheetLabelConnect( NETLIST_OBJECT* aSheetLabel );
+
+ void pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start );
+
+ /**
+ * Search connections between a junction and segments
+ * Propagate the junction net code to objects connected by this junction.
+ * The junction must have a valid net code
+ * The list of objects is expected sorted by sheets.
+ * Search is done from index aIdxStart to the last element of list
+ */
+ void segmentToPointConnect( NETLIST_OBJECT* aJonction, bool aIsBus, int aIdxStart );
+
+
+ /**
+ * Function connectBusLabels
+ * Propagate the net code (and create it, if not yet existing) between
+ * all bus label member objects connected by they name.
+ * Search is done in the entire list
+ */
+ void connectBusLabels();
+
+ /**
+ * Set the m_FlagOfConnection member of items in list
+ * depending on the connection type:
+ * UNCONNECTED, PAD_CONNECT or NOCONNECT_SYMBOL_PRESENT
+ * The list is expected sorted by order of net code,
+ * i.e. items having the same net code are grouped
+ */
+ void setUnconnectedFlag();
+
+ /**
+ * Function findBestNetNameForEachNet
+ * fill the .m_NetNameCandidate member of each item of aNetItemBuffer
+ * with a reference to the "best" NETLIST_OBJECT usable to give a name to the net
+ * If no suitable object found, .m_NetNameCandidate is filled with 0.
+ * The "best" NETLIST_OBJECT is a NETLIST_OBJECT that have the type label
+ * and by priority order:
+ * the label is global or local
+ * the label is in the first sheet in a hierarchy (the root sheet has the most priority)
+ * alphabetic order.
+ */
+ void findBestNetNameForEachNet();
+};
+
+
+/**
+ * Function IsBusLabel
+ * test if \a aLabel has a bus notation.
+ *
+ * @param aLabel A wxString object containing the label to test.
+ * @return true if text is a bus notation format otherwise false is returned.
+ */
+extern bool IsBusLabel( const wxString& aLabel );
+
+#endif // _CLASS_NETLIST_OBJECT_H_
diff --git a/eeschema/class_sch_screen.h b/eeschema/class_sch_screen.h
new file mode 100644
index 00000000..67c6451b
--- /dev/null
+++ b/eeschema/class_sch_screen.h
@@ -0,0 +1,599 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file class_sch_screen.h
+ * @brief Definitions for the Eeschema program SCH_SCREEN class.
+ */
+
+#ifndef CLASS_SCREEN_H
+#define CLASS_SCREEN_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include <../eeschema/general.h>
+
+
+class LIB_PIN;
+class SCH_COMPONENT;
+class SCH_SHEET_PATH;
+class SCH_SHEET_PIN;
+class SCH_LINE;
+class SCH_TEXT;
+class PLOTTER;
+
+
+enum SCH_LINE_TEST_T
+{
+ ENTIRE_LENGTH_T,
+ END_POINTS_ONLY_T,
+ EXCLUDE_END_POINTS_T
+};
+
+
+/// Max number of sheets in a hierarchy project
+#define NB_MAX_SHEET 500
+
+
+class SCH_SCREEN : public BASE_SCREEN, public KIWAY_HOLDER
+{
+private:
+
+ wxString m_fileName; ///< File used to load the screen.
+
+ int m_refCount; ///< Number of sheets referencing this screen.
+ ///< Delete when it goes to zero.
+
+ /// The size of the paper to print or plot on
+ PAGE_INFO m_paper; // keep with the MVC 'model' if this class gets split
+
+ TITLE_BLOCK m_titles;
+
+ /// Origin of the auxilliary axis, which is used in exports mostly, but not yet in EESCHEMA
+ wxPoint m_aux_origin;
+
+ DLIST< SCH_ITEM > m_drawList; ///< Object list for the screen.
+
+ int m_modification_sync; ///< inequality with PART_LIBS::GetModificationHash()
+ ///< will trigger ResolveAll().
+
+ /**
+ * Function addConnectedItemsToBlock
+ * add items connected at \a aPosition to the block pick list.
+ *
+ * This method tests all connectible unselected items in the screen that are connected to
+ * \a aPosition and adds them to the block selection pick list. This is used when a block
+ * drag is being performed to ensure connections to items in the block are not lost.
+ *
+ * @param aPosition = The connection point to test.
+ */
+ void addConnectedItemsToBlock( const wxPoint& aPosition );
+
+public:
+
+ /**
+ * Constructor
+ */
+ SCH_SCREEN( KIWAY* aKiway );
+
+ ~SCH_SCREEN();
+
+ virtual wxString GetClass() const
+ {
+ return wxT( "SCH_SCREEN" );
+ }
+
+ const PAGE_INFO& GetPageSettings() const { return m_paper; }
+ void SetPageSettings( const PAGE_INFO& aPageSettings ) { m_paper = aPageSettings; }
+
+ void SetFileName( const wxString& aFileName ) { m_fileName = aFileName; }
+
+ const wxString& GetFileName() const { return m_fileName; }
+
+ const wxPoint& GetAuxOrigin() const { return m_aux_origin; }
+ void SetAuxOrigin( const wxPoint& aPosition ) { m_aux_origin = aPosition; }
+
+ const TITLE_BLOCK& GetTitleBlock() const { return m_titles; }
+ //TITLE_BLOCK& GetTitleBlock() const { return (TITLE_BLOCK&) m_titles; }
+ void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) { m_titles = aTitleBlock; }
+
+ void DecRefCount();
+
+ void IncRefCount();
+
+ int GetRefCount() const { return m_refCount; }
+
+ /**
+ * Function GetDrawItems().
+ * @return - A pointer to the first item in the linked list of draw items.
+ */
+ SCH_ITEM* GetDrawItems() const { return m_drawList.begin(); }
+
+ void Append( SCH_ITEM* aItem )
+ {
+ m_drawList.Append( aItem );
+ --m_modification_sync;
+ }
+
+ /**
+ * Function Append
+ * adds \a aList of SCH_ITEM objects to the list for draw items for the sheet.
+ *
+ * @param aList A reference to a #DLIST containing the #SCH_ITEM to add to the sheet.
+ */
+ void Append( DLIST< SCH_ITEM >& aList )
+ {
+ m_drawList.Append( aList );
+ --m_modification_sync;
+ }
+
+ /**
+ * Function GetCurItem
+ * returns the currently selected SCH_ITEM, overriding BASE_SCREEN::GetCurItem().
+ * @return SCH_ITEM* - the one selected, or NULL.
+ */
+ SCH_ITEM* GetCurItem() const { return (SCH_ITEM*) BASE_SCREEN::GetCurItem(); }
+
+ /**
+ * Function SetCurItem
+ * sets the currently selected object, m_CurrentItem.
+ * @param aItem Any object derived from SCH_ITEM
+ */
+ void SetCurItem( SCH_ITEM* aItem ) { BASE_SCREEN::SetCurItem( (EDA_ITEM*) aItem ); }
+
+ /**
+ * Function Clear
+ * deletes all draw items and clears the project settings.
+ */
+ void Clear();
+
+ /**
+ * Free all the items from the schematic associated with the screen.
+ *
+ * This does not delete any sub hierarchies.
+ */
+ void FreeDrawList();
+
+ /**
+ * Function GetItem
+ * checks \a aPosition within a distance of \a aAccuracy for items of type \a aFilter.
+ * @param aPosition Position in drawing units.
+ * @param aAccuracy The maximum distance within \a Position to check for an item.
+ * @param aType The type of item to find or #NOT_USED to find any item type.
+ * @return The item found that meets the search criteria or NULL if none found.
+ */
+ SCH_ITEM* GetItem( const wxPoint& aPosition, int aAccuracy = 0,
+ KICAD_T aType = NOT_USED ) const;
+
+ void Place( SCH_EDIT_FRAME* frame, wxDC* DC ) { };
+
+ /**
+ * Function CheckComponentsToPartsLink
+ * initializes or reinitializes the weak reference
+ * to the LIB_PART for each SCH_COMPONENT found in m_drawList.
+ * It must be called from:
+ * - Draw function
+ * - when loading a schematic file
+ * - before creating a netlist (in case a library is modified)
+ */
+ void CheckComponentsToPartsLinks();
+
+ /**
+ * Function Draw
+ * draws all the items in the screen to \a aCanvas.
+ * note: this function is useful only for schematic.
+ * library editor and library viewer do not use a draw list, and therefore
+ * draws nothing
+ * @param aCanvas The canvas item to draw on.
+ * @param aDC The device context to draw on.
+ * @param aDrawMode The drawing mode.
+ * @param aColor The drawing color.
+ */
+ void Draw( EDA_DRAW_PANEL* aCanvas, wxDC* aDC, GR_DRAWMODE aDrawMode,
+ EDA_COLOR_T aColor = UNSPECIFIED_COLOR );
+
+ /**
+ * Function Plot
+ * plots all the schematic objects to \a aPlotter.
+ * note: this function is useful only for schematic.
+ * library editor and library viewer do not use a draw list, and therefore
+ * plots nothing
+ *
+ * @param aPlotter The plotter object to plot to.
+ */
+ void Plot( PLOTTER* aPlotter );
+
+ /**
+ * Function Remove
+ * removes \a aItem from the schematic associated with this screen.
+ *
+ * @note The removed item is not deleted. It is only unlinked from the item list.
+ * @param aItem Item to be removed from schematic.
+ */
+ void Remove( SCH_ITEM* aItem );
+
+ /**
+ * Function DeleteItem
+ * removes \a aItem from the linked list and deletes the object. If \a aItem is
+ * is a schematic sheet label, it is removed from the screen associated with the
+ * sheet that contains the label to be deleted.
+ * @param aItem The schematic object to be deleted from the screen.
+ */
+ void DeleteItem( SCH_ITEM* aItem );
+
+ bool CheckIfOnDrawList( SCH_ITEM* st );
+
+ /**
+ * Function SchematicCleanUp
+ * performs routine schematic cleaning including breaking wire and buses and
+ * deleting identical objects superimposed on top of each other.
+ *
+ * @param aCanvas The window to draw on.
+ * @param aDC The device context used for drawing to \a aCanvas.
+ * @return True if any schematic clean up was performed.
+ */
+ bool SchematicCleanUp( EDA_DRAW_PANEL* aCanvas = NULL, wxDC* aDC = NULL );
+
+ /**
+ * Function TestDanglingEnds
+ * tests all of the connectible objects in the schematic for unused connection points.
+ * @param aDC - The device context to draw the dangling status indicators.
+ * @param aCanvas - The window to draw on.
+ * @return True if any dangling ends were found.
+ */
+ bool TestDanglingEnds( EDA_DRAW_PANEL* aCanvas = NULL, wxDC* aDC = NULL );
+
+ /**
+ * Function ExtractWires
+ * extracts the old wires, junctions and buses. If \a aCreateCopy is true, replace
+ * extracted items with a copy of the original. Old items are to be put in undo list,
+ * and the new ones can be modified by clean up safely. If an abort draw segmat command
+ * is made, the old wires must be put back into #m_drawList, and the copies must be
+ * deleted. This is because previously stored undo commands can handle pointers on wires
+ * or buses, and we do not delete wires or buses, we must put them in undo list.
+ *
+ * Because cleanup deletes and/or modify bus and wires, it is easier is to put
+ * all the existing wires in undo list and use a new copy of wires for cleanup.
+ */
+ void ExtractWires( DLIST< SCH_ITEM >& aList, bool aCreateCopy );
+
+ /**
+ * Function ReplaceWires
+ * replaces all of the wires, buses, and junctions in the screen with \a aWireList.
+ *
+ * @param aWireList List of wires to replace the existing wires with.
+ */
+ void ReplaceWires( DLIST< SCH_ITEM >& aWireList );
+
+ /**
+ * Function MarkConnections
+ * add all wires and junctions connected to \a aSegment which are not connected any
+ * component pin to \a aItemList.
+ * @param aSegment The segment to test for connections.
+ */
+ void MarkConnections( SCH_LINE* aSegment );
+
+ /**
+ * Functions GetConnection
+ * adds all of the wires and junctions to \a aList that make up a connection to the
+ * object at \a aPosition.
+ * @param aPosition The position of the first connection object in drawing units.
+ * @param aList The pick list to add the connect item to.
+ * @param aFullConnection If true all the objects that make up this connection are
+ * add to \a aList. Otherwise, only the objects up to the first
+ * node are added.
+ * @return The number of items added to \a aList.
+ */
+ int GetConnection( const wxPoint& aPosition, PICKED_ITEMS_LIST& aList, bool aFullConnection );
+
+ /**
+ * Function BreakSegment
+ * checks every wire and bus for a intersection at \a aPoint and break into two segments
+ * at \a aPoint if an intersection is found.
+ * @param aPoint Test this point for an intersection.
+ * @return True if any wires or buses were broken.
+ */
+ bool BreakSegment( const wxPoint& aPoint );
+
+ /**
+ * Function BreakSegmentsOnJunctions
+ * tests all junctions and bus entries in the schematic for intersections with wires and
+ * buses and breaks any intersections into multiple segments.
+ * @return True if any wires or buses were broken.
+ */
+ bool BreakSegmentsOnJunctions();
+
+ /* full undo redo management : */
+ // use BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem )
+ // use BASE_SCREEN::PushCommandToRedoList( PICKED_ITEMS_LIST* aItem )
+
+ /**
+ * Function ClearUndoORRedoList
+ * free the undo or redo list from List element
+ * Wrappers are deleted.
+ * data pointed by wrappers are deleted if not in use in schematic
+ * i.e. when they are copy of a schematic item or they are no more in use (DELETED)
+ * @param aList = the UNDO_REDO_CONTAINER to clear
+ * @param aItemCount = the count of items to remove. < 0 for all items
+ * items are removed from the beginning of the list.
+ * So this function can be called to remove old commands
+ */
+ virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 );
+
+ /**
+ * Function Save
+ * writes the data structures for this object out to \a aFile in "*.sch" format.
+ *
+ * @param aFile The FILE to write to.
+ * @return bool - true if success writing else false.
+ */
+ bool Save( FILE* aFile ) const;
+
+ /**
+ * Clear the state flags of all the items in the screen.
+ */
+ void ClearDrawingState();
+
+ int CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const;
+
+ /**
+ * Function IsJunctionNeeded
+ * tests if a junction is required for the items at \a aPosition on the screen.
+ *
+ * A junction is required at \a aPosition if the following criteria are satisfied:
+ *
+ *
one wire midpoint, one or more wire endpoints and no junction.
+ *
three or more wire endpoints and no junction.
+ *
two wire midpoints and no junction
+ *
one wire midpoint, a component pin, and no junction.
+ *
three wire endpoints, a component pin, and no junction.
+ *
+ *
+ * @param aPosition The position to test.
+ * @return True if a junction is required at \a aPosition.
+ */
+ bool IsJunctionNeeded( const wxPoint& aPosition );
+
+ /**
+ * Function IsTerminalPoint
+ * tests if \a aPosition is a connection point on \a aLayer.
+ *
+ * @param aPosition Position to test.
+ * @param aLayer The layer type to test against. Valid layer types are #LAYER_NOTES,
+ * #LAYER_BUS, and #LAYER_WIRE.
+ * @return True if \a Position is a connection point on \a aLayer.
+ */
+ bool IsTerminalPoint( const wxPoint& aPosition, int aLayer );
+
+ /**
+ * Function GetPin
+ * test the screen for a component pin item at \a aPosition.
+ * @param aPosition Position to test.
+ * @param aComponent The component if a pin was found, otherwise NULL.
+ * @param aEndPointOnly Set to true to test if \a aPosition is the connection
+ * point of the pin.
+ * @return The pin item if found, otherwise NULL.
+ */
+ LIB_PIN* GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent = NULL,
+ bool aEndPointOnly = false ) const;
+
+ /**
+ * Function GetSheet
+ * returns a sheet object pointer that is named \a aName.
+ *
+ * @note The screen hierarchy is not descened.
+ * @param aName is the case insensitive name of the sheet.
+ * @return A pointer to the SCH_SHEET object found or NULL.
+ */
+ SCH_SHEET* GetSheet( const wxString& aName );
+
+ /**
+ * Function GetSheetLabel
+ * test the screen if \a aPosition is a sheet label object.
+ * @param aPosition The position to test.
+ * @return The sheet label object if found otherwise NULL.
+ */
+ SCH_SHEET_PIN* GetSheetLabel( const wxPoint& aPosition );
+
+ /**
+ * Function ClearAnnotation
+ * clears the annotation for the components in \a aSheetPath on the screen.
+ * @param aSheetPath The sheet path of the component annotation to clear. If NULL then
+ * the entire hierarchy is cleared.
+ */
+ void ClearAnnotation( SCH_SHEET_PATH* aSheetPath );
+
+ /**
+ * Function GetHierarchicalItems
+ * adds all schematic sheet and component object in the screen to \a aItems.
+ * @param aItems Hierarchical item list to fill.
+ */
+ void GetHierarchicalItems( EDA_ITEMS& aItems );
+
+ /**
+ * Function GetNode
+ * returns all the items at \a aPosition that form a node.
+ *
+ * @param aPosition The wxPoint to test for node items.
+ * @param aList A #EDA_ITEMS container to place the items found.
+ * @return The number of node items found at \a aPosition.
+ */
+ int GetNode( const wxPoint& aPosition, EDA_ITEMS& aList );
+
+ /**
+ * Function GetWireOrBus
+ * returns a wire or bus item located at \a aPosition.
+ *
+ * @param aPosition The wxPoint to test for node items.
+ * @return The SCH_LINE* of the wire or bus item found at \a aPosition or NULL if item not
+ * found.
+ */
+ SCH_LINE* GetWireOrBus( const wxPoint& aPosition );
+
+ /**
+ * Function GetLine
+ * returns a line item located at \a aPosition.
+ *
+ * @param aPosition The wxPoint to test for a line item.
+ * @param aAccuracy Amount to inflate the item hit test bounding box.
+ * @param aLayer The layer the line is drawn upon.
+ * @param aSearchType Additional line test criteria.
+ * @return The SCH_LINE* of the wire item found at \a aPosition or NULL if item not
+ * found.
+ */
+ SCH_LINE* GetLine( const wxPoint& aPosition, int aAccuracy = 0, int aLayer = LAYER_NOTES,
+ SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T );
+
+ SCH_LINE* GetWire( const wxPoint& aPosition, int aAccuracy = 0,
+ SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T )
+ {
+ return GetLine( aPosition, aAccuracy, LAYER_WIRE, aSearchType );
+ }
+
+ SCH_LINE* GetBus( const wxPoint& aPosition, int aAccuracy = 0,
+ SCH_LINE_TEST_T aSearchType = ENTIRE_LENGTH_T )
+ {
+ return GetLine( aPosition, aAccuracy, LAYER_BUS, aSearchType );
+ }
+
+ /**
+ * Function GetLabel
+ * returns a label item located at \a aPosition.
+ *
+ * @param aPosition The wxPoint to test for label items.
+ * @param aAccuracy Amount to inflate the item hit test bounding box.
+ * @return The SCH_TEXT* of the label item found at \a aPosition or NULL if item not
+ * found.
+ */
+ SCH_TEXT* GetLabel( const wxPoint& aPosition, int aAccuracy = 0 );
+
+ /**
+ * Function SetFootprintField
+ * searches screen for a component with \a aReference and set the footprint field to
+ * \a aFootPrint if found.
+ *
+ * @param aSheetPath The sheet path used to look up the reference designator.
+ * @param aReference The reference designator of the component.
+ * @param aFootPrint The value to set the footprint field.
+ * @param aSetVisible The value to set the field visibility flag.
+ * @return True if \a aReference was found otherwise false.
+ */
+ bool SetComponentFootprint( SCH_SHEET_PATH* aSheetPath, const wxString& aReference,
+ const wxString& aFootPrint, bool aSetVisible );
+
+ /**
+ * Function SelectBlockItems
+ * creates a list of items found when a block command is initiated. The items selected
+ * depend on the block command. If the drag block command is issued, than any items
+ * connected to items in the block are also selected.
+ */
+ void SelectBlockItems();
+
+ /**
+ * Function UpdatePickList
+ * adds all the items in the screen within the block selection rectangle to the pick list.
+ * @return The number of items in the pick list.
+ */
+ int UpdatePickList();
+
+#if defined(DEBUG)
+ void Show( int nestLevel, std::ostream& os ) const; // overload
+#endif
+};
+
+
+/**
+ * Class SCH_SCREENS
+ * is a container class that holds multiple SCH_SCREENs in a hierarchy.
+ * Individual SCH_SCREENs are unique, and correspond to .sch files.
+ */
+class SCH_SCREENS
+{
+private:
+ std::vector< SCH_SCREEN* > m_screens;
+ unsigned int m_index;
+
+public:
+ SCH_SCREENS();
+ ~SCH_SCREENS();
+ int GetCount() const { return m_screens.size(); }
+ SCH_SCREEN* GetFirst();
+ SCH_SCREEN* GetNext();
+ SCH_SCREEN* GetScreen( unsigned int aIndex ) const;
+
+ /**
+ * Function ClearAnnotation
+ * clears the annotation for all components in the hierarchy.
+ */
+ void ClearAnnotation();
+
+ /**
+ * Function SchematicCleanUp
+ * merges and breaks wire segments in the entire schematic hierarchy.
+ */
+ void SchematicCleanUp();
+
+ /**
+ * Function ReplaceDuplicateTimeStamps
+ * test all sheet and component objects in the schematic for duplicate time stamps
+ * an replaces them as necessary. Time stamps must be unique in order for complex
+ * hierarchies know which components go to which sheets.
+ * @return The number of duplicate time stamps replaced.
+ */
+ int ReplaceDuplicateTimeStamps();
+
+ /**
+ * Function DeleteAllMarkers
+ * deletes all electronic rules check markers of \a aMarkerType from all the screens in
+ * the list.
+ * @param aMarkerType Type of markers to be deleted.
+ */
+ void DeleteAllMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType );
+
+ /**
+ * Function GetMarkerCount
+ * returns the number of ERC markers of \a aMarkerType from all of the screens in the list.
+ *
+ * @param aMarkerType Indicates the type of marker to count. if MARKER_UNSPEC
+ * all markers are counted.
+ * @param aSeverity Indicates the error level of marker to count.
+ * useMARKER_SEVERITY_UNSPEC to count all markersof the specified type
+ * @return int count of the markers found.
+ */
+ int GetMarkerCount( enum MARKER_BASE::TYPEMARKER aMarkerType,
+ enum MARKER_BASE::MARKER_SEVERITY aSeverity );
+
+private:
+ void AddScreenToList( SCH_SCREEN* aScreen );
+ void BuildScreenList( EDA_ITEM* aItem );
+};
+
+#endif /* CLASS_SCREEN_H */
diff --git a/eeschema/cmp_library.keywords b/eeschema/cmp_library.keywords
new file mode 100644
index 00000000..6640005c
--- /dev/null
+++ b/eeschema/cmp_library.keywords
@@ -0,0 +1,33 @@
+header
+version
+name
+author
+comment
+license
+url
+copyright
+symbol
+component
+field
+tags
+docs
+drawing
+arc
+start
+end
+rectangle
+position
+width
+height
+polyline
+circle
+center
+radius
+text
+orientation
+pin
+number
+length
+electical_type
+style
+fill_style
diff --git a/eeschema/cmp_library_lexer.cpp b/eeschema/cmp_library_lexer.cpp
new file mode 100644
index 00000000..750bbaf6
--- /dev/null
+++ b/eeschema/cmp_library_lexer.cpp
@@ -0,0 +1,6 @@
+/*
+ * Do not delete this file. It will eventually become the new component
+ * library file DSN lexer which will replace the current library and library
+ * document file formats.
+ */
+#include
diff --git a/eeschema/component_references_lister.cpp b/eeschema/component_references_lister.cpp
new file mode 100644
index 00000000..6796ef39
--- /dev/null
+++ b/eeschema/component_references_lister.cpp
@@ -0,0 +1,788 @@
+/**
+ * @file component_references_lister.cpp
+ * @brief Code for creating a flat list of components needed for annotation and BOM.
+ */
+
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 1992-2011 jean-pierre Charras
+ * Copyright (C) 1992-2011 Wayne Stambaugh
+ * Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+//#define USE_OLD_ALGO
+
+
+void SCH_REFERENCE_LIST::RemoveItem( unsigned int aIndex )
+{
+ if( aIndex < componentFlatList.size() )
+ componentFlatList.erase( componentFlatList.begin() + aIndex );
+}
+
+
+bool SCH_REFERENCE_LIST::sortByXPosition( const SCH_REFERENCE& item1,
+ const SCH_REFERENCE& item2 )
+{
+ int ii = item1.CompareRef( item2 );
+
+ if( ii == 0 )
+ ii = item1.m_SheetNum - item2.m_SheetNum;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
+ if( ii == 0 )
+ ii = item1.m_TimeStamp - item2.m_TimeStamp;
+
+ return ii < 0;
+}
+
+bool SCH_REFERENCE_LIST::sortByYPosition( const SCH_REFERENCE& item1,
+ const SCH_REFERENCE& item2 )
+{
+ int ii = item1.CompareRef( item2 );
+
+ if( ii == 0 )
+ ii = item1.m_SheetNum - item2.m_SheetNum;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
+ if( ii == 0 )
+ ii = item1.m_TimeStamp - item2.m_TimeStamp;
+
+ return ii < 0;
+}
+
+
+bool SCH_REFERENCE_LIST::sortByRefAndValue( const SCH_REFERENCE& item1,
+ const SCH_REFERENCE& item2 )
+{
+ int ii = item1.CompareRef( item2 );
+ if( ii == 0 )
+ ii = item1.CompareValue( item2 );
+ if( ii == 0 )
+ ii = item1.m_Unit - item2.m_Unit;
+ if( ii == 0 )
+ ii = item1.m_SheetNum - item2.m_SheetNum;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.x - item2.m_CmpPos.x;
+ if( ii == 0 )
+ ii = item1.m_CmpPos.y - item2.m_CmpPos.y;
+ if( ii == 0 )
+ ii = item1.m_TimeStamp - item2.m_TimeStamp;
+
+ return ii < 0;
+}
+
+
+bool SCH_REFERENCE_LIST::sortByReferenceOnly( const SCH_REFERENCE& item1,
+ const SCH_REFERENCE& item2 )
+{
+ int ii;
+
+ ii = RefDesStringCompare( item1.GetRef(), item2.GetRef() );
+
+ if( ii == 0 )
+ {
+ ii = item1.m_RootCmp->GetField( VALUE )->GetText().CmpNoCase( item2.m_RootCmp->GetField( VALUE )->GetText() );
+ }
+
+ if( ii == 0 )
+ {
+ ii = item1.m_Unit - item2.m_Unit;
+ }
+
+ return ii < 0;
+}
+
+
+bool SCH_REFERENCE_LIST::sortByTimeStamp( const SCH_REFERENCE& item1,
+ const SCH_REFERENCE& item2 )
+{
+ int ii = item1.m_SheetPath.Cmp( item2.m_SheetPath );
+
+ if( ii == 0 )
+ ii = item1.m_TimeStamp - item2.m_TimeStamp;
+
+ return ii < 0;
+}
+
+int SCH_REFERENCE_LIST::FindUnit( size_t aIndex, int aUnit )
+{
+ int NumRef;
+
+ NumRef = componentFlatList[aIndex].m_NumRef;
+
+ for( size_t ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ if( ( aIndex == ii )
+ || ( componentFlatList[ii].m_IsNew )
+ || ( componentFlatList[ii].m_NumRef != NumRef )
+ || ( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) != 0 ) )
+ continue;
+
+ if( componentFlatList[ii].m_Unit == aUnit )
+ return (int) ii;
+ }
+
+ return -1;
+}
+
+
+void SCH_REFERENCE_LIST::RemoveSubComponentsFromList()
+{
+ SCH_COMPONENT* libItem;
+ wxString oldName;
+ wxString currName;
+
+ // The component list **MUST** be sorted by reference and by unit number
+ // in order to find all parts of a component
+ SortByReferenceOnly();
+
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+
+ libItem = componentFlatList[ii].m_RootCmp;
+ if( libItem == NULL )
+ continue;
+
+ currName = componentFlatList[ii].GetRef();
+
+ if( !oldName.IsEmpty() )
+ {
+ if( oldName == currName ) // currName is a subpart of oldName: remove it
+ {
+ componentFlatList.erase( componentFlatList.begin() + ii );
+ ii--;
+ }
+ }
+
+ oldName = currName;
+ }
+}
+
+
+void SCH_REFERENCE_LIST::ResetHiddenReferences()
+{
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ if( componentFlatList[ii].GetRefStr()[0] == '#' )
+ {
+ componentFlatList[ii].m_IsNew = true;
+ componentFlatList[ii].m_NumRef = 0;
+ }
+ }
+}
+
+
+void SCH_REFERENCE_LIST::GetRefsInUse( int aIndex, std::vector< int >& aIdList, int aMinRefId )
+{
+ aIdList.clear();
+
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ if( ( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) == 0 )
+ && ( componentFlatList[ii].m_NumRef >= aMinRefId ) )
+ aIdList.push_back( componentFlatList[ii].m_NumRef );
+ }
+
+ sort( aIdList.begin(), aIdList.end() );
+
+ // Ensure each reference number appears only once. If there are components with
+ // multiple parts per package the same number will be stored for each part.
+ std::vector< int >::iterator it = unique( aIdList.begin(), aIdList.end() );
+
+ // Using the C++ unique algorithm only moves the duplicate entries to the end of
+ // of the array. This removes the duplicate entries from the array.
+ aIdList.resize( it - aIdList.begin() );
+}
+
+
+int SCH_REFERENCE_LIST::GetLastReference( int aIndex, int aMinValue )
+{
+ int lastNumber = aMinValue;
+
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ // search only for the current reference prefix:
+ if( componentFlatList[aIndex].CompareRef( componentFlatList[ii] ) != 0 )
+ continue;
+
+ // update max value for the current reference prefix
+ if( lastNumber < componentFlatList[ii].m_NumRef )
+ lastNumber = componentFlatList[ii].m_NumRef;
+ }
+
+ return lastNumber;
+}
+
+
+int SCH_REFERENCE_LIST::CreateFirstFreeRefId( std::vector& aIdList, int aFirstValue )
+{
+ int expectedId = aFirstValue;
+
+ // We search for expected Id a value >= aFirstValue.
+ // Skip existing Id < aFirstValue
+ unsigned ii = 0;
+
+ for( ; ii < aIdList.size(); ii++ )
+ {
+ if( expectedId <= aIdList[ii] )
+ break;
+ }
+
+ // Ids are sorted by increasing value, from aFirstValue
+ // So we search from aFirstValue the first not used value, i.e. the first hole in list.
+ for( ; ii < aIdList.size(); ii++ )
+ {
+ if( expectedId != aIdList[ii] ) // This id is not yet used.
+ {
+ // Insert this free Id, in order to keep list sorted
+ aIdList.insert( aIdList.begin() + ii, expectedId );
+ return expectedId;
+ }
+
+ expectedId++;
+ }
+
+ // All existing Id are tested, and all values are found in use.
+ // So Create a new one.
+ aIdList.push_back( expectedId );
+ return expectedId;
+}
+
+
+void SCH_REFERENCE_LIST::Annotate( bool aUseSheetNum, int aSheetIntervalId,
+ SCH_MULTI_UNIT_REFERENCE_MAP aLockedUnitMap )
+{
+ if ( componentFlatList.size() == 0 )
+ return;
+
+ int LastReferenceNumber = 0;
+ int NumberOfUnits, Unit;
+
+ // Components with an invisible reference (power...) always are re-annotated.
+ ResetHiddenReferences();
+
+ /* calculate index of the first component with the same reference prefix
+ * than the current component. All components having the same reference
+ * prefix will receive a reference number with consecutive values:
+ * IC .. will be set to IC4, IC4, IC5 ...
+ */
+ unsigned first = 0;
+
+ // calculate the last used number for this reference prefix:
+#ifdef USE_OLD_ALGO
+ int minRefId = 0;
+
+ // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
+ if( aUseSheetNum )
+ minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId;
+
+ LastReferenceNumber = GetLastReference( first, minRefId );
+#else
+ int minRefId = 1;
+
+ // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
+ if( aUseSheetNum )
+ minRefId = componentFlatList[first].m_SheetNum * aSheetIntervalId + 1;
+
+ // This is the list of all Id already in use for a given reference prefix.
+ // Will be refilled for each new reference prefix.
+ std::vectoridList;
+ GetRefsInUse( first, idList, minRefId );
+#endif
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ if( componentFlatList[ii].m_Flag )
+ continue;
+
+ // Check whether this component is in aLockedUnitMap.
+ SCH_REFERENCE_LIST* lockedList = NULL;
+ BOOST_FOREACH( SCH_MULTI_UNIT_REFERENCE_MAP::value_type& pair, aLockedUnitMap )
+ {
+ unsigned n_refs = pair.second.GetCount();
+ for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
+ {
+ SCH_REFERENCE &thisRef = pair.second[thisRefI];
+
+ if( thisRef.IsSameInstance( componentFlatList[ii] ) )
+ {
+ lockedList = &pair.second;
+ break;
+ }
+ }
+ if( lockedList != NULL ) break;
+ }
+
+ if( ( componentFlatList[first].CompareRef( componentFlatList[ii] ) != 0 )
+ || ( aUseSheetNum && ( componentFlatList[first].m_SheetNum != componentFlatList[ii].m_SheetNum ) ) )
+ {
+ // New reference found: we need a new ref number for this reference
+ first = ii;
+#ifdef USE_OLD_ALGO
+ minRefId = 0;
+
+ // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
+ if( aUseSheetNum )
+ minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId;
+
+ LastReferenceNumber = componentFlatList.GetLastReference( ii, minRefId );
+#else
+ minRefId = 1;
+
+ // when using sheet number, ensure ref number >= sheet number* aSheetIntervalId
+ if( aUseSheetNum )
+ minRefId = componentFlatList[ii].m_SheetNum * aSheetIntervalId + 1;
+
+ GetRefsInUse( first, idList, minRefId );
+#endif
+ }
+
+ // Annotation of one part per package components (trivial case).
+ if( componentFlatList[ii].GetLibComponent()->GetUnitCount() <= 1 )
+ {
+ if( componentFlatList[ii].m_IsNew )
+ {
+#ifdef USE_OLD_ALGO
+ LastReferenceNumber++;
+#else
+ LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
+#endif
+ componentFlatList[ii].m_NumRef = LastReferenceNumber;
+ }
+
+ componentFlatList[ii].m_Unit = 1;
+ componentFlatList[ii].m_Flag = 1;
+ componentFlatList[ii].m_IsNew = false;
+ continue;
+ }
+
+ // Annotation of multi-unit parts ( n units per part ) (complex case)
+ NumberOfUnits = componentFlatList[ii].GetLibComponent()->GetUnitCount();
+
+ if( componentFlatList[ii].m_IsNew )
+ {
+#ifdef USE_OLD_ALGO
+ LastReferenceNumber++;
+#else
+ LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
+#endif
+ componentFlatList[ii].m_NumRef = LastReferenceNumber;
+
+ if( !componentFlatList[ii].IsUnitsLocked() )
+ componentFlatList[ii].m_Unit = 1;
+
+ componentFlatList[ii].m_Flag = 1;
+ }
+
+ // If this component is in aLockedUnitMap, copy the annotation to all
+ // components that are not it
+ if( lockedList != NULL )
+ {
+ unsigned n_refs = lockedList->GetCount();
+ for( unsigned thisRefI = 0; thisRefI < n_refs; ++thisRefI )
+ {
+ SCH_REFERENCE &thisRef = (*lockedList)[thisRefI];
+ if( thisRef.IsSameInstance( componentFlatList[ii] ) )
+ {
+ // This is the component we're currently annotating. Hold the unit!
+ componentFlatList[ii].m_Unit = thisRef.m_Unit;
+ }
+
+ if( thisRef.CompareValue( componentFlatList[ii] ) != 0 ) continue;
+ if( thisRef.CompareLibName( componentFlatList[ii] ) != 0 ) continue;
+
+ // Find the matching component
+ for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
+ {
+ if( ! thisRef.IsSameInstance( componentFlatList[jj] ) ) continue;
+ componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
+ componentFlatList[jj].m_Unit = thisRef.m_Unit;
+ componentFlatList[jj].m_IsNew = false;
+ componentFlatList[jj].m_Flag = 1;
+ break;
+ }
+ }
+ }
+
+ else
+ {
+ /* search for others units of this component.
+ * we search for others parts that have the same value and the same
+ * reference prefix (ref without ref number)
+ */
+ for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
+ {
+ if( componentFlatList[ii].m_Unit == Unit )
+ continue;
+
+ int found = FindUnit( ii, Unit );
+
+ if( found >= 0 )
+ continue; // this unit exists for this reference (unit already annotated)
+
+ // Search a component to annotate ( same prefix, same value, not annotated)
+ for( unsigned jj = ii + 1; jj < componentFlatList.size(); jj++ )
+ {
+ if( componentFlatList[jj].m_Flag ) // already tested
+ continue;
+
+ if( componentFlatList[ii].CompareRef( componentFlatList[jj] ) != 0 )
+ continue;
+
+ if( componentFlatList[jj].CompareValue( componentFlatList[ii] ) != 0 )
+ continue;
+
+ if( componentFlatList[jj].CompareLibName( componentFlatList[ii] ) != 0 )
+ continue;
+
+ if( !componentFlatList[jj].m_IsNew )
+ continue;
+
+ // Component without reference number found, annotate it if possible
+ if( !componentFlatList[jj].IsUnitsLocked()
+ || ( componentFlatList[jj].m_Unit == Unit ) )
+ {
+ componentFlatList[jj].m_NumRef = componentFlatList[ii].m_NumRef;
+ componentFlatList[jj].m_Unit = Unit;
+ componentFlatList[jj].m_Flag = 1;
+ componentFlatList[jj].m_IsNew = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+int SCH_REFERENCE_LIST::CheckAnnotation( wxArrayString* aMessageList )
+{
+ int error = 0;
+ wxString tmp;
+ wxString msg;
+
+ SortByRefAndValue();
+
+ // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
+ SplitReferences();
+
+ // count not yet annotated items or annotation error.
+ for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
+ {
+ msg.Empty();
+ tmp.Empty();
+
+ if( componentFlatList[ii].m_IsNew ) // Not yet annotated
+ {
+ if( componentFlatList[ii].m_NumRef >= 0 )
+ tmp << componentFlatList[ii].m_NumRef;
+ else
+ tmp = wxT( "?" );
+
+
+ if( ( componentFlatList[ii].m_Unit > 0 )
+ && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
+ {
+ msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ),
+ componentFlatList[ii].m_Unit );
+ }
+ else
+ {
+ msg.Printf( _( "Item not annotated: %s%s\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ) );
+ }
+
+ if( aMessageList )
+ aMessageList->Add( msg + wxT( "\n" ) );
+
+ error++;
+ break;
+ }
+
+ // Error if unit number selected does not exist ( greater than the number of
+ // parts in the component ). This can happen if a component has changed in a
+ // library after a previous annotation.
+ if( std::max( componentFlatList[ii].GetLibComponent()->GetUnitCount(), 1 )
+ < componentFlatList[ii].m_Unit )
+ {
+ if( componentFlatList[ii].m_NumRef >= 0 )
+ tmp << componentFlatList[ii].m_NumRef;
+ else
+ tmp = wxT( "?" );
+
+ msg.Printf( _( "Error item %s%s unit %d and no more than %d parts\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ),
+ componentFlatList[ii].m_Unit,
+ componentFlatList[ii].GetLibComponent()->GetUnitCount() );
+
+ if( aMessageList )
+ aMessageList->Add( msg );
+
+ error++;
+ break;
+ }
+ }
+
+ if( error )
+ return error;
+
+ // count the duplicated elements (if all are annotated)
+ int imax = componentFlatList.size() - 1;
+
+ for( int ii = 0; (ii < imax) && (error < 4); ii++ )
+ {
+ msg.Empty();
+ tmp.Empty();
+
+ if( ( componentFlatList[ii].CompareRef( componentFlatList[ii + 1] ) != 0 )
+ || ( componentFlatList[ii].m_NumRef != componentFlatList[ii + 1].m_NumRef ) )
+ continue;
+
+ // Same reference found. If same unit, error!
+ if( componentFlatList[ii].m_Unit == componentFlatList[ii + 1].m_Unit )
+ {
+ if( componentFlatList[ii].m_NumRef >= 0 )
+ tmp << componentFlatList[ii].m_NumRef;
+ else
+ tmp = wxT( "?" );
+
+ if( ( componentFlatList[ii].m_Unit > 0 )
+ && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
+ {
+ msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ),
+ componentFlatList[ii].m_Unit );
+ }
+ else
+ {
+ msg.Printf( _( "Multiple item %s%s\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ) );
+ }
+
+ if( aMessageList )
+ aMessageList->Add( msg );
+
+ error++;
+ continue;
+ }
+
+ /* Test error if units are different but number of parts per package
+ * too high (ex U3 ( 1 part) and we find U3B this is an error) */
+ if( componentFlatList[ii].GetLibComponent()->GetUnitCount()
+ != componentFlatList[ii + 1].GetLibComponent()->GetUnitCount() )
+ {
+ if( componentFlatList[ii].m_NumRef >= 0 )
+ tmp << componentFlatList[ii].m_NumRef;
+ else
+ tmp = wxT( "?" );
+
+ if( ( componentFlatList[ii].m_Unit > 0 )
+ && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
+ {
+ msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ),
+ componentFlatList[ii].m_Unit );
+ }
+ else
+ {
+ msg.Printf( _( "Multiple item %s%s\n" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ GetChars( tmp ) );
+ }
+
+ if( aMessageList )
+ aMessageList->Add( msg );
+
+ error++;
+ }
+
+ // Error if values are different between units, for the same reference
+ int next = ii + 1;
+
+ if( componentFlatList[ii].CompareValue( componentFlatList[next] ) != 0 )
+ {
+ msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ),
+ GetChars( componentFlatList[ii].GetRef() ),
+ componentFlatList[ii].m_NumRef,
+ GetChars( LIB_PART::SubReference(
+ componentFlatList[ii].m_Unit ) ),
+ GetChars( componentFlatList[ii].m_Value->GetText() ),
+ GetChars( componentFlatList[next].GetRef() ),
+ componentFlatList[next].m_NumRef,
+ GetChars( LIB_PART::SubReference(
+ componentFlatList[next].m_Unit ) ),
+ GetChars( componentFlatList[next].m_Value->GetText() ) );
+
+ if( aMessageList )
+ aMessageList->Add( msg + wxT( "\n" ));
+
+ error++;
+ }
+ }
+
+ // count the duplicated time stamps
+ SortByTimeStamp();
+
+ for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ )
+ {
+ if( ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
+ || ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() ) )
+ continue;
+
+ // Same time stamp found.
+ wxString full_path;
+
+ full_path.Printf( wxT( "%s%8.8X" ),
+ GetChars( componentFlatList[ii].GetSheetPath().Path() ),
+ componentFlatList[ii].m_TimeStamp );
+
+ msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
+ GetChars( full_path ),
+ GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef,
+ GetChars( componentFlatList[ii + 1].GetRef() ),
+ componentFlatList[ii + 1].m_NumRef );
+
+ if( aMessageList )
+ aMessageList->Add( msg + wxT( "\n" ));
+
+ error++;
+ }
+
+ return error;
+}
+
+
+SCH_REFERENCE::SCH_REFERENCE( SCH_COMPONENT* aComponent, LIB_PART* aLibComponent,
+ SCH_SHEET_PATH& aSheetPath )
+{
+ wxASSERT( aComponent != NULL && aLibComponent != NULL );
+
+ m_RootCmp = aComponent;
+ m_Entry = aLibComponent;
+ m_Unit = aComponent->GetUnitSelection( &aSheetPath );
+ m_SheetPath = aSheetPath;
+ m_IsNew = false;
+ m_Flag = 0;
+ m_TimeStamp = aComponent->GetTimeStamp();
+ m_CmpPos = aComponent->GetPosition();
+ m_SheetNum = 0;
+
+ if( aComponent->GetRef( &aSheetPath ).IsEmpty() )
+ aComponent->SetRef( &aSheetPath, wxT( "DefRef?" ) );
+
+ SetRef( aComponent->GetRef( &aSheetPath ) );
+
+ m_NumRef = -1;
+
+ if( aComponent->GetField( VALUE )->GetText().IsEmpty() )
+ aComponent->GetField( VALUE )->SetText( wxT( "~" ) );
+
+ m_Value = aComponent->GetField( VALUE );
+}
+
+
+void SCH_REFERENCE::Annotate()
+{
+ if( m_NumRef < 0 )
+ m_Ref += wxChar( '?' );
+ else
+ m_Ref = TO_UTF8( GetRef() << m_NumRef );
+
+ m_RootCmp->SetRef( &m_SheetPath, FROM_UTF8( m_Ref.c_str() ) );
+ m_RootCmp->SetUnit( m_Unit );
+ m_RootCmp->SetUnitSelection( &m_SheetPath, m_Unit );
+}
+
+
+void SCH_REFERENCE::Split()
+{
+ std::string refText = GetRefStr();
+
+ m_NumRef = -1;
+
+ int ll = refText.length() - 1;
+
+ if( refText[ll] == '?' )
+ {
+ m_IsNew = true;
+
+ if( !IsUnitsLocked() )
+ m_Unit = 0x7FFFFFFF;
+
+ refText.erase( ll ); // delete last char
+
+ SetRefStr( refText );
+ }
+ else if( isdigit( refText[ll] ) == 0 )
+ {
+ m_IsNew = true;
+
+ if( !IsUnitsLocked() )
+ m_Unit = 0x7FFFFFFF;
+ }
+ else
+ {
+ while( ll >= 0 )
+ {
+ if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) )
+ ll--;
+ else
+ {
+ if( isdigit( refText[ll + 1] ) )
+ {
+ // null terminated C string into cp
+ const char* cp = refText.c_str() + ll + 1;
+
+ m_NumRef = atoi( cp );
+ }
+
+ refText.erase( ll+1 ); // delete from ll+1 to end
+ break;
+ }
+ }
+
+ SetRefStr( refText );
+ }
+}
diff --git a/eeschema/component_tree_search_container.cpp b/eeschema/component_tree_search_container.cpp
new file mode 100644
index 00000000..c3061f95
--- /dev/null
+++ b/eeschema/component_tree_search_container.cpp
@@ -0,0 +1,443 @@
+/* -*- c++ -*-
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 Henner Zeller
+ * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+// Each node gets this lowest score initially, without any matches applied. Matches
+// will then increase this score depending on match quality.
+// This way, an empty search string will result in all components being displayed as they
+// have the minimum score. However, in that case, we avoid expanding all the nodes asd the
+// result is very unspecific.
+static const unsigned kLowestDefaultScore = 1;
+
+struct COMPONENT_TREE_SEARCH_CONTAINER::TREE_NODE
+{
+ // Levels of nodes.
+ enum NODE_TYPE {
+ TYPE_LIB,
+ TYPE_ALIAS,
+ TYPE_UNIT
+ };
+
+ TREE_NODE(NODE_TYPE aType, TREE_NODE* aParent, LIB_ALIAS* aAlias,
+ const wxString& aName, const wxString& aDisplayInfo,
+ const wxString& aSearchText )
+ : Type( aType ),
+ Parent( aParent ), Alias( aAlias ), Unit( 0 ),
+ DisplayName( aName ),
+ DisplayInfo( aDisplayInfo ),
+ MatchName( aName.Lower() ),
+ SearchText( aSearchText.Lower() ),
+ MatchScore( 0 ), PreviousScore( 0 )
+ {
+ }
+
+ const NODE_TYPE Type; ///< Type of node in the hierarchy.
+ TREE_NODE* const Parent; ///< NULL if library, pointer to parent when component/alias.
+ LIB_ALIAS* const Alias; ///< Component alias associated with this entry.
+ int Unit; ///< Part number; Assigned: >= 1; default = 0
+ const wxString DisplayName; ///< Exact name as displayed to the user.
+ const wxString DisplayInfo; ///< Additional info displayed in the tree (description..)
+
+ const wxString MatchName; ///< Preprocessed: lowercased display name.
+ const wxString SearchText; ///< Other text (keywords, description..) to search in.
+
+ unsigned MatchScore; ///< Result-Score after UpdateSearchTerm()
+ unsigned PreviousScore; ///< Optimization: used to see if we need any tree update.
+ wxTreeItemId TreeId; ///< Tree-ID if stored in the tree (if MatchScore > 0).
+};
+
+
+// Sort tree nodes by reverse match-score (bigger is first), then alphabetically.
+// Library (i.e. the ones that don't have a parent) are always sorted before any
+// leaf nodes. Component
+bool COMPONENT_TREE_SEARCH_CONTAINER::scoreComparator( const TREE_NODE* a1, const TREE_NODE* a2 )
+{
+ if( a1->Type != a2->Type )
+ return a1->Type < a2->Type;
+
+ if( a1->MatchScore != a2->MatchScore )
+ return a1->MatchScore > a2->MatchScore; // biggest first.
+
+ if( a1->Parent != a2->Parent )
+ return scoreComparator( a1->Parent, a2->Parent );
+
+ return a1->MatchName.Cmp( a2->MatchName ) < 0;
+}
+
+
+COMPONENT_TREE_SEARCH_CONTAINER::COMPONENT_TREE_SEARCH_CONTAINER( PART_LIBS* aLibs )
+ : m_tree( NULL ),
+ m_libraries_added( 0 ),
+ m_components_added( 0 ),
+ m_preselect_unit_number( -1 ),
+ m_libs( aLibs ),
+ m_filter( CMP_FILTER_NONE )
+{
+}
+
+
+COMPONENT_TREE_SEARCH_CONTAINER::~COMPONENT_TREE_SEARCH_CONTAINER()
+{
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ delete node;
+ m_nodes.clear();
+}
+
+
+void COMPONENT_TREE_SEARCH_CONTAINER::SetPreselectNode( const wxString& aComponentName,
+ int aUnit )
+{
+ m_preselect_node_name = aComponentName.Lower();
+ m_preselect_unit_number = aUnit;
+}
+
+
+void COMPONENT_TREE_SEARCH_CONTAINER::SetTree( wxTreeCtrl* aTree )
+{
+ m_tree = aTree;
+ UpdateSearchTerm( wxEmptyString );
+}
+
+
+void COMPONENT_TREE_SEARCH_CONTAINER::AddLibrary( PART_LIB& aLib )
+{
+ wxArrayString all_aliases;
+
+ if( m_filter == CMP_FILTER_POWER )
+ aLib.GetEntryTypePowerNames( all_aliases );
+ else
+ aLib.GetEntryNames( all_aliases );
+
+ AddAliasList( aLib.GetName(), all_aliases, &aLib );
+
+ ++m_libraries_added;
+}
+
+
+void COMPONENT_TREE_SEARCH_CONTAINER::AddAliasList( const wxString& aNodeName,
+ const wxArrayString& aAliasNameList,
+ PART_LIB* aOptionalLib )
+{
+ TREE_NODE* const lib_node = new TREE_NODE( TREE_NODE::TYPE_LIB, NULL, NULL,
+ aNodeName, wxEmptyString, wxEmptyString );
+ m_nodes.push_back( lib_node );
+
+ BOOST_FOREACH( const wxString& aName, aAliasNameList )
+ {
+ LIB_ALIAS* a;
+
+ if( aOptionalLib )
+ a = aOptionalLib->FindAlias( aName );
+ else
+ a = m_libs->FindLibraryEntry( aName, wxEmptyString );
+
+ if( a == NULL )
+ continue;
+
+ wxString search_text;
+ search_text = ( a->GetKeyWords().empty() ) ? wxT(" ") : a->GetKeyWords();
+ search_text += a->GetDescription();
+
+ wxString display_info;
+
+ if( !a->GetDescription().empty() )
+ {
+ // Preformatting. Unfortunately, the tree widget doesn't have columns
+ // and using tabs does not work very well or does not work at all
+ // (depending on OS versions). So indent with spaces in fixed-font width.
+
+ // The 98%-ile of length of strings found in the standard library is 15
+ // characters. Use this as a reasonable cut-off point for aligned indentation.
+ // For the few component names longer than that, the description is indented a
+ // bit more.
+ // The max found in the default lib would be 20 characters, but that creates too
+ // much visible whitespace for the less extreme component names.
+ const int COLUMN_DESCR_POS = 15;
+ const int indent_len = COLUMN_DESCR_POS - a->GetName().length();
+ display_info = wxString::Format( wxT( " %*s [ %s ]" ),
+ indent_len > 0 ? indent_len : 0, wxT( "" ),
+ GetChars( a->GetDescription() ) );
+ }
+
+ TREE_NODE* alias_node = new TREE_NODE( TREE_NODE::TYPE_ALIAS, lib_node,
+ a, a->GetName(), display_info, search_text );
+ m_nodes.push_back( alias_node );
+
+ if( a->GetPart()->IsMulti() ) // Add all units as sub-nodes.
+ {
+ for( int u = 1; u <= a->GetPart()->GetUnitCount(); ++u )
+ {
+ wxString unitName = _("Unit");
+ unitName += wxT( " " ) + LIB_PART::SubReference( u, false );
+ TREE_NODE* unit_node = new TREE_NODE( TREE_NODE::TYPE_UNIT,
+ alias_node, a,
+ unitName,
+ wxEmptyString, wxEmptyString );
+ unit_node->Unit = u;
+ m_nodes.push_back( unit_node );
+ }
+ }
+
+ ++m_components_added;
+ }
+}
+
+
+LIB_ALIAS* COMPONENT_TREE_SEARCH_CONTAINER::GetSelectedAlias( int* aUnit )
+{
+ if( m_tree == NULL )
+ return NULL;
+
+ const wxTreeItemId& select_id = m_tree->GetSelection();
+
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ {
+ if( node->MatchScore > 0 && node->TreeId == select_id ) {
+ if( aUnit && node->Unit > 0 )
+ *aUnit = node->Unit;
+ return node->Alias;
+ }
+ }
+ return NULL;
+}
+
+
+// Creates a score depending on the position of a string match. If the position
+// is 0 (= prefix match), this returns the maximum score. This degrades until
+// pos == max, which returns a score of 0;
+// Evertyhing else beyond that is just 0. Only values >= 0 allowed for position and max.
+//
+// @param aPosition is the position a string has been found in a substring.
+// @param aMaximum is the maximum score this function returns.
+// @return position dependent score.
+static int matchPosScore(int aPosition, int aMaximum)
+{
+ return ( aPosition < aMaximum ) ? aMaximum - aPosition : 0;
+}
+
+
+void COMPONENT_TREE_SEARCH_CONTAINER::UpdateSearchTerm( const wxString& aSearch )
+{
+ if( m_tree == NULL )
+ return;
+//#define SHOW_CALC_TIME // uncomment this to show calculation time
+
+#ifdef SHOW_CALC_TIME
+ unsigned starttime = GetRunningMicroSecs();
+#endif
+
+ // We score the list by going through it several time, essentially with a complexity
+ // of O(n). For the default library of 2000+ items, this typically takes less than 5ms
+ // on an i5. Good enough, no index needed.
+
+ // Initial AND condition: Leaf nodes are considered to match initially.
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ {
+ node->PreviousScore = node->MatchScore;
+ node->MatchScore = ( node->Type == TREE_NODE::TYPE_LIB ) ? 0 : kLowestDefaultScore;
+ }
+
+ // Create match scores for each node for all the terms, that come space-separated.
+ // Scoring adds up values for each term according to importance of the match. If a term does
+ // not match at all, the result is thrown out of the results (AND semantics).
+ // From high to low
+ // - Exact match for a ccmponent name gives the highest score, trumping all.
+ // - A positional score depending of where a term is found as substring; prefix-match: high.
+ // - substring-match in library name.
+ // - substring match in keywords and descriptions with positional score. Keywords come
+ // first so contribute more to the score.
+ //
+ // This is of course subject to tweaking.
+ wxStringTokenizer tokenizer( aSearch );
+
+ while ( tokenizer.HasMoreTokens() )
+ {
+ const wxString term = tokenizer.GetNextToken().Lower();
+
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ {
+ if( node->Type != TREE_NODE::TYPE_ALIAS )
+ continue; // Only aliases are actually scored here.
+
+ if( node->MatchScore == 0)
+ continue; // Leaf node without score are out of the game.
+
+ // Keywords and description we only count if the match string is at
+ // least two characters long. That avoids spurious, low quality
+ // matches. Most abbreviations are at three characters long.
+ int found_pos;
+
+ if( term == node->MatchName )
+ node->MatchScore += 1000; // exact match. High score :)
+ else if( (found_pos = node->MatchName.Find( term ) ) != wxNOT_FOUND )
+ {
+ // Substring match. The earlier in the string the better. score += 20..40
+ node->MatchScore += matchPosScore( found_pos, 20 ) + 20;
+ }
+ else if( node->Parent->MatchName.Find( term ) != wxNOT_FOUND )
+ node->MatchScore += 19; // parent name matches. score += 19
+ else if( ( found_pos = node->SearchText.Find( term ) ) != wxNOT_FOUND )
+ {
+ // If we have a very short search term (like one or two letters), we don't want
+ // to accumulate scores if they just happen to be in keywords or description as
+ // almost any one or two-letter combination shows up in there.
+ // For longer terms, we add scores 1..18 for positional match (higher in the
+ // front, where the keywords are). score += 0..18
+ node->MatchScore += ( ( term.length() >= 2 )
+ ? matchPosScore( found_pos, 17 ) + 1
+ : 0 );
+ }
+ else
+ node->MatchScore = 0; // No match. That's it for this item.
+ }
+ }
+
+ // Library nodes have the maximum score seen in any of their children.
+ // Alias nodes have the score of their parents.
+ unsigned highest_score_seen = 0;
+ bool any_change = false;
+
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ {
+ switch( node->Type )
+ {
+ case TREE_NODE::TYPE_ALIAS:
+ {
+ any_change |= (node->PreviousScore != node->MatchScore);
+ // Update library score.
+ node->Parent->MatchScore = std::max( node->Parent->MatchScore, node->MatchScore );
+ highest_score_seen = std::max( highest_score_seen, node->MatchScore );
+ }
+ break;
+
+ case TREE_NODE::TYPE_UNIT:
+ node->MatchScore = node->Parent->MatchScore;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // The tree update might be slow, so we want to bail out if there is no change.
+ if( !any_change )
+ return;
+
+ // Now: sort all items according to match score, libraries first.
+ std::sort( m_nodes.begin(), m_nodes.end(), scoreComparator );
+
+#ifdef SHOW_CALC_TIME
+ unsigned sorttime = GetRunningMicroSecs();
+#endif
+
+ // Fill the tree with all items that have a match. Re-arranging, adding and removing changed
+ // items is pretty complex, so we just re-build the whole tree.
+ m_tree->Freeze();
+ m_tree->DeleteAllItems();
+ const wxTreeItemId root_id = m_tree->AddRoot( wxEmptyString );
+ const TREE_NODE* first_match = NULL;
+ const TREE_NODE* preselected_node = NULL;
+
+ BOOST_FOREACH( TREE_NODE* node, m_nodes )
+ {
+ if( node->MatchScore == 0 )
+ continue;
+
+ // If we have nodes that go beyond the default score, suppress nodes that
+ // have the default score. That can happen if they have an honary += 0 score due to
+ // some one-letter match in the keyword or description. In this case, we prefer matches
+ // that just have higher scores. Improves relevancy and performance as the tree has to
+ // display less items.
+ if( highest_score_seen > kLowestDefaultScore && node->MatchScore == kLowestDefaultScore )
+ continue;
+
+ wxString node_text;
+#if 0
+ // Node text with scoring information for debugging
+ node_text.Printf( wxT("%s (s=%u)%s"), GetChars(node->DisplayName),
+ node->MatchScore, GetChars( node->DisplayInfo ));
+#else
+ node_text = node->DisplayName + node->DisplayInfo;
+#endif
+ node->TreeId = m_tree->AppendItem( node->Parent ? node->Parent->TreeId : root_id,
+ node_text );
+
+ // If we are a nicely scored alias, we want to have it visible. Also, if there
+ // is only a single library in this container, we want to have it unfolded
+ // (example: power library).
+ if( node->Type == TREE_NODE::TYPE_ALIAS
+ && ( node->MatchScore > kLowestDefaultScore || m_libraries_added == 1 ) )
+ {
+ m_tree->Expand( node->TreeId );
+
+ if( first_match == NULL )
+ first_match = node; // First, highest scoring: the "I am feeling lucky" element.
+ }
+
+ // The first node that matches our pre-select criteria is choosen. 'First node'
+ // means, it shows up in the history, as the history node is displayed very first
+ // (by virtue of alphabetical ordering)
+ if( preselected_node == NULL
+ && node->Type == TREE_NODE::TYPE_ALIAS
+ && node->MatchName == m_preselect_node_name )
+ preselected_node = node;
+
+ // Refinement in case we come accross a matching unit node.
+ if( preselected_node != NULL && preselected_node->Type == TREE_NODE::TYPE_ALIAS
+ && node->Parent == preselected_node
+ && m_preselect_unit_number >= 1 && node->Unit == m_preselect_unit_number )
+ preselected_node = node;
+ }
+
+ if( first_match ) // Highest score search match pre-selected.
+ {
+ m_tree->SelectItem( first_match->TreeId );
+ m_tree->EnsureVisible( first_match->TreeId );
+ }
+ else if( preselected_node ) // No search, so history item preselected.
+ {
+ m_tree->SelectItem( preselected_node->TreeId );
+ m_tree->EnsureVisible( preselected_node->TreeId );
+ }
+
+ m_tree->Thaw();
+
+#ifdef SHOW_CALC_TIME
+ unsigned endtime = GetRunningMicroSecs();
+ wxLogMessage( wxT("sort components %.1f ms, rebuild tree %.1f ms"),
+ double(sorttime-starttime)/1000.0, double(endtime-sorttime)/1000.0 );
+#endif
+}
diff --git a/eeschema/component_tree_search_container.h b/eeschema/component_tree_search_container.h
new file mode 100644
index 00000000..9d75f918
--- /dev/null
+++ b/eeschema/component_tree_search_container.h
@@ -0,0 +1,145 @@
+/* -*- c++ -*-
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2014 Henner Zeller
+ * Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http: *www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http: *www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef COMPONENT_TREE_SEARCH_CONTAINER_H
+#define COMPONENT_TREE_SEARCH_CONTAINER_H
+
+#include
+#include
+
+class LIB_ALIAS;
+class PART_LIB;
+class PART_LIBS;
+class wxTreeCtrl;
+class wxArrayString;
+
+// class COMPONENT_TREE_SEARCH_CONTAINER
+// A container for components that allows to search them matching their name, keywords
+// and descriptions, updating a wxTreeCtrl with the results (toplevel nodes:
+// libraries, leafs: components), scored by relevance.
+//
+// The scored result list is adpated on each update on the search-term: this allows
+// to have a search-as-you-type experience.
+class COMPONENT_TREE_SEARCH_CONTAINER
+{
+public:
+ /** This enum allows a selective filtering of component to list
+ * currently: no filtering
+ * list power components only
+ */
+ enum CMP_FILTER_TYPE
+ {
+ CMP_FILTER_NONE, ///< no filtering
+ CMP_FILTER_POWER ///< list components flagged PWR
+ };
+
+public:
+ COMPONENT_TREE_SEARCH_CONTAINER( PART_LIBS* aLibs );
+ ~COMPONENT_TREE_SEARCH_CONTAINER();
+
+ void SetFilter( CMP_FILTER_TYPE aFilter )
+ {
+ m_filter = aFilter;
+ }
+
+ /** Function AddLibrary
+ * Add all the components and their aliases of this library to be searched.
+ * To be called in the setup phase to fill this container.
+ *
+ * @param aLib containting all the components to be added.
+ */
+ void AddLibrary( PART_LIB& aLib );
+
+ /** Function AddComponentList
+ * Add the given list of components, given by name, to be searched.
+ * To be called in the setup phase to fill this container.
+ *
+ * @param aNodeName The parent node name the components will show up as leaf.
+ * @param aAliasNameList List of alias names.
+ * @param aOptionalLib Library to look up the component names (if NULL: global lookup)
+ */
+ void AddAliasList( const wxString& aNodeName, const wxArrayString& aAliasNameList,
+ PART_LIB* aOptionalLib );
+
+ /** Function SetPreselectNode
+ * Set the component name to be selected in absence of any search-result.
+ *
+ * @param aComponentName the component name to be selected.
+ * @param aUnit the component unit to be selected (if > 0).
+ */
+ void SetPreselectNode( const wxString& aComponentName, int aUnit );
+
+ /** Function SetTree
+ * Set the tree to be manipulated.
+ * Each update of the search term will update the tree, with the most
+ * scoring component at the top and selected. If a preselect node is set, this
+ * is displayed. Does not take ownership of the tree.
+ *
+ * @param aTree that is to be modified on search updates.
+ */
+ void SetTree( wxTreeCtrl* aTree );
+
+ /** Function UpdateSearchTerm
+ * Update the search string provided by the user and narrow down the result list.
+ *
+ * This string is a space-separated list of terms, each of which
+ * is applied to the components list to narrow it down. Results are scored by
+ * relevancy (e.g. exact match scores higher than prefix-match which in turn scores
+ * higher than substring match). This updates the search and tree on each call.
+ *
+ * @param aSearch is the user-provided search string.
+ */
+ void UpdateSearchTerm( const wxString& aSearch );
+
+ /** Function GetSelectedAlias
+ *
+ * @param aUnit : if not NULL, the selected sub-unit is set here.
+ * @return the selected alias or NULL if there is none, or there is no tree.
+ */
+ LIB_ALIAS* GetSelectedAlias( int* aUnit );
+
+ /**
+ * Function GetComponentsCount
+ * @return the number of components loaded in the tree
+ */
+ int GetComponentsCount() { return m_components_added; }
+
+
+private:
+ struct TREE_NODE;
+ static bool scoreComparator( const TREE_NODE* a1, const TREE_NODE* a2 );
+
+ std::vector m_nodes;
+ wxTreeCtrl* m_tree;
+ int m_libraries_added;
+ int m_components_added;
+
+ wxString m_preselect_node_name;
+ int m_preselect_unit_number;
+
+ PART_LIBS* m_libs; // no ownership
+
+ enum CMP_FILTER_TYPE m_filter; // the current filter
+};
+
+#endif /* COMPONENT_TREE_SEARCH_CONTAINER_H */
diff --git a/eeschema/controle.cpp b/eeschema/controle.cpp
new file mode 100644
index 00000000..cfd7c6e8
--- /dev/null
+++ b/eeschema/controle.cpp
@@ -0,0 +1,326 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 2008-2011 Wayne Stambaugh
+ * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * eeschema/controle.cpp
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+SCH_ITEM* SCH_EDIT_FRAME::LocateAndShowItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
+ int aHotKeyCommandId )
+{
+ SCH_ITEM* item;
+ LIB_PIN* Pin = NULL;
+ SCH_COMPONENT* LibItem = NULL;
+ wxPoint gridPosition = GetNearestGridPosition( aPosition );
+
+ // Check the on grid position first. There is more likely to be multiple items on
+ // grid than off grid.
+ item = LocateItem( gridPosition, aFilterList, aHotKeyCommandId );
+
+ // If the user aborted the clarification context menu, don't show it again at the
+ // off grid position.
+ if( !item && m_canvas->GetAbortRequest() )
+ {
+ m_canvas->SetAbortRequest( false );
+ return NULL;
+ }
+
+ if( !item && (aPosition != gridPosition) )
+ item = LocateItem( aPosition, aFilterList, aHotKeyCommandId );
+
+ if( !item )
+ {
+ m_canvas->SetAbortRequest( false ); // Just in case the user aborted the context menu.
+ return NULL;
+ }
+
+ // Cross probing to Pcbnew if a pin or a component is found
+ switch( item->Type() )
+ {
+ case SCH_FIELD_T:
+ case LIB_FIELD_T:
+ LibItem = (SCH_COMPONENT*) item->GetParent();
+ SendMessageToPCBNEW( item, LibItem );
+ break;
+
+ case SCH_COMPONENT_T:
+ LibItem = (SCH_COMPONENT*) item;
+ SendMessageToPCBNEW( item, LibItem );
+ break;
+
+ case LIB_PIN_T:
+ Pin = (LIB_PIN*) item;
+ LibItem = (SCH_COMPONENT*) LocateItem( aPosition, SCH_COLLECTOR::ComponentsOnly );
+ break;
+
+ default:
+ ;
+ }
+
+ if( Pin )
+ {
+ // Force display pin information (the previous display could be a component info)
+ MSG_PANEL_ITEMS items;
+
+ Pin->GetMsgPanelInfo( items );
+
+ if( LibItem )
+ items.push_back( MSG_PANEL_ITEM( LibItem->GetRef( m_CurrentSheet ),
+ LibItem->GetField( VALUE )->GetShownText(), DARKCYAN ) );
+
+ SetMsgPanel( items );
+
+ // Cross probing:2 - pin found, and send a locate pin command to Pcbnew (highlight net)
+ SendMessageToPCBNEW( Pin, LibItem );
+ }
+
+ return item;
+}
+
+
+SCH_ITEM* SCH_EDIT_FRAME::LocateItem( const wxPoint& aPosition, const KICAD_T aFilterList[],
+ int aHotKeyCommandId )
+{
+ SCH_ITEM* item = NULL;
+
+ m_collectedItems.Collect( GetScreen()->GetDrawItems(), aFilterList, aPosition );
+
+ if( m_collectedItems.GetCount() == 0 )
+ {
+ ClearMsgPanel();
+ }
+ else if( m_collectedItems.GetCount() == 1 )
+ {
+ item = m_collectedItems[0];
+ }
+ else
+ {
+ // There are certain combinations of items that do not need clarification such as
+ // a corner were two lines meet or all the items form a junction.
+ if( aHotKeyCommandId )
+ {
+ switch( aHotKeyCommandId )
+ {
+ case HK_DRAG:
+ if( m_collectedItems.IsCorner() || m_collectedItems.IsNode( false )
+ || m_collectedItems.IsDraggableJunction() )
+ {
+ item = m_collectedItems[0];
+ }
+ default:
+ ;
+ }
+ }
+
+ if( item == NULL )
+ {
+ wxASSERT_MSG( m_collectedItems.GetCount() <= MAX_SELECT_ITEM_IDS,
+ wxT( "Select item clarification context menu size limit exceeded." ) );
+
+ wxMenu selectMenu;
+ wxMenuItem* title = new wxMenuItem( &selectMenu, wxID_NONE, _( "Clarify Selection" ) );
+
+ selectMenu.Append( title );
+ selectMenu.AppendSeparator();
+
+ for( int i = 0; i < m_collectedItems.GetCount() && i < MAX_SELECT_ITEM_IDS; i++ )
+ {
+ wxString text = m_collectedItems[i]->GetSelectMenuText();
+ BITMAP_DEF xpm = m_collectedItems[i]->GetMenuImage();
+ AddMenuItem( &selectMenu, ID_SELECT_ITEM_START + i, text, KiBitmap( xpm ) );
+ }
+
+ // Set to NULL in case user aborts the clarification context menu.
+ GetScreen()->SetCurItem( NULL );
+ m_canvas->SetAbortRequest( true ); // Changed to false if an item is selected
+ PopupMenu( &selectMenu );
+ m_canvas->MoveCursorToCrossHair();
+ item = GetScreen()->GetCurItem();
+ }
+ }
+
+ GetScreen()->SetCurItem( item );
+
+ if( item )
+ {
+ if( item->Type() == SCH_COMPONENT_T )
+ ( (SCH_COMPONENT*) item )->SetCurrentSheetPath( &GetCurrentSheet() );
+
+ MSG_PANEL_ITEMS items;
+ item->GetMsgPanelInfo( items );
+ SetMsgPanel( items );
+ }
+ else
+ {
+ ClearMsgPanel();
+ }
+
+ return item;
+}
+
+
+bool SCH_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
+{
+ bool eventHandled = true;
+
+ // Filter out the 'fake' mouse motion after a keyboard movement
+ if( !aHotKey && m_movingCursorWithKeyboard )
+ {
+ m_movingCursorWithKeyboard = false;
+ return false;
+ }
+
+ // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
+ // for next cursor position
+ // ( shift or ctrl key down are PAN command with mouse wheel)
+ bool snapToGrid = true;
+
+ if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
+ snapToGrid = false;
+
+ // Cursor is left off grid only if no block in progress
+ if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+ snapToGrid = true;
+
+ wxPoint pos = aPosition;
+ wxPoint oldpos = GetCrossHairPosition();
+ GeneralControlKeyMovement( aHotKey, &pos, snapToGrid );
+
+ // Update cursor position.
+ SetCrossHairPosition( pos, snapToGrid );
+ RefreshCrossHair( oldpos, aPosition, aDC );
+
+ if( aHotKey )
+ {
+ SCH_SCREEN* screen = GetScreen();
+
+ if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
+ eventHandled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
+ else
+ eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
+ }
+
+ UpdateStatusBar(); /* Display cursor coordinates info */
+
+ return eventHandled;
+}
+
+
+bool LIB_EDIT_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
+{
+ bool eventHandled = true;
+
+ // Filter out the 'fake' mouse motion after a keyboard movement
+ if( !aHotKey && m_movingCursorWithKeyboard )
+ {
+ m_movingCursorWithKeyboard = false;
+ return false;
+ }
+
+ // when moving mouse, use the "magnetic" grid, unless the shift+ctrl keys is pressed
+ // for next cursor position
+ // ( shift or ctrl key down are PAN command with mouse wheel)
+ bool snapToGrid = true;
+
+ if( !aHotKey && wxGetKeyState( WXK_SHIFT ) && wxGetKeyState( WXK_CONTROL ) )
+ snapToGrid = false;
+
+ // Cursor is left off grid only if no block in progress
+ if( GetScreen()->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+ snapToGrid = true;
+
+ wxPoint pos = aPosition;
+ wxPoint oldpos = GetCrossHairPosition();
+ GeneralControlKeyMovement( aHotKey, &pos, snapToGrid );
+
+ // Update the cursor position.
+ SetCrossHairPosition( pos, snapToGrid );
+ RefreshCrossHair( oldpos, aPosition, aDC );
+
+ if( aHotKey )
+ {
+ eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
+ }
+
+ UpdateStatusBar();
+
+ return eventHandled;
+}
+
+
+bool LIB_VIEW_FRAME::GeneralControl( wxDC* aDC, const wxPoint& aPosition, int aHotKey )
+{
+ bool eventHandled = true;
+
+ // Filter out the 'fake' mouse motion after a keyboard movement
+ if( !aHotKey && m_movingCursorWithKeyboard )
+ {
+ m_movingCursorWithKeyboard = false;
+ return false;
+ }
+
+ wxPoint pos = aPosition;
+ wxPoint oldpos = GetCrossHairPosition();
+ GeneralControlKeyMovement( aHotKey, &pos, true );
+
+ // Update cursor position.
+ SetCrossHairPosition( pos, true );
+ RefreshCrossHair( oldpos, aPosition, aDC );
+
+ if( aHotKey )
+ {
+ SCH_SCREEN* screen = GetScreen();
+
+ if( screen->GetCurItem() && screen->GetCurItem()->GetFlags() )
+ eventHandled = OnHotKey( aDC, aHotKey, aPosition, screen->GetCurItem() );
+ else
+ eventHandled = OnHotKey( aDC, aHotKey, aPosition, NULL );
+ }
+
+ UpdateStatusBar(); // Display cursor coordinates info.
+
+ return eventHandled;
+}
diff --git a/eeschema/cross-probing.cpp b/eeschema/cross-probing.cpp
new file mode 100644
index 00000000..f9b67e77
--- /dev/null
+++ b/eeschema/cross-probing.cpp
@@ -0,0 +1,214 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 2011 Wayne Stambaugh
+ * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * @file eeschema/cross-probing.cpp
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+
+/**
+ * Execute a remote command sent by Pcbnew via a socket connection.
+ *
+ * When user selects a module or pin in Pcbnew, Eeschema shows that same
+ * component or pin and moves cursor on the item. The socket port used
+ * is #KICAD_SCH_PORT_SERVICE_NUMBER which defaults to 4243.
+ *
+ * Valid commands are:
+ * \li \c \$PART: \c "reference" Put cursor on component.
+ * \li \c \$PART: \c "reference" \c \$REF: \c "ref" Put cursor on component reference.
+ * \li \c \$PART: \c "reference" \c \$VAL: \c "value" Put cursor on component value.
+ * \li \c \$PART: \c "reference" \c \$PAD: \c "pin name" Put cursor on the component pin.
+ *
+ * @param cmdline = received command from Pcbnew
+ */
+void SCH_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
+{
+ char line[1024];
+
+ strncpy( line, cmdline, sizeof(line) - 1 );
+ line[ sizeof(line) - 1 ] = '\0';
+
+ char* idcmd = strtok( line, " \n\r" );
+ char* text = strtok( NULL, "\"\n\r" );
+
+ if( (idcmd == NULL) || (text == NULL) )
+ return;
+
+ if( strcmp( idcmd, "$PART:" ) != 0 )
+ return;
+
+ wxString part_ref = FROM_UTF8( text );
+
+ /* look for a complement */
+ idcmd = strtok( NULL, " \n\r" );
+
+ if( idcmd == NULL ) // component only
+ {
+ FindComponentAndItem( part_ref, true, FIND_COMPONENT_ONLY, wxEmptyString, false );
+ return;
+ }
+
+ text = strtok( NULL, "\"\n\r" );
+
+ if( text == NULL )
+ return;
+
+ wxString msg = FROM_UTF8( text );
+
+ if( strcmp( idcmd, "$REF:" ) == 0 )
+ {
+ FindComponentAndItem( part_ref, true, FIND_REFERENCE, msg, false );
+ }
+ else if( strcmp( idcmd, "$VAL:" ) == 0 )
+ {
+ FindComponentAndItem( part_ref, true, FIND_VALUE, msg, false );
+ }
+ else if( strcmp( idcmd, "$PAD:" ) == 0 )
+ {
+ FindComponentAndItem( part_ref, true, FIND_PIN, msg, false );
+ }
+ else
+ {
+ FindComponentAndItem( part_ref, true, FIND_COMPONENT_ONLY, wxEmptyString, false );
+ }
+}
+
+
+std::string FormatProbeItem( EDA_ITEM* aComponent, SCH_COMPONENT* aPart )
+{
+ // Cross probing to Pcbnew if a pin or a component is found
+ switch( aComponent->Type() )
+ {
+ case SCH_FIELD_T:
+ case LIB_FIELD_T:
+ {
+ if( !aPart )
+ break;
+
+ return StrPrintf( "$PART: %s", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
+ }
+ break;
+
+ case SCH_COMPONENT_T:
+ aPart = (SCH_COMPONENT*) aComponent;
+ return StrPrintf( "$PART: %s", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
+
+ case LIB_PIN_T:
+ {
+ if( !aPart )
+ break;
+
+ LIB_PIN* pin = (LIB_PIN*) aComponent;
+
+ if( pin->GetNumber() )
+ {
+ wxString pinnum;
+
+ pin->PinStringNum( pinnum );
+
+ return StrPrintf( "$PIN: %s $PART: %s", TO_UTF8( pinnum ),
+ TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
+ }
+ else
+ {
+ return StrPrintf( "$PART: %s", TO_UTF8( aPart->GetField( REFERENCE )->GetText() ) );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return "";
+}
+
+
+void SCH_EDIT_FRAME::SendMessageToPCBNEW( EDA_ITEM* aComponent, SCH_COMPONENT* aPart )
+{
+#if 1
+ wxASSERT( aComponent ); // fix the caller
+
+#else // WTF?
+ if( !aComponent ) // caller remains eternally stupid.
+ return;
+#endif
+
+ std::string packet = FormatProbeItem( aComponent, aPart );
+
+ if( packet.size() )
+ {
+ if( Kiface().IsSingle() )
+ SendCommand( MSG_TO_PCB, packet.c_str() );
+ else
+ {
+ // Typically ExpressMail is going to be s-expression packets, but since
+ // we have existing interpreter of the cross probe packet on the other
+ // side in place, we use that here.
+ Kiway().ExpressMail( FRAME_PCB, MAIL_CROSS_PROBE, packet, this );
+ }
+ }
+}
+
+
+void SCH_EDIT_FRAME::KiwayMailIn( KIWAY_EXPRESS& mail )
+{
+ const std::string& payload = mail.GetPayload();
+
+ switch( mail.Command() )
+ {
+ case MAIL_CROSS_PROBE:
+ ExecuteRemoteCommand( payload.c_str() );
+ break;
+
+ case MAIL_BACKANNOTATE_FOOTPRINTS:
+ try
+ {
+ backAnnotateFootprints( payload );
+ }
+ catch( const IO_ERROR& ioe )
+ {
+ DBG( printf( "%s: ioe:%s\n", __func__, TO_UTF8( ioe.errorText ) );)
+ }
+ break;
+
+ default:
+ ;
+ }
+}
diff --git a/eeschema/dialog_erc_listbox.h b/eeschema/dialog_erc_listbox.h
new file mode 100644
index 00000000..65bde96c
--- /dev/null
+++ b/eeschema/dialog_erc_listbox.h
@@ -0,0 +1,120 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef DIALOG_ERC_LISTBOX_H
+#define DIALOG_ERC_LISTBOX_H
+
+#include
+
+#include
+#include
+#include
+#include
+
+/**
+ * Class ERC_HTML_LISTFRAME
+ * is used to display a DRC_ITEM_LIST.
+ */
+class ERC_HTML_LISTFRAME : public wxHtmlWindow
+{
+private:
+ std::vector m_MarkerListReferences; // The pointers to markers shown in list
+
+public:
+ ERC_HTML_LISTFRAME( wxWindow* parent, wxWindowID id = wxID_ANY,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = 0 ) :
+ wxHtmlWindow( parent, id, pos, size, style | wxHW_NO_SELECTION )
+ {
+ }
+
+ ~ERC_HTML_LISTFRAME()
+ {
+ }
+
+
+ /**
+ * Function AppendToList
+ * @param aItem The SCH_MARKER* to add to the current list which will be
+ * later displayed in the wxHtmlWindow
+ */
+ void AppendToList( SCH_MARKER* aMarker )
+ {
+ m_MarkerListReferences.push_back( aMarker );
+ }
+
+ /**
+ * Function DisplayList();
+ * Build the Html marker list and show it
+ */
+ void DisplayList()
+ {
+ wxString htmlpage;
+
+ // for each marker, build a link like:
+ // text to click
+ // The "text to click" is the error name (first line of the full error text).
+ wxString marker_text;
+
+ for( unsigned ii = 0; ii < m_MarkerListReferences.size(); ii++ )
+ {
+ marker_text.Printf( wxT( "" ), ii );
+ marker_text << m_MarkerListReferences[ii]->GetReporter().ShowHtml();
+ marker_text.Replace( wxT( "
+The
+Eeschema documentationdescribes
+this intermediate netlist and gives examples See
+also https://answers.launchpad.net/kicad/+faq/2265
+
2 - The intermediate Netlist File
+
+BOM
+files (and netlist files) can be created from an Intermediate netlist
+file created by Eeschema.
+
+This
+file uses XML syntax and is called the intermediate netlist. The
+intermediate netlist includes a large amount of data about your board
+and because of this, it can be used with post-processing to create a
+BOM or other reports.
+
+Depending
+on the output (BOM or netlist), different subsets of the complete
+Intermediate Netlist file will be used in the post-processing.
+
3 - Conversion to a new format
+
+By
+applying a post-processing filter to the Intermediate netlist file
+you can generate foreign netlist files as well as BOM files. Because
+this conversion is a text to text transformation.
+
+this
+post-processing filter can be written using Python, XSLT,
+or any other tool capable of taking XML as input.
+
+XSLT
+itself is a XML language very suitable for XML transformations. There
+is a free program called xsltproc
+that
+you can download and install. The
+xsltproc
+program can be used to read the Intermediate XML netlist input file,
+applya
+style-sheet to transform the input, and save the results in an output
+file. Use of xsltproc requires a style-sheet file using XSLT
+conventions. The full conversion process is handled
+by
+Eeschema, after it is configured once to run xsltproc in a specific
+way.
+
+A
+Python script is somewhat more easy to create.
+
4 - Initialization of the dialog window
+
+You
+should add a new pluging (a script) in plugin list by clicking on the
+Add Plugin button.
+
4.1 - Plugin Configuration Parameters
+
+The
+Eeschema plug-in configuration dialog requires the following
+information:
+
+
+
+ The
+ title: for instance, the name of the netlist format.
+
+
+ The
+ command line to launch the converter (usually a script).
+
+
+Once
+you click on the generate button the following will happen:
+
+
+
+ Eeschema
+ creates an intermediate netlist file *.xml, for instance test.xml.
+
+
+ Eeschema
+ runs the script from the command line to create the final output
+ file.
+
+
4.2 - Generate netlist files with the command
+line
+
+Assuming
+we are using the program xsltproc.exe
+to
+apply the sheet style to the intermediate file, xsltproc.exe
+is
+executed with the following command.
+
+xsltproc.exe
+-o < output filename > < style-sheet filename > <
+input XML file to convert >
+
+On
+Windows the command line is the following. f:/kicad/bin/xsltproc.exe
+-o “%O” f:/kicad/bin/plugins/myconverter.xsl “%I”
+
+On
+Linux the command becomes as following. xsltproc -o “%O”
+/usr/local/kicad/bin/plugins/myconverter .xsl “%I” where
+myconverter.xsl
+is
+the style-sheet that you are applying.
+
+Do
+not forget the double quotes
+around
+the file names, this allows them to have spaces after the
+substitution by Eeschema.
+
+If
+a Python script is used, the command line is something like
+(depending on the Python script):
+
+python
+f:/kicad/bin/plugins/bom-in-python/myconverter.py
+“%I”“%O” or python
+/usr/local/kicad/bin/plugins/bom-in-python/myconverter .xsl “%I”
+“%O”
+
+
+The
+command line format accepts parameters for filenames:
+
+The
+supported formatting parameters are.
+
+
+
+ %B
+ => base filename of selected output file, minus path and extension.
+
+
+ %P
+ => project directory, without name and without trailing '/'.
+
+
+ %I
+ => complete filename and path of the temporary input file
+ (the intermediate net file).
+
+
+ %O
+ => complete filename and path (but without extension) of the user
+ chosen output file.
+
+
+%I
+will be replaced by the actual intermediate file name(usually
+the full root sheet filename with extension “.xml”) %O
+will
+be replaced by the actual output file name (the full root sheet
+filename minus extension). %B
+will
+be replaced by the actual output short file name
+(the
+short root sheet filename minus extension). %P
+will
+be replaced by the actual current project path.
+
4.3 - Command line format:
+
4.3.1 - Remark:
+
+Most
+of time, the created file must have an extension, depending on its
+type. Therefore you have to add to the option %O the
+right file extension.
+
+For
+instance:
+
+
+
+ %O.csv
+ to create a .csv file (comma separated value file).
+
+
+ %O.html
+ to create a .html file.
+
+
+ %O.bom
+ to create a .bom file.
+
+
4.3.2 Example forxsltproc:
+
+The
+command line format for xsltproc is the following: < path of
+xsltproc > xsltproc
+< xsltproc parameters >